text: 'use strict';
  
  Object.defineProperty(exports, '__esModule', { value: true });
  
  /*! *****************************************************************************
  Copyright (c) Microsoft Corporation.
  
  Permission to use, copy, modify, and/or distribute this software for any
  purpose with or without fee is hereby granted.
  
  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  PERFORMANCE OF THIS SOFTWARE.
  ***************************************************************************** */
  /* global Reflect, Promise */
  
  var extendStatics = function(d, b) {
      extendStatics = Object.setPrototypeOf ||
          ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
          function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
      return extendStatics(d, b);
  };
  
  function __extends(d, b) {
      extendStatics(d, b);
      function __() { this.constructor = d; }
      d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  }
  
  var __assign = function() {
      __assign = Object.assign || function __assign(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 __rest(s, e) {
      var t = {};
      for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
          t[p] = s[p];
      if (s != null && typeof Object.getOwnPropertySymbols === "function")
          for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
              if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                  t[p[i]] = s[p[i]];
          }
      return t;
  }
  
  function __awaiter(thisArg, _arguments, P, generator) {
      function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
      return new (P || (P = Promise))(function (resolve, reject) {
          function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
          function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
          function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
          step((generator = generator.apply(thisArg, _arguments || [])).next());
      });
  }
  
  function __generator(thisArg, body) {
      var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
      return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
      function verb(n) { return function (v) { return step([n, v]); }; }
      function step(op) {
          if (f) throw new TypeError("Generator is already executing.");
          while (_) try {
              if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
              if (y = 0, t) op = [op[0] & 2, t.value];
              switch (op[0]) {
                  case 0: case 1: t = op; break;
                  case 4: _.label++; return { value: op[1], done: false };
                  case 5: _.label++; y = op[1]; op = [0]; continue;
                  case 7: op = _.ops.pop(); _.trys.pop(); continue;
                  default:
                      if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                      if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                      if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                      if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                      if (t[2]) _.ops.pop();
                      _.trys.pop(); continue;
              }
              op = body.call(thisArg, _);
          } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
          if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
      }
  }
  
  function __spreadArrays() {
      for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
      for (var r = Array(s), k = 0, i = 0; i < il; i++)
          for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
              r[k] = a[j];
      return r;
  }
  
  var nodejsCustomInspectSymbol = typeof Symbol === 'function' && typeof Symbol.for === 'function' ? Symbol.for('nodejs.util.inspect.custom') : undefined;
  
  function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
  var MAX_ARRAY_LENGTH = 10;
  var MAX_RECURSIVE_DEPTH = 2;
  /**
   * Used to print values in error messages.
   */
  
  function inspect(value) {
    return formatValue(value, []);
  }
  
  function formatValue(value, seenValues) {
    switch (_typeof(value)) {
      case 'string':
        return JSON.stringify(value);
  
      case 'function':
        return value.name ? "[function ".concat(value.name, "]") : '[function]';
  
      case 'object':
        if (value === null) {
          return 'null';
        }
  
        return formatObjectValue(value, seenValues);
  
      default:
        return String(value);
    }
  }
  
  function formatObjectValue(value, previouslySeenValues) {
    if (previouslySeenValues.indexOf(value) !== -1) {
      return '[Circular]';
    }
  
    var seenValues = [].concat(previouslySeenValues, [value]);
    var customInspectFn = getCustomFn(value);
  
    if (customInspectFn !== undefined) {
      // $FlowFixMe(>=0.90.0)
      var customValue = customInspectFn.call(value); // check for infinite recursion
  
      if (customValue !== value) {
        return typeof customValue === 'string' ? customValue : formatValue(customValue, seenValues);
      }
    } else if (Array.isArray(value)) {
      return formatArray(value, seenValues);
    }
  
    return formatObject(value, seenValues);
  }
  
  function formatObject(object, seenValues) {
    var keys = Object.keys(object);
  
    if (keys.length === 0) {
      return '{}';
    }
  
    if (seenValues.length > MAX_RECURSIVE_DEPTH) {
      return '[' + getObjectTag(object) + ']';
    }
  
    var properties = keys.map(function (key) {
      var value = formatValue(object[key], seenValues);
      return key + ': ' + value;
    });
    return '{ ' + properties.join(', ') + ' }';
  }
  
  function formatArray(array, seenValues) {
    if (array.length === 0) {
      return '[]';
    }
  
    if (seenValues.length > MAX_RECURSIVE_DEPTH) {
      return '[Array]';
    }
  
    var len = Math.min(MAX_ARRAY_LENGTH, array.length);
    var remaining = array.length - len;
    var items = [];
  
    for (var i = 0; i < len; ++i) {
      items.push(formatValue(array[i], seenValues));
    }
  
    if (remaining === 1) {
      items.push('... 1 more item');
    } else if (remaining > 1) {
      items.push("... ".concat(remaining, " more items"));
    }
  
    return '[' + items.join(', ') + ']';
  }
  
  function getCustomFn(object) {
    var customInspectFn = object[String(nodejsCustomInspectSymbol)];
  
    if (typeof customInspectFn === 'function') {
      return customInspectFn;
    }
  
    if (typeof object.inspect === 'function') {
      return object.inspect;
    }
  }
  
  function getObjectTag(object) {
    var tag = Object.prototype.toString.call(object).replace(/^\[object /, '').replace(/]$/, '');
  
    if (tag === 'Object' && typeof object.constructor === 'function') {
      var name = object.constructor.name;
  
      if (typeof name === 'string' && name !== '') {
        return name;
      }
    }
  
    return tag;
  }
  
  function devAssert(condition, message) {
    var booleanCondition = Boolean(condition);
  
    if (!booleanCondition) {
      throw new Error(message);
    }
  }
  
  /**
   * The `defineToJSON()` function defines toJSON() and inspect() prototype
   * methods, if no function provided they become aliases for toString().
   */
  
  function defineToJSON(classObject) {
    var fn = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : classObject.prototype.toString;
    classObject.prototype.toJSON = fn;
    classObject.prototype.inspect = fn;
  
    if (nodejsCustomInspectSymbol) {
      classObject.prototype[nodejsCustomInspectSymbol] = fn;
    }
  }
  
  function _typeof$1(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof$1 = function _typeof(obj) { return typeof obj; }; } else { _typeof$1 = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof$1(obj); }
  
  /**
   * Return true if `value` is object-like. A value is object-like if it's not
   * `null` and has a `typeof` result of "object".
   */
  function isObjectLike(value) {
    return _typeof$1(value) == 'object' && value !== null;
  }
  
  /**
   * Represents a location in a Source.
   */
  
  /**
   * Takes a Source and a UTF-8 character offset, and returns the corresponding
   * line and column as a SourceLocation.
   */
  function getLocation(source, position) {
    var lineRegexp = /\r\n|[\n\r]/g;
    var line = 1;
    var column = position + 1;
    var match;
  
    while ((match = lineRegexp.exec(source.body)) && match.index < position) {
      line += 1;
      column = position + 1 - (match.index + match[0].length);
    }
  
    return {
      line: line,
      column: column
    };
  }
  
  /**
   * Render a helpful description of the location in the GraphQL Source document.
   */
  
  function printLocation(location) {
    return printSourceLocation(location.source, getLocation(location.source, location.start));
  }
  /**
   * Render a helpful description of the location in the GraphQL Source document.
   */
  
  function printSourceLocation(source, sourceLocation) {
    var firstLineColumnOffset = source.locationOffset.column - 1;
    var body = whitespace(firstLineColumnOffset) + source.body;
    var lineIndex = sourceLocation.line - 1;
    var lineOffset = source.locationOffset.line - 1;
    var lineNum = sourceLocation.line + lineOffset;
    var columnOffset = sourceLocation.line === 1 ? firstLineColumnOffset : 0;
    var columnNum = sourceLocation.column + columnOffset;
    var locationStr = "".concat(source.name, ":").concat(lineNum, ":").concat(columnNum, "\n");
    var lines = body.split(/\r\n|[\n\r]/g);
    var locationLine = lines[lineIndex]; // Special case for minified documents
  
    if (locationLine.length > 120) {
      var sublineIndex = Math.floor(columnNum / 80);
      var sublineColumnNum = columnNum % 80;
      var sublines = [];
  
      for (var i = 0; i < locationLine.length; i += 80) {
        sublines.push(locationLine.slice(i, i + 80));
      }
  
      return locationStr + printPrefixedLines([["".concat(lineNum), sublines[0]]].concat(sublines.slice(1, sublineIndex + 1).map(function (subline) {
        return ['', subline];
      }), [[' ', whitespace(sublineColumnNum - 1) + '^'], ['', sublines[sublineIndex + 1]]]));
    }
  
    return locationStr + printPrefixedLines([// Lines specified like this: ["prefix", "string"],
    ["".concat(lineNum - 1), lines[lineIndex - 1]], ["".concat(lineNum), locationLine], ['', whitespace(columnNum - 1) + '^'], ["".concat(lineNum + 1), lines[lineIndex + 1]]]);
  }
  
  function printPrefixedLines(lines) {
    var existingLines = lines.filter(function (_ref) {
      _ref[0];
          var line = _ref[1];
      return line !== undefined;
    });
    var padLen = Math.max.apply(Math, existingLines.map(function (_ref2) {
      var prefix = _ref2[0];
      return prefix.length;
    }));
    return existingLines.map(function (_ref3) {
      var prefix = _ref3[0],
          line = _ref3[1];
      return lpad(padLen, prefix) + (line ? ' | ' + line : ' |');
    }).join('\n');
  }
  
  function whitespace(len) {
    return Array(len + 1).join(' ');
  }
  
  function lpad(len, str) {
    return whitespace(len - str.length) + str;
  }
  
  /**
   * A GraphQLError describes an Error found during the parse, validate, or
   * execute phases of performing a GraphQL operation. In addition to a message
   * and stack trace, it also includes information about the locations in a
   * GraphQL document and/or execution result that correspond to the Error.
   */
  
  function GraphQLError( // eslint-disable-line no-redeclare
  message, nodes, source, positions, path, originalError, extensions) {
    // Compute list of blame nodes.
    var _nodes = Array.isArray(nodes) ? nodes.length !== 0 ? nodes : undefined : nodes ? [nodes] : undefined; // Compute locations in the source for the given nodes/positions.
  
  
    var _source = source;
  
    if (!_source && _nodes) {
      var node = _nodes[0];
      _source = node && node.loc && node.loc.source;
    }
  
    var _positions = positions;
  
    if (!_positions && _nodes) {
      _positions = _nodes.reduce(function (list, node) {
        if (node.loc) {
          list.push(node.loc.start);
        }
  
        return list;
      }, []);
    }
  
    if (_positions && _positions.length === 0) {
      _positions = undefined;
    }
  
    var _locations;
  
    if (positions && source) {
      _locations = positions.map(function (pos) {
        return getLocation(source, pos);
      });
    } else if (_nodes) {
      _locations = _nodes.reduce(function (list, node) {
        if (node.loc) {
          list.push(getLocation(node.loc.source, node.loc.start));
        }
  
        return list;
      }, []);
    }
  
    var _extensions = extensions;
  
    if (_extensions == null && originalError != null) {
      var originalExtensions = originalError.extensions;
  
      if (isObjectLike(originalExtensions)) {
        _extensions = originalExtensions;
      }
    }
  
    Object.defineProperties(this, {
      message: {
        value: message,
        // By being enumerable, JSON.stringify will include `message` in the
        // resulting output. This ensures that the simplest possible GraphQL
        // service adheres to the spec.
        enumerable: true,
        writable: true
      },
      locations: {
        // Coercing falsey values to undefined ensures they will not be included
        // in JSON.stringify() when not provided.
        value: _locations || undefined,
        // By being enumerable, JSON.stringify will include `locations` in the
        // resulting output. This ensures that the simplest possible GraphQL
        // service adheres to the spec.
        enumerable: Boolean(_locations)
      },
      path: {
        // Coercing falsey values to undefined ensures they will not be included
        // in JSON.stringify() when not provided.
        value: path || undefined,
        // By being enumerable, JSON.stringify will include `path` in the
        // resulting output. This ensures that the simplest possible GraphQL
        // service adheres to the spec.
        enumerable: Boolean(path)
      },
      nodes: {
        value: _nodes || undefined
      },
      source: {
        value: _source || undefined
      },
      positions: {
        value: _positions || undefined
      },
      originalError: {
        value: originalError
      },
      extensions: {
        // Coercing falsey values to undefined ensures they will not be included
        // in JSON.stringify() when not provided.
        value: _extensions || undefined,
        // By being enumerable, JSON.stringify will include `path` in the
        // resulting output. This ensures that the simplest possible GraphQL
        // service adheres to the spec.
        enumerable: Boolean(_extensions)
      }
    }); // Include (non-enumerable) stack trace.
  
    if (originalError && originalError.stack) {
      Object.defineProperty(this, 'stack', {
        value: originalError.stack,
        writable: true,
        configurable: true
      });
    } else if (Error.captureStackTrace) {
      Error.captureStackTrace(this, GraphQLError);
    } else {
      Object.defineProperty(this, 'stack', {
        value: Error().stack,
        writable: true,
        configurable: true
      });
    }
  }
  GraphQLError.prototype = Object.create(Error.prototype, {
    constructor: {
      value: GraphQLError
    },
    name: {
      value: 'GraphQLError'
    },
    toString: {
      value: function toString() {
        return printError(this);
      }
    }
  });
  /**
   * Prints a GraphQLError to a string, representing useful location information
   * about the error's position in the source.
   */
  
  function printError(error) {
    var output = error.message;
  
    if (error.nodes) {
      for (var _i2 = 0, _error$nodes2 = error.nodes; _i2 < _error$nodes2.length; _i2++) {
        var node = _error$nodes2[_i2];
  
        if (node.loc) {
          output += '\n\n' + printLocation(node.loc);
        }
      }
    } else if (error.source && error.locations) {
      for (var _i4 = 0, _error$locations2 = error.locations; _i4 < _error$locations2.length; _i4++) {
        var location = _error$locations2[_i4];
        output += '\n\n' + printSourceLocation(error.source, location);
      }
    }
  
    return output;
  }
  
  /**
   * Produces a GraphQLError representing a syntax error, containing useful
   * descriptive information about the syntax error's position in the source.
   */
  
  function syntaxError(source, position, description) {
    return new GraphQLError("Syntax Error: ".concat(description), undefined, source, [position]);
  }
  
  /**
   * The set of allowed kind values for AST nodes.
   */
  var Kind = Object.freeze({
    // Name
    NAME: 'Name',
    // Document
    DOCUMENT: 'Document',
    OPERATION_DEFINITION: 'OperationDefinition',
    VARIABLE_DEFINITION: 'VariableDefinition',
    SELECTION_SET: 'SelectionSet',
    FIELD: 'Field',
    ARGUMENT: 'Argument',
    // Fragments
    FRAGMENT_SPREAD: 'FragmentSpread',
    INLINE_FRAGMENT: 'InlineFragment',
    FRAGMENT_DEFINITION: 'FragmentDefinition',
    // Values
    VARIABLE: 'Variable',
    INT: 'IntValue',
    FLOAT: 'FloatValue',
    STRING: 'StringValue',
    BOOLEAN: 'BooleanValue',
    NULL: 'NullValue',
    ENUM: 'EnumValue',
    LIST: 'ListValue',
    OBJECT: 'ObjectValue',
    OBJECT_FIELD: 'ObjectField',
    // Directives
    DIRECTIVE: 'Directive',
    // Types
    NAMED_TYPE: 'NamedType',
    LIST_TYPE: 'ListType',
    NON_NULL_TYPE: 'NonNullType',
    // Type System Definitions
    SCHEMA_DEFINITION: 'SchemaDefinition',
    OPERATION_TYPE_DEFINITION: 'OperationTypeDefinition',
    // Type Definitions
    SCALAR_TYPE_DEFINITION: 'ScalarTypeDefinition',
    OBJECT_TYPE_DEFINITION: 'ObjectTypeDefinition',
    FIELD_DEFINITION: 'FieldDefinition',
    INPUT_VALUE_DEFINITION: 'InputValueDefinition',
    INTERFACE_TYPE_DEFINITION: 'InterfaceTypeDefinition',
    UNION_TYPE_DEFINITION: 'UnionTypeDefinition',
    ENUM_TYPE_DEFINITION: 'EnumTypeDefinition',
    ENUM_VALUE_DEFINITION: 'EnumValueDefinition',
    INPUT_OBJECT_TYPE_DEFINITION: 'InputObjectTypeDefinition',
    // Directive Definitions
    DIRECTIVE_DEFINITION: 'DirectiveDefinition',
    // Type System Extensions
    SCHEMA_EXTENSION: 'SchemaExtension',
    // Type Extensions
    SCALAR_TYPE_EXTENSION: 'ScalarTypeExtension',
    OBJECT_TYPE_EXTENSION: 'ObjectTypeExtension',
    INTERFACE_TYPE_EXTENSION: 'InterfaceTypeExtension',
    UNION_TYPE_EXTENSION: 'UnionTypeExtension',
    ENUM_TYPE_EXTENSION: 'EnumTypeExtension',
    INPUT_OBJECT_TYPE_EXTENSION: 'InputObjectTypeExtension'
  });
  /**
   * The enum type representing the possible kind values of AST nodes.
   */
  
  /**
   * The `defineToStringTag()` function checks first to see if the runtime
   * supports the `Symbol` class and then if the `Symbol.toStringTag` constant
   * is defined as a `Symbol` instance. If both conditions are met, the
   * Symbol.toStringTag property is defined as a getter that returns the
   * supplied class constructor's name.
   *
   * @method defineToStringTag
   *
   * @param {Class<any>} classObject a class such as Object, String, Number but
   * typically one of your own creation through the class keyword; `class A {}`,
   * for example.
   */
  function defineToStringTag(classObject) {
    if (typeof Symbol === 'function' && Symbol.toStringTag) {
      Object.defineProperty(classObject.prototype, Symbol.toStringTag, {
        get: function get() {
          return this.constructor.name;
        }
      });
    }
  }
  
  /**
   * A representation of source input to GraphQL.
   * `name` and `locationOffset` are optional. They are useful for clients who
   * store GraphQL documents in source files; for example, if the GraphQL input
   * starts at line 40 in a file named Foo.graphql, it might be useful for name to
   * be "Foo.graphql" and location to be `{ line: 40, column: 0 }`.
   * line and column in locationOffset are 1-indexed
   */
  var Source = function Source(body, name, locationOffset) {
    this.body = body;
    this.name = name || 'GraphQL request';
    this.locationOffset = locationOffset || {
      line: 1,
      column: 1
    };
    this.locationOffset.line > 0 || devAssert(0, 'line in locationOffset is 1-indexed and must be positive');
    this.locationOffset.column > 0 || devAssert(0, 'column in locationOffset is 1-indexed and must be positive');
  }; // Conditionally apply `[Symbol.toStringTag]` if `Symbol`s are supported
  
  defineToStringTag(Source);
  
  /**
   * Produces the value of a block string from its parsed raw value, similar to
   * CoffeeScript's block string, Python's docstring trim or Ruby's strip_heredoc.
   *
   * This implements the GraphQL spec's BlockStringValue() static algorithm.
   */
  function dedentBlockStringValue(rawString) {
    // Expand a block string's raw value into independent lines.
    var lines = rawString.split(/\r\n|[\n\r]/g); // Remove common indentation from all lines but first.
  
    var commonIndent = getBlockStringIndentation(lines);
  
    if (commonIndent !== 0) {
      for (var i = 1; i < lines.length; i++) {
        lines[i] = lines[i].slice(commonIndent);
      }
    } // Remove leading and trailing blank lines.
  
  
    while (lines.length > 0 && isBlank(lines[0])) {
      lines.shift();
    }
  
    while (lines.length > 0 && isBlank(lines[lines.length - 1])) {
      lines.pop();
    } // Return a string of the lines joined with U+000A.
  
  
    return lines.join('\n');
  } // @internal
  
  function getBlockStringIndentation(lines) {
    var commonIndent = null;
  
    for (var i = 1; i < lines.length; i++) {
      var line = lines[i];
      var indent = leadingWhitespace(line);
  
      if (indent === line.length) {
        continue; // skip empty lines
      }
  
      if (commonIndent === null || indent < commonIndent) {
        commonIndent = indent;
  
        if (commonIndent === 0) {
          break;
        }
      }
    }
  
    return commonIndent === null ? 0 : commonIndent;
  }
  
  function leadingWhitespace(str) {
    var i = 0;
  
    while (i < str.length && (str[i] === ' ' || str[i] === '\t')) {
      i++;
    }
  
    return i;
  }
  
  function isBlank(str) {
    return leadingWhitespace(str) === str.length;
  }
  /**
   * Print a block string in the indented block form by adding a leading and
   * trailing blank line. However, if a block string starts with whitespace and is
   * a single-line, adding a leading blank line would strip that whitespace.
   */
  
  
  function printBlockString(value) {
    var indentation = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
    var preferMultipleLines = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
    var isSingleLine = value.indexOf('\n') === -1;
    var hasLeadingSpace = value[0] === ' ' || value[0] === '\t';
    var hasTrailingQuote = value[value.length - 1] === '"';
    var printAsMultipleLines = !isSingleLine || hasTrailingQuote || preferMultipleLines;
    var result = ''; // Format a multi-line block quote to account for leading space.
  
    if (printAsMultipleLines && !(isSingleLine && hasLeadingSpace)) {
      result += '\n' + indentation;
    }
  
    result += indentation ? value.replace(/\n/g, '\n' + indentation) : value;
  
    if (printAsMultipleLines) {
      result += '\n';
    }
  
    return '"""' + result.replace(/"""/g, '\\"""') + '"""';
  }
  
  /**
   * An exported enum describing the different kinds of tokens that the
   * lexer emits.
   */
  var TokenKind = Object.freeze({
    SOF: '<SOF>',
    EOF: '<EOF>',
    BANG: '!',
    DOLLAR: '$',
    AMP: '&',
    PAREN_L: '(',
    PAREN_R: ')',
    SPREAD: '...',
    COLON: ':',
    EQUALS: '=',
    AT: '@',
    BRACKET_L: '[',
    BRACKET_R: ']',
    BRACE_L: '{',
    PIPE: '|',
    BRACE_R: '}',
    NAME: 'Name',
    INT: 'Int',
    FLOAT: 'Float',
    STRING: 'String',
    BLOCK_STRING: 'BlockString',
    COMMENT: 'Comment'
  });
  /**
   * The enum type representing the token kinds values.
   */
  
  /**
   * Given a Source object, this returns a Lexer for that source.
   * A Lexer is a stateful stream generator in that every time
   * it is advanced, it returns the next token in the Source. Assuming the
   * source lexes, the final Token emitted by the lexer will be of kind
   * EOF, after which the lexer will repeatedly return the same EOF token
   * whenever called.
   */
  
  function createLexer(source, options) {
    var startOfFileToken = new Tok(TokenKind.SOF, 0, 0, 0, 0, null);
    var lexer = {
      source: source,
      options: options,
      lastToken: startOfFileToken,
      token: startOfFileToken,
      line: 1,
      lineStart: 0,
      advance: advanceLexer,
      lookahead: lookahead
    };
    return lexer;
  }
  
  function advanceLexer() {
    this.lastToken = this.token;
    var token = this.token = this.lookahead();
    return token;
  }
  
  function lookahead() {
    var token = this.token;
  
    if (token.kind !== TokenKind.EOF) {
      do {
        // Note: next is only mutable during parsing, so we cast to allow this.
        token = token.next || (token.next = readToken(this, token));
      } while (token.kind === TokenKind.COMMENT);
    }
  
    return token;
  }
  /**
   * Helper function for constructing the Token object.
   */
  
  function Tok(kind, start, end, line, column, prev, value) {
    this.kind = kind;
    this.start = start;
    this.end = end;
    this.line = line;
    this.column = column;
    this.value = value;
    this.prev = prev;
    this.next = null;
  } // Print a simplified form when appearing in JSON/util.inspect.
  
  
  defineToJSON(Tok, function () {
    return {
      kind: this.kind,
      value: this.value,
      line: this.line,
      column: this.column
    };
  });
  
  function printCharCode(code) {
    return (// NaN/undefined represents access beyond the end of the file.
      isNaN(code) ? TokenKind.EOF : // Trust JSON for ASCII.
      code < 0x007f ? JSON.stringify(String.fromCharCode(code)) : // Otherwise print the escaped form.
      "\"\\u".concat(('00' + code.toString(16).toUpperCase()).slice(-4), "\"")
    );
  }
  /**
   * Gets the next token from the source starting at the given position.
   *
   * This skips over whitespace until it finds the next lexable token, then lexes
   * punctuators immediately or calls the appropriate helper function for more
   * complicated tokens.
   */
  
  
  function readToken(lexer, prev) {
    var source = lexer.source;
    var body = source.body;
    var bodyLength = body.length;
    var pos = positionAfterWhitespace(body, prev.end, lexer);
    var line = lexer.line;
    var col = 1 + pos - lexer.lineStart;
  
    if (pos >= bodyLength) {
      return new Tok(TokenKind.EOF, bodyLength, bodyLength, line, col, prev);
    }
  
    var code = body.charCodeAt(pos); // SourceCharacter
  
    switch (code) {
      // !
      case 33:
        return new Tok(TokenKind.BANG, pos, pos + 1, line, col, prev);
      // #
  
      case 35:
        return readComment(source, pos, line, col, prev);
      // $
  
      case 36:
        return new Tok(TokenKind.DOLLAR, pos, pos + 1, line, col, prev);
      // &
  
      case 38:
        return new Tok(TokenKind.AMP, pos, pos + 1, line, col, prev);
      // (
  
      case 40:
        return new Tok(TokenKind.PAREN_L, pos, pos + 1, line, col, prev);
      // )
  
      case 41:
        return new Tok(TokenKind.PAREN_R, pos, pos + 1, line, col, prev);
      // .
  
      case 46:
        if (body.charCodeAt(pos + 1) === 46 && body.charCodeAt(pos + 2) === 46) {
          return new Tok(TokenKind.SPREAD, pos, pos + 3, line, col, prev);
        }
  
        break;
      // :
  
      case 58:
        return new Tok(TokenKind.COLON, pos, pos + 1, line, col, prev);
      // =
  
      case 61:
        return new Tok(TokenKind.EQUALS, pos, pos + 1, line, col, prev);
      // @
  
      case 64:
        return new Tok(TokenKind.AT, pos, pos + 1, line, col, prev);
      // [
  
      case 91:
        return new Tok(TokenKind.BRACKET_L, pos, pos + 1, line, col, prev);
      // ]
  
      case 93:
        return new Tok(TokenKind.BRACKET_R, pos, pos + 1, line, col, prev);
      // {
  
      case 123:
        return new Tok(TokenKind.BRACE_L, pos, pos + 1, line, col, prev);
      // |
  
      case 124:
        return new Tok(TokenKind.PIPE, pos, pos + 1, line, col, prev);
      // }
  
      case 125:
        return new Tok(TokenKind.BRACE_R, pos, pos + 1, line, col, prev);
      // A-Z _ a-z
  
      case 65:
      case 66:
      case 67:
      case 68:
      case 69:
      case 70:
      case 71:
      case 72:
      case 73:
      case 74:
      case 75:
      case 76:
      case 77:
      case 78:
      case 79:
      case 80:
      case 81:
      case 82:
      case 83:
      case 84:
      case 85:
      case 86:
      case 87:
      case 88:
      case 89:
      case 90:
      case 95:
      case 97:
      case 98:
      case 99:
      case 100:
      case 101:
      case 102:
      case 103:
      case 104:
      case 105:
      case 106:
      case 107:
      case 108:
      case 109:
      case 110:
      case 111:
      case 112:
      case 113:
      case 114:
      case 115:
      case 116:
      case 117:
      case 118:
      case 119:
      case 120:
      case 121:
      case 122:
        return readName(source, pos, line, col, prev);
      // - 0-9
  
      case 45:
      case 48:
      case 49:
      case 50:
      case 51:
      case 52:
      case 53:
      case 54:
      case 55:
      case 56:
      case 57:
        return readNumber(source, pos, code, line, col, prev);
      // "
  
      case 34:
        if (body.charCodeAt(pos + 1) === 34 && body.charCodeAt(pos + 2) === 34) {
          return readBlockString(source, pos, line, col, prev, lexer);
        }
  
        return readString(source, pos, line, col, prev);
    }
  
    throw syntaxError(source, pos, unexpectedCharacterMessage(code));
  }
  /**
   * Report a message that an unexpected character was encountered.
   */
  
  
  function unexpectedCharacterMessage(code) {
    if (code < 0x0020 && code !== 0x0009 && code !== 0x000a && code !== 0x000d) {
      return "Cannot contain the invalid character ".concat(printCharCode(code), ".");
    }
  
    if (code === 39) {
      // '
      return 'Unexpected single quote character (\'), did you mean to use a double quote (")?';
    }
  
    return "Cannot parse the unexpected character ".concat(printCharCode(code), ".");
  }
  /**
   * Reads from body starting at startPosition until it finds a non-whitespace
   * character, then returns the position of that character for lexing.
   */
  
  
  function positionAfterWhitespace(body, startPosition, lexer) {
    var bodyLength = body.length;
    var position = startPosition;
  
    while (position < bodyLength) {
      var code = body.charCodeAt(position); // tab | space | comma | BOM
  
      if (code === 9 || code === 32 || code === 44 || code === 0xfeff) {
        ++position;
      } else if (code === 10) {
        // new line
        ++position;
        ++lexer.line;
        lexer.lineStart = position;
      } else if (code === 13) {
        // carriage return
        if (body.charCodeAt(position + 1) === 10) {
          position += 2;
        } else {
          ++position;
        }
  
        ++lexer.line;
        lexer.lineStart = position;
      } else {
        break;
      }
    }
  
    return position;
  }
  /**
   * Reads a comment token from the source file.
   *
   * #[\u0009\u0020-\uFFFF]*
   */
  
  
  function readComment(source, start, line, col, prev) {
    var body = source.body;
    var code;
    var position = start;
  
    do {
      code = body.charCodeAt(++position);
    } while (!isNaN(code) && ( // SourceCharacter but not LineTerminator
    code > 0x001f || code === 0x0009));
  
    return new Tok(TokenKind.COMMENT, start, position, line, col, prev, body.slice(start + 1, position));
  }
  /**
   * Reads a number token from the source file, either a float
   * or an int depending on whether a decimal point appears.
   *
   * Int:   -?(0|[1-9][0-9]*)
   * Float: -?(0|[1-9][0-9]*)(\.[0-9]+)?((E|e)(+|-)?[0-9]+)?
   */
  
  
  function readNumber(source, start, firstCode, line, col, prev) {
    var body = source.body;
    var code = firstCode;
    var position = start;
    var isFloat = false;
  
    if (code === 45) {
      // -
      code = body.charCodeAt(++position);
    }
  
    if (code === 48) {
      // 0
      code = body.charCodeAt(++position);
  
      if (code >= 48 && code <= 57) {
        throw syntaxError(source, position, "Invalid number, unexpected digit after 0: ".concat(printCharCode(code), "."));
      }
    } else {
      position = readDigits(source, position, code);
      code = body.charCodeAt(position);
    }
  
    if (code === 46) {
      // .
      isFloat = true;
      code = body.charCodeAt(++position);
      position = readDigits(source, position, code);
      code = body.charCodeAt(position);
    }
  
    if (code === 69 || code === 101) {
      // E e
      isFloat = true;
      code = body.charCodeAt(++position);
  
      if (code === 43 || code === 45) {
        // + -
        code = body.charCodeAt(++position);
      }
  
      position = readDigits(source, position, code);
      code = body.charCodeAt(position);
    } // Numbers cannot be followed by . or e
  
  
    if (code === 46 || code === 69 || code === 101) {
      throw syntaxError(source, position, "Invalid number, expected digit but got: ".concat(printCharCode(code), "."));
    }
  
    return new Tok(isFloat ? TokenKind.FLOAT : TokenKind.INT, start, position, line, col, prev, body.slice(start, position));
  }
  /**
   * Returns the new position in the source after reading digits.
   */
  
  
  function readDigits(source, start, firstCode) {
    var body = source.body;
    var position = start;
    var code = firstCode;
  
    if (code >= 48 && code <= 57) {
      // 0 - 9
      do {
        code = body.charCodeAt(++position);
      } while (code >= 48 && code <= 57); // 0 - 9
  
  
      return position;
    }
  
    throw syntaxError(source, position, "Invalid number, expected digit but got: ".concat(printCharCode(code), "."));
  }
  /**
   * Reads a string token from the source file.
   *
   * "([^"\\\u000A\u000D]|(\\(u[0-9a-fA-F]{4}|["\\/bfnrt])))*"
   */
  
  
  function readString(source, start, line, col, prev) {
    var body = source.body;
    var position = start + 1;
    var chunkStart = position;
    var code = 0;
    var value = '';
  
    while (position < body.length && !isNaN(code = body.charCodeAt(position)) && // not LineTerminator
    code !== 0x000a && code !== 0x000d) {
      // Closing Quote (")
      if (code === 34) {
        value += body.slice(chunkStart, position);
        return new Tok(TokenKind.STRING, start, position + 1, line, col, prev, value);
      } // SourceCharacter
  
  
      if (code < 0x0020 && code !== 0x0009) {
        throw syntaxError(source, position, "Invalid character within String: ".concat(printCharCode(code), "."));
      }
  
      ++position;
  
      if (code === 92) {
        // \
        value += body.slice(chunkStart, position - 1);
        code = body.charCodeAt(position);
  
        switch (code) {
          case 34:
            value += '"';
            break;
  
          case 47:
            value += '/';
            break;
  
          case 92:
            value += '\\';
            break;
  
          case 98:
            value += '\b';
            break;
  
          case 102:
            value += '\f';
            break;
  
          case 110:
            value += '\n';
            break;
  
          case 114:
            value += '\r';
            break;
  
          case 116:
            value += '\t';
            break;
  
          case 117:
            {
              // uXXXX
              var charCode = uniCharCode(body.charCodeAt(position + 1), body.charCodeAt(position + 2), body.charCodeAt(position + 3), body.charCodeAt(position + 4));
  
              if (charCode < 0) {
                var invalidSequence = body.slice(position + 1, position + 5);
                throw syntaxError(source, position, "Invalid character escape sequence: \\u".concat(invalidSequence, "."));
              }
  
              value += String.fromCharCode(charCode);
              position += 4;
              break;
            }
  
          default:
            throw syntaxError(source, position, "Invalid character escape sequence: \\".concat(String.fromCharCode(code), "."));
        }
  
        ++position;
        chunkStart = position;
      }
    }
  
    throw syntaxError(source, position, 'Unterminated string.');
  }
  /**
   * Reads a block string token from the source file.
   *
   * """("?"?(\\"""|\\(?!=""")|[^"\\]))*"""
   */
  
  
  function readBlockString(source, start, line, col, prev, lexer) {
    var body = source.body;
    var position = start + 3;
    var chunkStart = position;
    var code = 0;
    var rawValue = '';
  
    while (position < body.length && !isNaN(code = body.charCodeAt(position))) {
      // Closing Triple-Quote (""")
      if (code === 34 && body.charCodeAt(position + 1) === 34 && body.charCodeAt(position + 2) === 34) {
        rawValue += body.slice(chunkStart, position);
        return new Tok(TokenKind.BLOCK_STRING, start, position + 3, line, col, prev, dedentBlockStringValue(rawValue));
      } // SourceCharacter
  
  
      if (code < 0x0020 && code !== 0x0009 && code !== 0x000a && code !== 0x000d) {
        throw syntaxError(source, position, "Invalid character within String: ".concat(printCharCode(code), "."));
      }
  
      if (code === 10) {
        // new line
        ++position;
        ++lexer.line;
        lexer.lineStart = position;
      } else if (code === 13) {
        // carriage return
        if (body.charCodeAt(position + 1) === 10) {
          position += 2;
        } else {
          ++position;
        }
  
        ++lexer.line;
        lexer.lineStart = position;
      } else if ( // Escape Triple-Quote (\""")
      code === 92 && body.charCodeAt(position + 1) === 34 && body.charCodeAt(position + 2) === 34 && body.charCodeAt(position + 3) === 34) {
        rawValue += body.slice(chunkStart, position) + '"""';
        position += 4;
        chunkStart = position;
      } else {
        ++position;
      }
    }
  
    throw syntaxError(source, position, 'Unterminated string.');
  }
  /**
   * Converts four hexadecimal chars to the integer that the
   * string represents. For example, uniCharCode('0','0','0','f')
   * will return 15, and uniCharCode('0','0','f','f') returns 255.
   *
   * Returns a negative number on error, if a char was invalid.
   *
   * This is implemented by noting that char2hex() returns -1 on error,
   * which means the result of ORing the char2hex() will also be negative.
   */
  
  
  function uniCharCode(a, b, c, d) {
    return char2hex(a) << 12 | char2hex(b) << 8 | char2hex(c) << 4 | char2hex(d);
  }
  /**
   * Converts a hex character to its integer value.
   * '0' becomes 0, '9' becomes 9
   * 'A' becomes 10, 'F' becomes 15
   * 'a' becomes 10, 'f' becomes 15
   *
   * Returns -1 on error.
   */
  
  
  function char2hex(a) {
    return a >= 48 && a <= 57 ? a - 48 // 0-9
    : a >= 65 && a <= 70 ? a - 55 // A-F
    : a >= 97 && a <= 102 ? a - 87 // a-f
    : -1;
  }
  /**
   * Reads an alphanumeric + underscore name from the source.
   *
   * [_A-Za-z][_0-9A-Za-z]*
   */
  
  
  function readName(source, start, line, col, prev) {
    var body = source.body;
    var bodyLength = body.length;
    var position = start + 1;
    var code = 0;
  
    while (position !== bodyLength && !isNaN(code = body.charCodeAt(position)) && (code === 95 || // _
    code >= 48 && code <= 57 || // 0-9
    code >= 65 && code <= 90 || // A-Z
    code >= 97 && code <= 122) // a-z
    ) {
      ++position;
    }
  
    return new Tok(TokenKind.NAME, start, position, line, col, prev, body.slice(start, position));
  }
  
  /**
   * The set of allowed directive location values.
   */
  var DirectiveLocation = Object.freeze({
    // Request Definitions
    QUERY: 'QUERY',
    MUTATION: 'MUTATION',
    SUBSCRIPTION: 'SUBSCRIPTION',
    FIELD: 'FIELD',
    FRAGMENT_DEFINITION: 'FRAGMENT_DEFINITION',
    FRAGMENT_SPREAD: 'FRAGMENT_SPREAD',
    INLINE_FRAGMENT: 'INLINE_FRAGMENT',
    VARIABLE_DEFINITION: 'VARIABLE_DEFINITION',
    // Type System Definitions
    SCHEMA: 'SCHEMA',
    SCALAR: 'SCALAR',
    OBJECT: 'OBJECT',
    FIELD_DEFINITION: 'FIELD_DEFINITION',
    ARGUMENT_DEFINITION: 'ARGUMENT_DEFINITION',
    INTERFACE: 'INTERFACE',
    UNION: 'UNION',
    ENUM: 'ENUM',
    ENUM_VALUE: 'ENUM_VALUE',
    INPUT_OBJECT: 'INPUT_OBJECT',
    INPUT_FIELD_DEFINITION: 'INPUT_FIELD_DEFINITION'
  });
  /**
   * The enum type representing the directive location values.
   */
  
  /**
   * Given a GraphQL source, parses it into a Document.
   * Throws GraphQLError if a syntax error is encountered.
   */
  function parse(source, options) {
    var parser = new Parser(source, options);
    return parser.parseDocument();
  }
  /**
   * Given a string containing a GraphQL value (ex. `[42]`), parse the AST for
   * that value.
   * Throws GraphQLError if a syntax error is encountered.
   *
   * This is useful within tools that operate upon GraphQL Values directly and
   * in isolation of complete GraphQL documents.
   *
   * Consider providing the results to the utility function: valueFromAST().
   */
  
  function parseValue(source, options) {
    var parser = new Parser(source, options);
    parser.expectToken(TokenKind.SOF);
    var value = parser.parseValueLiteral(false);
    parser.expectToken(TokenKind.EOF);
    return value;
  }
  /**
   * Given a string containing a GraphQL Type (ex. `[Int!]`), parse the AST for
   * that type.
   * Throws GraphQLError if a syntax error is encountered.
   *
   * This is useful within tools that operate upon GraphQL Types directly and
   * in isolation of complete GraphQL documents.
   *
   * Consider providing the results to the utility function: typeFromAST().
   */
  
  function parseType(source, options) {
    var parser = new Parser(source, options);
    parser.expectToken(TokenKind.SOF);
    var type = parser.parseTypeReference();
    parser.expectToken(TokenKind.EOF);
    return type;
  }
  
  var Parser =
  /*#__PURE__*/
  function () {
    function Parser(source, options) {
      var sourceObj = typeof source === 'string' ? new Source(source) : source;
      sourceObj instanceof Source || devAssert(0, "Must provide Source. Received: ".concat(inspect(sourceObj)));
      this._lexer = createLexer(sourceObj);
      this._options = options || {};
    }
    /**
     * Converts a name lex token into a name parse node.
     */
  
  
    var _proto = Parser.prototype;
  
    _proto.parseName = function parseName() {
      var token = this.expectToken(TokenKind.NAME);
      return {
        kind: Kind.NAME,
        value: token.value,
        loc: this.loc(token)
      };
    } // Implements the parsing rules in the Document section.
  
    /**
     * Document : Definition+
     */
    ;
  
    _proto.parseDocument = function parseDocument() {
      var start = this._lexer.token;
      return {
        kind: Kind.DOCUMENT,
        definitions: this.many(TokenKind.SOF, this.parseDefinition, TokenKind.EOF),
        loc: this.loc(start)
      };
    }
    /**
     * Definition :
     *   - ExecutableDefinition
     *   - TypeSystemDefinition
     *   - TypeSystemExtension
     *
     * ExecutableDefinition :
     *   - OperationDefinition
     *   - FragmentDefinition
     */
    ;
  
    _proto.parseDefinition = function parseDefinition() {
      if (this.peek(TokenKind.NAME)) {
        switch (this._lexer.token.value) {
          case 'query':
          case 'mutation':
          case 'subscription':
            return this.parseOperationDefinition();
  
          case 'fragment':
            return this.parseFragmentDefinition();
  
          case 'schema':
          case 'scalar':
          case 'type':
          case 'interface':
          case 'union':
          case 'enum':
          case 'input':
          case 'directive':
            return this.parseTypeSystemDefinition();
  
          case 'extend':
            return this.parseTypeSystemExtension();
        }
      } else if (this.peek(TokenKind.BRACE_L)) {
        return this.parseOperationDefinition();
      } else if (this.peekDescription()) {
        return this.parseTypeSystemDefinition();
      }
  
      throw this.unexpected();
    } // Implements the parsing rules in the Operations section.
  
    /**
     * OperationDefinition :
     *  - SelectionSet
     *  - OperationType Name? VariableDefinitions? Directives? SelectionSet
     */
    ;
  
    _proto.parseOperationDefinition = function parseOperationDefinition() {
      var start = this._lexer.token;
  
      if (this.peek(TokenKind.BRACE_L)) {
        return {
          kind: Kind.OPERATION_DEFINITION,
          operation: 'query',
          name: undefined,
          variableDefinitions: [],
          directives: [],
          selectionSet: this.parseSelectionSet(),
          loc: this.loc(start)
        };
      }
  
      var operation = this.parseOperationType();
      var name;
  
      if (this.peek(TokenKind.NAME)) {
        name = this.parseName();
      }
  
      return {
        kind: Kind.OPERATION_DEFINITION,
        operation: operation,
        name: name,
        variableDefinitions: this.parseVariableDefinitions(),
        directives: this.parseDirectives(false),
        selectionSet: this.parseSelectionSet(),
        loc: this.loc(start)
      };
    }
    /**
     * OperationType : one of query mutation subscription
     */
    ;
  
    _proto.parseOperationType = function parseOperationType() {
      var operationToken = this.expectToken(TokenKind.NAME);
  
      switch (operationToken.value) {
        case 'query':
          return 'query';
  
        case 'mutation':
          return 'mutation';
  
        case 'subscription':
          return 'subscription';
      }
  
      throw this.unexpected(operationToken);
    }
    /**
     * VariableDefinitions : ( VariableDefinition+ )
     */
    ;
  
    _proto.parseVariableDefinitions = function parseVariableDefinitions() {
      return this.optionalMany(TokenKind.PAREN_L, this.parseVariableDefinition, TokenKind.PAREN_R);
    }
    /**
     * VariableDefinition : Variable : Type DefaultValue? Directives[Const]?
     */
    ;
  
    _proto.parseVariableDefinition = function parseVariableDefinition() {
      var start = this._lexer.token;
      return {
        kind: Kind.VARIABLE_DEFINITION,
        variable: this.parseVariable(),
        type: (this.expectToken(TokenKind.COLON), this.parseTypeReference()),
        defaultValue: this.expectOptionalToken(TokenKind.EQUALS) ? this.parseValueLiteral(true) : undefined,
        directives: this.parseDirectives(true),
        loc: this.loc(start)
      };
    }
    /**
     * Variable : $ Name
     */
    ;
  
    _proto.parseVariable = function parseVariable() {
      var start = this._lexer.token;
      this.expectToken(TokenKind.DOLLAR);
      return {
        kind: Kind.VARIABLE,
        name: this.parseName(),
        loc: this.loc(start)
      };
    }
    /**
     * SelectionSet : { Selection+ }
     */
    ;
  
    _proto.parseSelectionSet = function parseSelectionSet() {
      var start = this._lexer.token;
      return {
        kind: Kind.SELECTION_SET,
        selections: this.many(TokenKind.BRACE_L, this.parseSelection, TokenKind.BRACE_R),
        loc: this.loc(start)
      };
    }
    /**
     * Selection :
     *   - Field
     *   - FragmentSpread
     *   - InlineFragment
     */
    ;
  
    _proto.parseSelection = function parseSelection() {
      return this.peek(TokenKind.SPREAD) ? this.parseFragment() : this.parseField();
    }
    /**
     * Field : Alias? Name Arguments? Directives? SelectionSet?
     *
     * Alias : Name :
     */
    ;
  
    _proto.parseField = function parseField() {
      var start = this._lexer.token;
      var nameOrAlias = this.parseName();
      var alias;
      var name;
  
      if (this.expectOptionalToken(TokenKind.COLON)) {
        alias = nameOrAlias;
        name = this.parseName();
      } else {
        name = nameOrAlias;
      }
  
      return {
        kind: Kind.FIELD,
        alias: alias,
        name: name,
        arguments: this.parseArguments(false),
        directives: this.parseDirectives(false),
        selectionSet: this.peek(TokenKind.BRACE_L) ? this.parseSelectionSet() : undefined,
        loc: this.loc(start)
      };
    }
    /**
     * Arguments[Const] : ( Argument[?Const]+ )
     */
    ;
  
    _proto.parseArguments = function parseArguments(isConst) {
      var item = isConst ? this.parseConstArgument : this.parseArgument;
      return this.optionalMany(TokenKind.PAREN_L, item, TokenKind.PAREN_R);
    }
    /**
     * Argument[Const] : Name : Value[?Const]
     */
    ;
  
    _proto.parseArgument = function parseArgument() {
      var start = this._lexer.token;
      var name = this.parseName();
      this.expectToken(TokenKind.COLON);
      return {
        kind: Kind.ARGUMENT,
        name: name,
        value: this.parseValueLiteral(false),
        loc: this.loc(start)
      };
    };
  
    _proto.parseConstArgument = function parseConstArgument() {
      var start = this._lexer.token;
      return {
        kind: Kind.ARGUMENT,
        name: this.parseName(),
        value: (this.expectToken(TokenKind.COLON), this.parseValueLiteral(true)),
        loc: this.loc(start)
      };
    } // Implements the parsing rules in the Fragments section.
  
    /**
     * Corresponds to both FragmentSpread and InlineFragment in the spec.
     *
     * FragmentSpread : ... FragmentName Directives?
     *
     * InlineFragment : ... TypeCondition? Directives? SelectionSet
     */
    ;
  
    _proto.parseFragment = function parseFragment() {
      var start = this._lexer.token;
      this.expectToken(TokenKind.SPREAD);
      var hasTypeCondition = this.expectOptionalKeyword('on');
  
      if (!hasTypeCondition && this.peek(TokenKind.NAME)) {
        return {
          kind: Kind.FRAGMENT_SPREAD,
          name: this.parseFragmentName(),
          directives: this.parseDirectives(false),
          loc: this.loc(start)
        };
      }
  
      return {
        kind: Kind.INLINE_FRAGMENT,
        typeCondition: hasTypeCondition ? this.parseNamedType() : undefined,
        directives: this.parseDirectives(false),
        selectionSet: this.parseSelectionSet(),
        loc: this.loc(start)
      };
    }
    /**
     * FragmentDefinition :
     *   - fragment FragmentName on TypeCondition Directives? SelectionSet
     *
     * TypeCondition : NamedType
     */
    ;
  
    _proto.parseFragmentDefinition = function parseFragmentDefinition() {
      var start = this._lexer.token;
      this.expectKeyword('fragment'); // Experimental support for defining variables within fragments changes
      // the grammar of FragmentDefinition:
      //   - fragment FragmentName VariableDefinitions? on TypeCondition Directives? SelectionSet
  
      if (this._options.experimentalFragmentVariables) {
        return {
          kind: Kind.FRAGMENT_DEFINITION,
          name: this.parseFragmentName(),
          variableDefinitions: this.parseVariableDefinitions(),
          typeCondition: (this.expectKeyword('on'), this.parseNamedType()),
          directives: this.parseDirectives(false),
          selectionSet: this.parseSelectionSet(),
          loc: this.loc(start)
        };
      }
  
      return {
        kind: Kind.FRAGMENT_DEFINITION,
        name: this.parseFragmentName(),
        typeCondition: (this.expectKeyword('on'), this.parseNamedType()),
        directives: this.parseDirectives(false),
        selectionSet: this.parseSelectionSet(),
        loc: this.loc(start)
      };
    }
    /**
     * FragmentName : Name but not `on`
     */
    ;
  
    _proto.parseFragmentName = function parseFragmentName() {
      if (this._lexer.token.value === 'on') {
        throw this.unexpected();
      }
  
      return this.parseName();
    } // Implements the parsing rules in the Values section.
  
    /**
     * Value[Const] :
     *   - [~Const] Variable
     *   - IntValue
     *   - FloatValue
     *   - StringValue
     *   - BooleanValue
     *   - NullValue
     *   - EnumValue
     *   - ListValue[?Const]
     *   - ObjectValue[?Const]
     *
     * BooleanValue : one of `true` `false`
     *
     * NullValue : `null`
     *
     * EnumValue : Name but not `true`, `false` or `null`
     */
    ;
  
    _proto.parseValueLiteral = function parseValueLiteral(isConst) {
      var token = this._lexer.token;
  
      switch (token.kind) {
        case TokenKind.BRACKET_L:
          return this.parseList(isConst);
  
        case TokenKind.BRACE_L:
          return this.parseObject(isConst);
  
        case TokenKind.INT:
          this._lexer.advance();
  
          return {
            kind: Kind.INT,
            value: token.value,
            loc: this.loc(token)
          };
  
        case TokenKind.FLOAT:
          this._lexer.advance();
  
          return {
            kind: Kind.FLOAT,
            value: token.value,
            loc: this.loc(token)
          };
  
        case TokenKind.STRING:
        case TokenKind.BLOCK_STRING:
          return this.parseStringLiteral();
  
        case TokenKind.NAME:
          if (token.value === 'true' || token.value === 'false') {
            this._lexer.advance();
  
            return {
              kind: Kind.BOOLEAN,
              value: token.value === 'true',
              loc: this.loc(token)
            };
          } else if (token.value === 'null') {
            this._lexer.advance();
  
            return {
              kind: Kind.NULL,
              loc: this.loc(token)
            };
          }
  
          this._lexer.advance();
  
          return {
            kind: Kind.ENUM,
            value: token.value,
            loc: this.loc(token)
          };
  
        case TokenKind.DOLLAR:
          if (!isConst) {
            return this.parseVariable();
          }
  
          break;
      }
  
      throw this.unexpected();
    };
  
    _proto.parseStringLiteral = function parseStringLiteral() {
      var token = this._lexer.token;
  
      this._lexer.advance();
  
      return {
        kind: Kind.STRING,
        value: token.value,
        block: token.kind === TokenKind.BLOCK_STRING,
        loc: this.loc(token)
      };
    }
    /**
     * ListValue[Const] :
     *   - [ ]
     *   - [ Value[?Const]+ ]
     */
    ;
  
    _proto.parseList = function parseList(isConst) {
      var _this = this;
  
      var start = this._lexer.token;
  
      var item = function item() {
        return _this.parseValueLiteral(isConst);
      };
  
      return {
        kind: Kind.LIST,
        values: this.any(TokenKind.BRACKET_L, item, TokenKind.BRACKET_R),
        loc: this.loc(start)
      };
    }
    /**
     * ObjectValue[Const] :
     *   - { }
     *   - { ObjectField[?Const]+ }
     */
    ;
  
    _proto.parseObject = function parseObject(isConst) {
      var _this2 = this;
  
      var start = this._lexer.token;
  
      var item = function item() {
        return _this2.parseObjectField(isConst);
      };
  
      return {
        kind: Kind.OBJECT,
        fields: this.any(TokenKind.BRACE_L, item, TokenKind.BRACE_R),
        loc: this.loc(start)
      };
    }
    /**
     * ObjectField[Const] : Name : Value[?Const]
     */
    ;
  
    _proto.parseObjectField = function parseObjectField(isConst) {
      var start = this._lexer.token;
      var name = this.parseName();
      this.expectToken(TokenKind.COLON);
      return {
        kind: Kind.OBJECT_FIELD,
        name: name,
        value: this.parseValueLiteral(isConst),
        loc: this.loc(start)
      };
    } // Implements the parsing rules in the Directives section.
  
    /**
     * Directives[Const] : Directive[?Const]+
     */
    ;
  
    _proto.parseDirectives = function parseDirectives(isConst) {
      var directives = [];
  
      while (this.peek(TokenKind.AT)) {
        directives.push(this.parseDirective(isConst));
      }
  
      return directives;
    }
    /**
     * Directive[Const] : @ Name Arguments[?Const]?
     */
    ;
  
    _proto.parseDirective = function parseDirective(isConst) {
      var start = this._lexer.token;
      this.expectToken(TokenKind.AT);
      return {
        kind: Kind.DIRECTIVE,
        name: this.parseName(),
        arguments: this.parseArguments(isConst),
        loc: this.loc(start)
      };
    } // Implements the parsing rules in the Types section.
  
    /**
     * Type :
     *   - NamedType
     *   - ListType
     *   - NonNullType
     */
    ;
  
    _proto.parseTypeReference = function parseTypeReference() {
      var start = this._lexer.token;
      var type;
  
      if (this.expectOptionalToken(TokenKind.BRACKET_L)) {
        type = this.parseTypeReference();
        this.expectToken(TokenKind.BRACKET_R);
        type = {
          kind: Kind.LIST_TYPE,
          type: type,
          loc: this.loc(start)
        };
      } else {
        type = this.parseNamedType();
      }
  
      if (this.expectOptionalToken(TokenKind.BANG)) {
        return {
          kind: Kind.NON_NULL_TYPE,
          type: type,
          loc: this.loc(start)
        };
      }
  
      return type;
    }
    /**
     * NamedType : Name
     */
    ;
  
    _proto.parseNamedType = function parseNamedType() {
      var start = this._lexer.token;
      return {
        kind: Kind.NAMED_TYPE,
        name: this.parseName(),
        loc: this.loc(start)
      };
    } // Implements the parsing rules in the Type Definition section.
  
    /**
     * TypeSystemDefinition :
     *   - SchemaDefinition
     *   - TypeDefinition
     *   - DirectiveDefinition
     *
     * TypeDefinition :
     *   - ScalarTypeDefinition
     *   - ObjectTypeDefinition
     *   - InterfaceTypeDefinition
     *   - UnionTypeDefinition
     *   - EnumTypeDefinition
     *   - InputObjectTypeDefinition
     */
    ;
  
    _proto.parseTypeSystemDefinition = function parseTypeSystemDefinition() {
      // Many definitions begin with a description and require a lookahead.
      var keywordToken = this.peekDescription() ? this._lexer.lookahead() : this._lexer.token;
  
      if (keywordToken.kind === TokenKind.NAME) {
        switch (keywordToken.value) {
          case 'schema':
            return this.parseSchemaDefinition();
  
          case 'scalar':
            return this.parseScalarTypeDefinition();
  
          case 'type':
            return this.parseObjectTypeDefinition();
  
          case 'interface':
            return this.parseInterfaceTypeDefinition();
  
          case 'union':
            return this.parseUnionTypeDefinition();
  
          case 'enum':
            return this.parseEnumTypeDefinition();
  
          case 'input':
            return this.parseInputObjectTypeDefinition();
  
          case 'directive':
            return this.parseDirectiveDefinition();
        }
      }
  
      throw this.unexpected(keywordToken);
    };
  
    _proto.peekDescription = function peekDescription() {
      return this.peek(TokenKind.STRING) || this.peek(TokenKind.BLOCK_STRING);
    }
    /**
     * Description : StringValue
     */
    ;
  
    _proto.parseDescription = function parseDescription() {
      if (this.peekDescription()) {
        return this.parseStringLiteral();
      }
    }
    /**
     * SchemaDefinition : schema Directives[Const]? { OperationTypeDefinition+ }
     */
    ;
  
    _proto.parseSchemaDefinition = function parseSchemaDefinition() {
      var start = this._lexer.token;
      this.expectKeyword('schema');
      var directives = this.parseDirectives(true);
      var operationTypes = this.many(TokenKind.BRACE_L, this.parseOperationTypeDefinition, TokenKind.BRACE_R);
      return {
        kind: Kind.SCHEMA_DEFINITION,
        directives: directives,
        operationTypes: operationTypes,
        loc: this.loc(start)
      };
    }
    /**
     * OperationTypeDefinition : OperationType : NamedType
     */
    ;
  
    _proto.parseOperationTypeDefinition = function parseOperationTypeDefinition() {
      var start = this._lexer.token;
      var operation = this.parseOperationType();
      this.expectToken(TokenKind.COLON);
      var type = this.parseNamedType();
      return {
        kind: Kind.OPERATION_TYPE_DEFINITION,
        operation: operation,
        type: type,
        loc: this.loc(start)
      };
    }
    /**
     * ScalarTypeDefinition : Description? scalar Name Directives[Const]?
     */
    ;
  
    _proto.parseScalarTypeDefinition = function parseScalarTypeDefinition() {
      var start = this._lexer.token;
      var description = this.parseDescription();
      this.expectKeyword('scalar');
      var name = this.parseName();
      var directives = this.parseDirectives(true);
      return {
        kind: Kind.SCALAR_TYPE_DEFINITION,
        description: description,
        name: name,
        directives: directives,
        loc: this.loc(start)
      };
    }
    /**
     * ObjectTypeDefinition :
     *   Description?
     *   type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition?
     */
    ;
  
    _proto.parseObjectTypeDefinition = function parseObjectTypeDefinition() {
      var start = this._lexer.token;
      var description = this.parseDescription();
      this.expectKeyword('type');
      var name = this.parseName();
      var interfaces = this.parseImplementsInterfaces();
      var directives = this.parseDirectives(true);
      var fields = this.parseFieldsDefinition();
      return {
        kind: Kind.OBJECT_TYPE_DEFINITION,
        description: description,
        name: name,
        interfaces: interfaces,
        directives: directives,
        fields: fields,
        loc: this.loc(start)
      };
    }
    /**
     * ImplementsInterfaces :
     *   - implements `&`? NamedType
     *   - ImplementsInterfaces & NamedType
     */
    ;
  
    _proto.parseImplementsInterfaces = function parseImplementsInterfaces() {
      var types = [];
  
      if (this.expectOptionalKeyword('implements')) {
        // Optional leading ampersand
        this.expectOptionalToken(TokenKind.AMP);
  
        do {
          types.push(this.parseNamedType());
        } while (this.expectOptionalToken(TokenKind.AMP) || // Legacy support for the SDL?
        this._options.allowLegacySDLImplementsInterfaces && this.peek(TokenKind.NAME));
      }
  
      return types;
    }
    /**
     * FieldsDefinition : { FieldDefinition+ }
     */
    ;
  
    _proto.parseFieldsDefinition = function parseFieldsDefinition() {
      // Legacy support for the SDL?
      if (this._options.allowLegacySDLEmptyFields && this.peek(TokenKind.BRACE_L) && this._lexer.lookahead().kind === TokenKind.BRACE_R) {
        this._lexer.advance();
  
        this._lexer.advance();
  
        return [];
      }
  
      return this.optionalMany(TokenKind.BRACE_L, this.parseFieldDefinition, TokenKind.BRACE_R);
    }
    /**
     * FieldDefinition :
     *   - Description? Name ArgumentsDefinition? : Type Directives[Const]?
     */
    ;
  
    _proto.parseFieldDefinition = function parseFieldDefinition() {
      var start = this._lexer.token;
      var description = this.parseDescription();
      var name = this.parseName();
      var args = this.parseArgumentDefs();
      this.expectToken(TokenKind.COLON);
      var type = this.parseTypeReference();
      var directives = this.parseDirectives(true);
      return {
        kind: Kind.FIELD_DEFINITION,
        description: description,
        name: name,
        arguments: args,
        type: type,
        directives: directives,
        loc: this.loc(start)
      };
    }
    /**
     * ArgumentsDefinition : ( InputValueDefinition+ )
     */
    ;
  
    _proto.parseArgumentDefs = function parseArgumentDefs() {
      return this.optionalMany(TokenKind.PAREN_L, this.parseInputValueDef, TokenKind.PAREN_R);
    }
    /**
     * InputValueDefinition :
     *   - Description? Name : Type DefaultValue? Directives[Const]?
     */
    ;
  
    _proto.parseInputValueDef = function parseInputValueDef() {
      var start = this._lexer.token;
      var description = this.parseDescription();
      var name = this.parseName();
      this.expectToken(TokenKind.COLON);
      var type = this.parseTypeReference();
      var defaultValue;
  
      if (this.expectOptionalToken(TokenKind.EQUALS)) {
        defaultValue = this.parseValueLiteral(true);
      }
  
      var directives = this.parseDirectives(true);
      return {
        kind: Kind.INPUT_VALUE_DEFINITION,
        description: description,
        name: name,
        type: type,
        defaultValue: defaultValue,
        directives: directives,
        loc: this.loc(start)
      };
    }
    /**
     * InterfaceTypeDefinition :
     *   - Description? interface Name Directives[Const]? FieldsDefinition?
     */
    ;
  
    _proto.parseInterfaceTypeDefinition = function parseInterfaceTypeDefinition() {
      var start = this._lexer.token;
      var description = this.parseDescription();
      this.expectKeyword('interface');
      var name = this.parseName();
      var directives = this.parseDirectives(true);
      var fields = this.parseFieldsDefinition();
      return {
        kind: Kind.INTERFACE_TYPE_DEFINITION,
        description: description,
        name: name,
        directives: directives,
        fields: fields,
        loc: this.loc(start)
      };
    }
    /**
     * UnionTypeDefinition :
     *   - Description? union Name Directives[Const]? UnionMemberTypes?
     */
    ;
  
    _proto.parseUnionTypeDefinition = function parseUnionTypeDefinition() {
      var start = this._lexer.token;
      var description = this.parseDescription();
      this.expectKeyword('union');
      var name = this.parseName();
      var directives = this.parseDirectives(true);
      var types = this.parseUnionMemberTypes();
      return {
        kind: Kind.UNION_TYPE_DEFINITION,
        description: description,
        name: name,
        directives: directives,
        types: types,
        loc: this.loc(start)
      };
    }
    /**
     * UnionMemberTypes :
     *   - = `|`? NamedType
     *   - UnionMemberTypes | NamedType
     */
    ;
  
    _proto.parseUnionMemberTypes = function parseUnionMemberTypes() {
      var types = [];
  
      if (this.expectOptionalToken(TokenKind.EQUALS)) {
        // Optional leading pipe
        this.expectOptionalToken(TokenKind.PIPE);
  
        do {
          types.push(this.parseNamedType());
        } while (this.expectOptionalToken(TokenKind.PIPE));
      }
  
      return types;
    }
    /**
     * EnumTypeDefinition :
     *   - Description? enum Name Directives[Const]? EnumValuesDefinition?
     */
    ;
  
    _proto.parseEnumTypeDefinition = function parseEnumTypeDefinition() {
      var start = this._lexer.token;
      var description = this.parseDescription();
      this.expectKeyword('enum');
      var name = this.parseName();
      var directives = this.parseDirectives(true);
      var values = this.parseEnumValuesDefinition();
      return {
        kind: Kind.ENUM_TYPE_DEFINITION,
        description: description,
        name: name,
        directives: directives,
        values: values,
        loc: this.loc(start)
      };
    }
    /**
     * EnumValuesDefinition : { EnumValueDefinition+ }
     */
    ;
  
    _proto.parseEnumValuesDefinition = function parseEnumValuesDefinition() {
      return this.optionalMany(TokenKind.BRACE_L, this.parseEnumValueDefinition, TokenKind.BRACE_R);
    }
    /**
     * EnumValueDefinition : Description? EnumValue Directives[Const]?
     *
     * EnumValue : Name
     */
    ;
  
    _proto.parseEnumValueDefinition = function parseEnumValueDefinition() {
      var start = this._lexer.token;
      var description = this.parseDescription();
      var name = this.parseName();
      var directives = this.parseDirectives(true);
      return {
        kind: Kind.ENUM_VALUE_DEFINITION,
        description: description,
        name: name,
        directives: directives,
        loc: this.loc(start)
      };
    }
    /**
     * InputObjectTypeDefinition :
     *   - Description? input Name Directives[Const]? InputFieldsDefinition?
     */
    ;
  
    _proto.parseInputObjectTypeDefinition = function parseInputObjectTypeDefinition() {
      var start = this._lexer.token;
      var description = this.parseDescription();
      this.expectKeyword('input');
      var name = this.parseName();
      var directives = this.parseDirectives(true);
      var fields = this.parseInputFieldsDefinition();
      return {
        kind: Kind.INPUT_OBJECT_TYPE_DEFINITION,
        description: description,
        name: name,
        directives: directives,
        fields: fields,
        loc: this.loc(start)
      };
    }
    /**
     * InputFieldsDefinition : { InputValueDefinition+ }
     */
    ;
  
    _proto.parseInputFieldsDefinition = function parseInputFieldsDefinition() {
      return this.optionalMany(TokenKind.BRACE_L, this.parseInputValueDef, TokenKind.BRACE_R);
    }
    /**
     * TypeSystemExtension :
     *   - SchemaExtension
     *   - TypeExtension
     *
     * TypeExtension :
     *   - ScalarTypeExtension
     *   - ObjectTypeExtension
     *   - InterfaceTypeExtension
     *   - UnionTypeExtension
     *   - EnumTypeExtension
     *   - InputObjectTypeDefinition
     */
    ;
  
    _proto.parseTypeSystemExtension = function parseTypeSystemExtension() {
      var keywordToken = this._lexer.lookahead();
  
      if (keywordToken.kind === TokenKind.NAME) {
        switch (keywordToken.value) {
          case 'schema':
            return this.parseSchemaExtension();
  
          case 'scalar':
            return this.parseScalarTypeExtension();
  
          case 'type':
            return this.parseObjectTypeExtension();
  
          case 'interface':
            return this.parseInterfaceTypeExtension();
  
          case 'union':
            return this.parseUnionTypeExtension();
  
          case 'enum':
            return this.parseEnumTypeExtension();
  
          case 'input':
            return this.parseInputObjectTypeExtension();
        }
      }
  
      throw this.unexpected(keywordToken);
    }
    /**
     * SchemaExtension :
     *  - extend schema Directives[Const]? { OperationTypeDefinition+ }
     *  - extend schema Directives[Const]
     */
    ;
  
    _proto.parseSchemaExtension = function parseSchemaExtension() {
      var start = this._lexer.token;
      this.expectKeyword('extend');
      this.expectKeyword('schema');
      var directives = this.parseDirectives(true);
      var operationTypes = this.optionalMany(TokenKind.BRACE_L, this.parseOperationTypeDefinition, TokenKind.BRACE_R);
  
      if (directives.length === 0 && operationTypes.length === 0) {
        throw this.unexpected();
      }
  
      return {
        kind: Kind.SCHEMA_EXTENSION,
        directives: directives,
        operationTypes: operationTypes,
        loc: this.loc(start)
      };
    }
    /**
     * ScalarTypeExtension :
     *   - extend scalar Name Directives[Const]
     */
    ;
  
    _proto.parseScalarTypeExtension = function parseScalarTypeExtension() {
      var start = this._lexer.token;
      this.expectKeyword('extend');
      this.expectKeyword('scalar');
      var name = this.parseName();
      var directives = this.parseDirectives(true);
  
      if (directives.length === 0) {
        throw this.unexpected();
      }
  
      return {
        kind: Kind.SCALAR_TYPE_EXTENSION,
        name: name,
        directives: directives,
        loc: this.loc(start)
      };
    }
    /**
     * ObjectTypeExtension :
     *  - extend type Name ImplementsInterfaces? Directives[Const]? FieldsDefinition
     *  - extend type Name ImplementsInterfaces? Directives[Const]
     *  - extend type Name ImplementsInterfaces
     */
    ;
  
    _proto.parseObjectTypeExtension = function parseObjectTypeExtension() {
      var start = this._lexer.token;
      this.expectKeyword('extend');
      this.expectKeyword('type');
      var name = this.parseName();
      var interfaces = this.parseImplementsInterfaces();
      var directives = this.parseDirectives(true);
      var fields = this.parseFieldsDefinition();
  
      if (interfaces.length === 0 && directives.length === 0 && fields.length === 0) {
        throw this.unexpected();
      }
  
      return {
        kind: Kind.OBJECT_TYPE_EXTENSION,
        name: name,
        interfaces: interfaces,
        directives: directives,
        fields: fields,
        loc: this.loc(start)
      };
    }
    /**
     * InterfaceTypeExtension :
     *   - extend interface Name Directives[Const]? FieldsDefinition
     *   - extend interface Name Directives[Const]
     */
    ;
  
    _proto.parseInterfaceTypeExtension = function parseInterfaceTypeExtension() {
      var start = this._lexer.token;
      this.expectKeyword('extend');
      this.expectKeyword('interface');
      var name = this.parseName();
      var directives = this.parseDirectives(true);
      var fields = this.parseFieldsDefinition();
  
      if (directives.length === 0 && fields.length === 0) {
        throw this.unexpected();
      }
  
      return {
        kind: Kind.INTERFACE_TYPE_EXTENSION,
        name: name,
        directives: directives,
        fields: fields,
        loc: this.loc(start)
      };
    }
    /**
     * UnionTypeExtension :
     *   - extend union Name Directives[Const]? UnionMemberTypes
     *   - extend union Name Directives[Const]
     */
    ;
  
    _proto.parseUnionTypeExtension = function parseUnionTypeExtension() {
      var start = this._lexer.token;
      this.expectKeyword('extend');
      this.expectKeyword('union');
      var name = this.parseName();
      var directives = this.parseDirectives(true);
      var types = this.parseUnionMemberTypes();
  
      if (directives.length === 0 && types.length === 0) {
        throw this.unexpected();
      }
  
      return {
        kind: Kind.UNION_TYPE_EXTENSION,
        name: name,
        directives: directives,
        types: types,
        loc: this.loc(start)
      };
    }
    /**
     * EnumTypeExtension :
     *   - extend enum Name Directives[Const]? EnumValuesDefinition
     *   - extend enum Name Directives[Const]
     */
    ;
  
    _proto.parseEnumTypeExtension = function parseEnumTypeExtension() {
      var start = this._lexer.token;
      this.expectKeyword('extend');
      this.expectKeyword('enum');
      var name = this.parseName();
      var directives = this.parseDirectives(true);
      var values = this.parseEnumValuesDefinition();
  
      if (directives.length === 0 && values.length === 0) {
        throw this.unexpected();
      }
  
      return {
        kind: Kind.ENUM_TYPE_EXTENSION,
        name: name,
        directives: directives,
        values: values,
        loc: this.loc(start)
      };
    }
    /**
     * InputObjectTypeExtension :
     *   - extend input Name Directives[Const]? InputFieldsDefinition
     *   - extend input Name Directives[Const]
     */
    ;
  
    _proto.parseInputObjectTypeExtension = function parseInputObjectTypeExtension() {
      var start = this._lexer.token;
      this.expectKeyword('extend');
      this.expectKeyword('input');
      var name = this.parseName();
      var directives = this.parseDirectives(true);
      var fields = this.parseInputFieldsDefinition();
  
      if (directives.length === 0 && fields.length === 0) {
        throw this.unexpected();
      }
  
      return {
        kind: Kind.INPUT_OBJECT_TYPE_EXTENSION,
        name: name,
        directives: directives,
        fields: fields,
        loc: this.loc(start)
      };
    }
    /**
     * DirectiveDefinition :
     *   - Description? directive @ Name ArgumentsDefinition? `repeatable`? on DirectiveLocations
     */
    ;
  
    _proto.parseDirectiveDefinition = function parseDirectiveDefinition() {
      var start = this._lexer.token;
      var description = this.parseDescription();
      this.expectKeyword('directive');
      this.expectToken(TokenKind.AT);
      var name = this.parseName();
      var args = this.parseArgumentDefs();
      var repeatable = this.expectOptionalKeyword('repeatable');
      this.expectKeyword('on');
      var locations = this.parseDirectiveLocations();
      return {
        kind: Kind.DIRECTIVE_DEFINITION,
        description: description,
        name: name,
        arguments: args,
        repeatable: repeatable,
        locations: locations,
        loc: this.loc(start)
      };
    }
    /**
     * DirectiveLocations :
     *   - `|`? DirectiveLocation
     *   - DirectiveLocations | DirectiveLocation
     */
    ;
  
    _proto.parseDirectiveLocations = function parseDirectiveLocations() {
      // Optional leading pipe
      this.expectOptionalToken(TokenKind.PIPE);
      var locations = [];
  
      do {
        locations.push(this.parseDirectiveLocation());
      } while (this.expectOptionalToken(TokenKind.PIPE));
  
      return locations;
    }
    /*
     * DirectiveLocation :
     *   - ExecutableDirectiveLocation
     *   - TypeSystemDirectiveLocation
     *
     * ExecutableDirectiveLocation : one of
     *   `QUERY`
     *   `MUTATION`
     *   `SUBSCRIPTION`
     *   `FIELD`
     *   `FRAGMENT_DEFINITION`
     *   `FRAGMENT_SPREAD`
     *   `INLINE_FRAGMENT`
     *
     * TypeSystemDirectiveLocation : one of
     *   `SCHEMA`
     *   `SCALAR`
     *   `OBJECT`
     *   `FIELD_DEFINITION`
     *   `ARGUMENT_DEFINITION`
     *   `INTERFACE`
     *   `UNION`
     *   `ENUM`
     *   `ENUM_VALUE`
     *   `INPUT_OBJECT`
     *   `INPUT_FIELD_DEFINITION`
     */
    ;
  
    _proto.parseDirectiveLocation = function parseDirectiveLocation() {
      var start = this._lexer.token;
      var name = this.parseName();
  
      if (DirectiveLocation[name.value] !== undefined) {
        return name;
      }
  
      throw this.unexpected(start);
    } // Core parsing utility functions
  
    /**
     * Returns a location object, used to identify the place in
     * the source that created a given parsed object.
     */
    ;
  
    _proto.loc = function loc(startToken) {
      if (!this._options.noLocation) {
        return new Loc(startToken, this._lexer.lastToken, this._lexer.source);
      }
    }
    /**
     * Determines if the next token is of a given kind
     */
    ;
  
    _proto.peek = function peek(kind) {
      return this._lexer.token.kind === kind;
    }
    /**
     * If the next token is of the given kind, return that token after advancing
     * the lexer. Otherwise, do not change the parser state and throw an error.
     */
    ;
  
    _proto.expectToken = function expectToken(kind) {
      var token = this._lexer.token;
  
      if (token.kind === kind) {
        this._lexer.advance();
  
        return token;
      }
  
      throw syntaxError(this._lexer.source, token.start, "Expected ".concat(kind, ", found ").concat(getTokenDesc(token)));
    }
    /**
     * If the next token is of the given kind, return that token after advancing
     * the lexer. Otherwise, do not change the parser state and return undefined.
     */
    ;
  
    _proto.expectOptionalToken = function expectOptionalToken(kind) {
      var token = this._lexer.token;
  
      if (token.kind === kind) {
        this._lexer.advance();
  
        return token;
      }
  
      return undefined;
    }
    /**
     * If the next token is a given keyword, advance the lexer.
     * Otherwise, do not change the parser state and throw an error.
     */
    ;
  
    _proto.expectKeyword = function expectKeyword(value) {
      var token = this._lexer.token;
  
      if (token.kind === TokenKind.NAME && token.value === value) {
        this._lexer.advance();
      } else {
        throw syntaxError(this._lexer.source, token.start, "Expected \"".concat(value, "\", found ").concat(getTokenDesc(token)));
      }
    }
    /**
     * If the next token is a given keyword, return "true" after advancing
     * the lexer. Otherwise, do not change the parser state and return "false".
     */
    ;
  
    _proto.expectOptionalKeyword = function expectOptionalKeyword(value) {
      var token = this._lexer.token;
  
      if (token.kind === TokenKind.NAME && token.value === value) {
        this._lexer.advance();
  
        return true;
      }
  
      return false;
    }
    /**
     * Helper function for creating an error when an unexpected lexed token
     * is encountered.
     */
    ;
  
    _proto.unexpected = function unexpected(atToken) {
      var token = atToken || this._lexer.token;
      return syntaxError(this._lexer.source, token.start, "Unexpected ".concat(getTokenDesc(token)));
    }
    /**
     * Returns a possibly empty list of parse nodes, determined by
     * the parseFn. This list begins with a lex token of openKind
     * and ends with a lex token of closeKind. Advances the parser
     * to the next lex token after the closing token.
     */
    ;
  
    _proto.any = function any(openKind, parseFn, closeKind) {
      this.expectToken(openKind);
      var nodes = [];
  
      while (!this.expectOptionalToken(closeKind)) {
        nodes.push(parseFn.call(this));
      }
  
      return nodes;
    }
    /**
     * Returns a list of parse nodes, determined by the parseFn.
     * It can be empty only if open token is missing otherwise it will always
     * return non-empty list that begins with a lex token of openKind and ends
     * with a lex token of closeKind. Advances the parser to the next lex token
     * after the closing token.
     */
    ;
  
    _proto.optionalMany = function optionalMany(openKind, parseFn, closeKind) {
      if (this.expectOptionalToken(openKind)) {
        var nodes = [];
  
        do {
          nodes.push(parseFn.call(this));
        } while (!this.expectOptionalToken(closeKind));
  
        return nodes;
      }
  
      return [];
    }
    /**
     * Returns a non-empty list of parse nodes, determined by
     * the parseFn. This list begins with a lex token of openKind
     * and ends with a lex token of closeKind. Advances the parser
     * to the next lex token after the closing token.
     */
    ;
  
    _proto.many = function many(openKind, parseFn, closeKind) {
      this.expectToken(openKind);
      var nodes = [];
  
      do {
        nodes.push(parseFn.call(this));
      } while (!this.expectOptionalToken(closeKind));
  
      return nodes;
    };
  
    return Parser;
  }();
  
  function Loc(startToken, endToken, source) {
    this.start = startToken.start;
    this.end = endToken.end;
    this.startToken = startToken;
    this.endToken = endToken;
    this.source = source;
  } // Print a simplified form when appearing in JSON/util.inspect.
  
  
  defineToJSON(Loc, function () {
    return {
      start: this.start,
      end: this.end
    };
  });
  /**
   * A helper function to describe a token as a string for debugging
   */
  
  function getTokenDesc(token) {
    var value = token.value;
    return value ? "".concat(token.kind, " \"").concat(value, "\"") : token.kind;
  }
  
  var parser = /*#__PURE__*/Object.freeze({
      __proto__: null,
      parse: parse,
      parseValue: parseValue,
      parseType: parseType
  });
  
  var QueryDocumentKeys = {
    Name: [],
    Document: ['definitions'],
    OperationDefinition: ['name', 'variableDefinitions', 'directives', 'selectionSet'],
    VariableDefinition: ['variable', 'type', 'defaultValue', 'directives'],
    Variable: ['name'],
    SelectionSet: ['selections'],
    Field: ['alias', 'name', 'arguments', 'directives', 'selectionSet'],
    Argument: ['name', 'value'],
    FragmentSpread: ['name', 'directives'],
    InlineFragment: ['typeCondition', 'directives', 'selectionSet'],
    FragmentDefinition: ['name', // Note: fragment variable definitions are experimental and may be changed
    // or removed in the future.
    'variableDefinitions', 'typeCondition', 'directives', 'selectionSet'],
    IntValue: [],
    FloatValue: [],
    StringValue: [],
    BooleanValue: [],
    NullValue: [],
    EnumValue: [],
    ListValue: ['values'],
    ObjectValue: ['fields'],
    ObjectField: ['name', 'value'],
    Directive: ['name', 'arguments'],
    NamedType: ['name'],
    ListType: ['type'],
    NonNullType: ['type'],
    SchemaDefinition: ['directives', 'operationTypes'],
    OperationTypeDefinition: ['type'],
    ScalarTypeDefinition: ['description', 'name', 'directives'],
    ObjectTypeDefinition: ['description', 'name', 'interfaces', 'directives', 'fields'],
    FieldDefinition: ['description', 'name', 'arguments', 'type', 'directives'],
    InputValueDefinition: ['description', 'name', 'type', 'defaultValue', 'directives'],
    InterfaceTypeDefinition: ['description', 'name', 'directives', 'fields'],
    UnionTypeDefinition: ['description', 'name', 'directives', 'types'],
    EnumTypeDefinition: ['description', 'name', 'directives', 'values'],
    EnumValueDefinition: ['description', 'name', 'directives'],
    InputObjectTypeDefinition: ['description', 'name', 'directives', 'fields'],
    DirectiveDefinition: ['description', 'name', 'arguments', 'locations'],
    SchemaExtension: ['directives', 'operationTypes'],
    ScalarTypeExtension: ['name', 'directives'],
    ObjectTypeExtension: ['name', 'interfaces', 'directives', 'fields'],
    InterfaceTypeExtension: ['name', 'directives', 'fields'],
    UnionTypeExtension: ['name', 'directives', 'types'],
    EnumTypeExtension: ['name', 'directives', 'values'],
    InputObjectTypeExtension: ['name', 'directives', 'fields']
  };
  var BREAK = Object.freeze({});
  /**
   * visit() will walk through an AST using a depth first traversal, calling
   * the visitor's enter function at each node in the traversal, and calling the
   * leave function after visiting that node and all of its child nodes.
   *
   * By returning different values from the enter and leave functions, the
   * behavior of the visitor can be altered, including skipping over a sub-tree of
   * the AST (by returning false), editing the AST by returning a value or null
   * to remove the value, or to stop the whole traversal by returning BREAK.
   *
   * When using visit() to edit an AST, the original AST will not be modified, and
   * a new version of the AST with the changes applied will be returned from the
   * visit function.
   *
   *     const editedAST = visit(ast, {
   *       enter(node, key, parent, path, ancestors) {
   *         // @return
   *         //   undefined: no action
   *         //   false: skip visiting this node
   *         //   visitor.BREAK: stop visiting altogether
   *         //   null: delete this node
   *         //   any value: replace this node with the returned value
   *       },
   *       leave(node, key, parent, path, ancestors) {
   *         // @return
   *         //   undefined: no action
   *         //   false: no action
   *         //   visitor.BREAK: stop visiting altogether
   *         //   null: delete this node
   *         //   any value: replace this node with the returned value
   *       }
   *     });
   *
   * Alternatively to providing enter() and leave() functions, a visitor can
   * instead provide functions named the same as the kinds of AST nodes, or
   * enter/leave visitors at a named key, leading to four permutations of
   * visitor API:
   *
   * 1) Named visitors triggered when entering a node a specific kind.
   *
   *     visit(ast, {
   *       Kind(node) {
   *         // enter the "Kind" node
   *       }
   *     })
   *
   * 2) Named visitors that trigger upon entering and leaving a node of
   *    a specific kind.
   *
   *     visit(ast, {
   *       Kind: {
   *         enter(node) {
   *           // enter the "Kind" node
   *         }
   *         leave(node) {
   *           // leave the "Kind" node
   *         }
   *       }
   *     })
   *
   * 3) Generic visitors that trigger upon entering and leaving any node.
   *
   *     visit(ast, {
   *       enter(node) {
   *         // enter any node
   *       },
   *       leave(node) {
   *         // leave any node
   *       }
   *     })
   *
   * 4) Parallel visitors for entering and leaving nodes of a specific kind.
   *
   *     visit(ast, {
   *       enter: {
   *         Kind(node) {
   *           // enter the "Kind" node
   *         }
   *       },
   *       leave: {
   *         Kind(node) {
   *           // leave the "Kind" node
   *         }
   *       }
   *     })
   */
  
  function visit(root, visitor) {
    var visitorKeys = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : QueryDocumentKeys;
  
    /* eslint-disable no-undef-init */
    var stack = undefined;
    var inArray = Array.isArray(root);
    var keys = [root];
    var index = -1;
    var edits = [];
    var node = undefined;
    var key = undefined;
    var parent = undefined;
    var path = [];
    var ancestors = [];
    var newRoot = root;
    /* eslint-enable no-undef-init */
  
    do {
      index++;
      var isLeaving = index === keys.length;
      var isEdited = isLeaving && edits.length !== 0;
  
      if (isLeaving) {
        key = ancestors.length === 0 ? undefined : path[path.length - 1];
        node = parent;
        parent = ancestors.pop();
  
        if (isEdited) {
          if (inArray) {
            node = node.slice();
          } else {
            var clone = {};
  
            for (var _i2 = 0, _Object$keys2 = Object.keys(node); _i2 < _Object$keys2.length; _i2++) {
              var k = _Object$keys2[_i2];
              clone[k] = node[k];
            }
  
            node = clone;
          }
  
          var editOffset = 0;
  
          for (var ii = 0; ii < edits.length; ii++) {
            var editKey = edits[ii][0];
            var editValue = edits[ii][1];
  
            if (inArray) {
              editKey -= editOffset;
            }
  
            if (inArray && editValue === null) {
              node.splice(editKey, 1);
              editOffset++;
            } else {
              node[editKey] = editValue;
            }
          }
        }
  
        index = stack.index;
        keys = stack.keys;
        edits = stack.edits;
        inArray = stack.inArray;
        stack = stack.prev;
      } else {
        key = parent ? inArray ? index : keys[index] : undefined;
        node = parent ? parent[key] : newRoot;
  
        if (node === null || node === undefined) {
          continue;
        }
  
        if (parent) {
          path.push(key);
        }
      }
  
      var result = void 0;
  
      if (!Array.isArray(node)) {
        if (!isNode(node)) {
          throw new Error('Invalid AST Node: ' + inspect(node));
        }
  
        var visitFn = getVisitFn(visitor, node.kind, isLeaving);
  
        if (visitFn) {
          result = visitFn.call(visitor, node, key, parent, path, ancestors);
  
          if (result === BREAK) {
            break;
          }
  
          if (result === false) {
            if (!isLeaving) {
              path.pop();
              continue;
            }
          } else if (result !== undefined) {
            edits.push([key, result]);
  
            if (!isLeaving) {
              if (isNode(result)) {
                node = result;
              } else {
                path.pop();
                continue;
              }
            }
          }
        }
      }
  
      if (result === undefined && isEdited) {
        edits.push([key, node]);
      }
  
      if (isLeaving) {
        path.pop();
      } else {
        stack = {
          inArray: inArray,
          index: index,
          keys: keys,
          edits: edits,
          prev: stack
        };
        inArray = Array.isArray(node);
        keys = inArray ? node : visitorKeys[node.kind] || [];
        index = -1;
        edits = [];
  
        if (parent) {
          ancestors.push(parent);
        }
  
        parent = node;
      }
    } while (stack !== undefined);
  
    if (edits.length !== 0) {
      newRoot = edits[edits.length - 1][1];
    }
  
    return newRoot;
  }
  
  function isNode(maybeNode) {
    return Boolean(maybeNode && typeof maybeNode.kind === 'string');
  }
  /**
   * Given a visitor instance, if it is leaving or not, and a node kind, return
   * the function the visitor runtime should call.
   */
  
  function getVisitFn(visitor, kind, isLeaving) {
    var kindVisitor = visitor[kind];
  
    if (kindVisitor) {
      if (!isLeaving && typeof kindVisitor === 'function') {
        // { Kind() {} }
        return kindVisitor;
      }
  
      var kindSpecificVisitor = isLeaving ? kindVisitor.leave : kindVisitor.enter;
  
      if (typeof kindSpecificVisitor === 'function') {
        // { Kind: { enter() {}, leave() {} } }
        return kindSpecificVisitor;
      }
    } else {
      var specificVisitor = isLeaving ? visitor.leave : visitor.enter;
  
      if (specificVisitor) {
        if (typeof specificVisitor === 'function') {
          // { enter() {}, leave() {} }
          return specificVisitor;
        }
  
        var specificKindVisitor = specificVisitor[kind];
  
        if (typeof specificKindVisitor === 'function') {
          // { enter: { Kind() {} }, leave: { Kind() {} } }
          return specificKindVisitor;
        }
      }
    }
  }
  
  /**
   * Converts an AST into a string, using one set of reasonable
   * formatting rules.
   */
  
  function print(ast) {
    return visit(ast, {
      leave: printDocASTReducer
    });
  } // TODO: provide better type coverage in future
  
  var printDocASTReducer = {
    Name: function Name(node) {
      return node.value;
    },
    Variable: function Variable(node) {
      return '$' + node.name;
    },
    // Document
    Document: function Document(node) {
      return join(node.definitions, '\n\n') + '\n';
    },
    OperationDefinition: function OperationDefinition(node) {
      var op = node.operation;
      var name = node.name;
      var varDefs = wrap('(', join(node.variableDefinitions, ', '), ')');
      var directives = join(node.directives, ' ');
      var selectionSet = node.selectionSet; // Anonymous queries with no directives or variable definitions can use
      // the query short form.
  
      return !name && !directives && !varDefs && op === 'query' ? selectionSet : join([op, join([name, varDefs]), directives, selectionSet], ' ');
    },
    VariableDefinition: function VariableDefinition(_ref) {
      var variable = _ref.variable,
          type = _ref.type,
          defaultValue = _ref.defaultValue,
          directives = _ref.directives;
      return variable + ': ' + type + wrap(' = ', defaultValue) + wrap(' ', join(directives, ' '));
    },
    SelectionSet: function SelectionSet(_ref2) {
      var selections = _ref2.selections;
      return block(selections);
    },
    Field: function Field(_ref3) {
      var alias = _ref3.alias,
          name = _ref3.name,
          args = _ref3.arguments,
          directives = _ref3.directives,
          selectionSet = _ref3.selectionSet;
      return join([wrap('', alias, ': ') + name + wrap('(', join(args, ', '), ')'), join(directives, ' '), selectionSet], ' ');
    },
    Argument: function Argument(_ref4) {
      var name = _ref4.name,
          value = _ref4.value;
      return name + ': ' + value;
    },
    // Fragments
    FragmentSpread: function FragmentSpread(_ref5) {
      var name = _ref5.name,
          directives = _ref5.directives;
      return '...' + name + wrap(' ', join(directives, ' '));
    },
    InlineFragment: function InlineFragment(_ref6) {
      var typeCondition = _ref6.typeCondition,
          directives = _ref6.directives,
          selectionSet = _ref6.selectionSet;
      return join(['...', wrap('on ', typeCondition), join(directives, ' '), selectionSet], ' ');
    },
    FragmentDefinition: function FragmentDefinition(_ref7) {
      var name = _ref7.name,
          typeCondition = _ref7.typeCondition,
          variableDefinitions = _ref7.variableDefinitions,
          directives = _ref7.directives,
          selectionSet = _ref7.selectionSet;
      return (// Note: fragment variable definitions are experimental and may be changed
        // or removed in the future.
        "fragment ".concat(name).concat(wrap('(', join(variableDefinitions, ', '), ')'), " ") + "on ".concat(typeCondition, " ").concat(wrap('', join(directives, ' '), ' ')) + selectionSet
      );
    },
    // Value
    IntValue: function IntValue(_ref8) {
      var value = _ref8.value;
      return value;
    },
    FloatValue: function FloatValue(_ref9) {
      var value = _ref9.value;
      return value;
    },
    StringValue: function StringValue(_ref10, key) {
      var value = _ref10.value,
          isBlockString = _ref10.block;
      return isBlockString ? printBlockString(value, key === 'description' ? '' : '  ') : JSON.stringify(value);
    },
    BooleanValue: function BooleanValue(_ref11) {
      var value = _ref11.value;
      return value ? 'true' : 'false';
    },
    NullValue: function NullValue() {
      return 'null';
    },
    EnumValue: function EnumValue(_ref12) {
      var value = _ref12.value;
      return value;
    },
    ListValue: function ListValue(_ref13) {
      var values = _ref13.values;
      return '[' + join(values, ', ') + ']';
    },
    ObjectValue: function ObjectValue(_ref14) {
      var fields = _ref14.fields;
      return '{' + join(fields, ', ') + '}';
    },
    ObjectField: function ObjectField(_ref15) {
      var name = _ref15.name,
          value = _ref15.value;
      return name + ': ' + value;
    },
    // Directive
    Directive: function Directive(_ref16) {
      var name = _ref16.name,
          args = _ref16.arguments;
      return '@' + name + wrap('(', join(args, ', '), ')');
    },
    // Type
    NamedType: function NamedType(_ref17) {
      var name = _ref17.name;
      return name;
    },
    ListType: function ListType(_ref18) {
      var type = _ref18.type;
      return '[' + type + ']';
    },
    NonNullType: function NonNullType(_ref19) {
      var type = _ref19.type;
      return type + '!';
    },
    // Type System Definitions
    SchemaDefinition: function SchemaDefinition(_ref20) {
      var directives = _ref20.directives,
          operationTypes = _ref20.operationTypes;
      return join(['schema', join(directives, ' '), block(operationTypes)], ' ');
    },
    OperationTypeDefinition: function OperationTypeDefinition(_ref21) {
      var operation = _ref21.operation,
          type = _ref21.type;
      return operation + ': ' + type;
    },
    ScalarTypeDefinition: addDescription(function (_ref22) {
      var name = _ref22.name,
          directives = _ref22.directives;
      return join(['scalar', name, join(directives, ' ')], ' ');
    }),
    ObjectTypeDefinition: addDescription(function (_ref23) {
      var name = _ref23.name,
          interfaces = _ref23.interfaces,
          directives = _ref23.directives,
          fields = _ref23.fields;
      return join(['type', name, wrap('implements ', join(interfaces, ' & ')), join(directives, ' '), block(fields)], ' ');
    }),
    FieldDefinition: addDescription(function (_ref24) {
      var name = _ref24.name,
          args = _ref24.arguments,
          type = _ref24.type,
          directives = _ref24.directives;
      return name + (hasMultilineItems(args) ? wrap('(\n', indent(join(args, '\n')), '\n)') : wrap('(', join(args, ', '), ')')) + ': ' + type + wrap(' ', join(directives, ' '));
    }),
    InputValueDefinition: addDescription(function (_ref25) {
      var name = _ref25.name,
          type = _ref25.type,
          defaultValue = _ref25.defaultValue,
          directives = _ref25.directives;
      return join([name + ': ' + type, wrap('= ', defaultValue), join(directives, ' ')], ' ');
    }),
    InterfaceTypeDefinition: addDescription(function (_ref26) {
      var name = _ref26.name,
          directives = _ref26.directives,
          fields = _ref26.fields;
      return join(['interface', name, join(directives, ' '), block(fields)], ' ');
    }),
    UnionTypeDefinition: addDescription(function (_ref27) {
      var name = _ref27.name,
          directives = _ref27.directives,
          types = _ref27.types;
      return join(['union', name, join(directives, ' '), types && types.length !== 0 ? '= ' + join(types, ' | ') : ''], ' ');
    }),
    EnumTypeDefinition: addDescription(function (_ref28) {
      var name = _ref28.name,
          directives = _ref28.directives,
          values = _ref28.values;
      return join(['enum', name, join(directives, ' '), block(values)], ' ');
    }),
    EnumValueDefinition: addDescription(function (_ref29) {
      var name = _ref29.name,
          directives = _ref29.directives;
      return join([name, join(directives, ' ')], ' ');
    }),
    InputObjectTypeDefinition: addDescription(function (_ref30) {
      var name = _ref30.name,
          directives = _ref30.directives,
          fields = _ref30.fields;
      return join(['input', name, join(directives, ' '), block(fields)], ' ');
    }),
    DirectiveDefinition: addDescription(function (_ref31) {
      var name = _ref31.name,
          args = _ref31.arguments,
          repeatable = _ref31.repeatable,
          locations = _ref31.locations;
      return 'directive @' + name + (hasMultilineItems(args) ? wrap('(\n', indent(join(args, '\n')), '\n)') : wrap('(', join(args, ', '), ')')) + (repeatable ? ' repeatable' : '') + ' on ' + join(locations, ' | ');
    }),
    SchemaExtension: function SchemaExtension(_ref32) {
      var directives = _ref32.directives,
          operationTypes = _ref32.operationTypes;
      return join(['extend schema', join(directives, ' '), block(operationTypes)], ' ');
    },
    ScalarTypeExtension: function ScalarTypeExtension(_ref33) {
      var name = _ref33.name,
          directives = _ref33.directives;
      return join(['extend scalar', name, join(directives, ' ')], ' ');
    },
    ObjectTypeExtension: function ObjectTypeExtension(_ref34) {
      var name = _ref34.name,
          interfaces = _ref34.interfaces,
          directives = _ref34.directives,
          fields = _ref34.fields;
      return join(['extend type', name, wrap('implements ', join(interfaces, ' & ')), join(directives, ' '), block(fields)], ' ');
    },
    InterfaceTypeExtension: function InterfaceTypeExtension(_ref35) {
      var name = _ref35.name,
          directives = _ref35.directives,
          fields = _ref35.fields;
      return join(['extend interface', name, join(directives, ' '), block(fields)], ' ');
    },
    UnionTypeExtension: function UnionTypeExtension(_ref36) {
      var name = _ref36.name,
          directives = _ref36.directives,
          types = _ref36.types;
      return join(['extend union', name, join(directives, ' '), types && types.length !== 0 ? '= ' + join(types, ' | ') : ''], ' ');
    },
    EnumTypeExtension: function EnumTypeExtension(_ref37) {
      var name = _ref37.name,
          directives = _ref37.directives,
          values = _ref37.values;
      return join(['extend enum', name, join(directives, ' '), block(values)], ' ');
    },
    InputObjectTypeExtension: function InputObjectTypeExtension(_ref38) {
      var name = _ref38.name,
          directives = _ref38.directives,
          fields = _ref38.fields;
      return join(['extend input', name, join(directives, ' '), block(fields)], ' ');
    }
  };
  
  function addDescription(cb) {
    return function (node) {
      return join([node.description, cb(node)], '\n');
    };
  }
  /**
   * Given maybeArray, print an empty string if it is null or empty, otherwise
   * print all items together separated by separator if provided
   */
  
  
  function join(maybeArray, separator) {
    return maybeArray ? maybeArray.filter(function (x) {
      return x;
    }).join(separator || '') : '';
  }
  /**
   * Given array, print each item on its own line, wrapped in an
   * indented "{ }" block.
   */
  
  
  function block(array) {
    return array && array.length !== 0 ? '{\n' + indent(join(array, '\n')) + '\n}' : '';
  }
  /**
   * If maybeString is not null or empty, then wrap with start and end, otherwise
   * print an empty string.
   */
  
  
  function wrap(start, maybeString, end) {
    return maybeString ? start + maybeString + (end || '') : '';
  }
  
  function indent(maybeString) {
    return maybeString && '  ' + maybeString.replace(/\n/g, '\n  ');
  }
  
  function isMultiline(string) {
    return string.indexOf('\n') !== -1;
  }
  
  function hasMultilineItems(maybeArray) {
    return maybeArray && maybeArray.some(isMultiline);
  }
  
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
  
  function unwrapExports (x) {
  	return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
  }
  
  function createCommonjsModule(fn, module) {
  	return module = { exports: {} }, fn(module, module.exports), module.exports;
  }
  
  function getCjsExportFromNamespace (n) {
  	return n && n['default'] || n;
  }
  
  function commonjsRequire () {
  	throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
  }
  
  var lodash_isequal = createCommonjsModule(function (module, exports) {
  /**
   * Lodash (Custom Build) <https://lodash.com/>
   * Build: `lodash modularize exports="npm" -o ./`
   * Copyright JS Foundation and other contributors <https://js.foundation/>
   * Released under MIT license <https://lodash.com/license>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   */
  
  /** Used as the size to enable large array optimizations. */
  var LARGE_ARRAY_SIZE = 200;
  
  /** Used to stand-in for `undefined` hash values. */
  var HASH_UNDEFINED = '__lodash_hash_undefined__';
  
  /** Used to compose bitmasks for value comparisons. */
  var COMPARE_PARTIAL_FLAG = 1,
      COMPARE_UNORDERED_FLAG = 2;
  
  /** Used as references for various `Number` constants. */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /** `Object#toString` result references. */
  var argsTag = '[object Arguments]',
      arrayTag = '[object Array]',
      asyncTag = '[object AsyncFunction]',
      boolTag = '[object Boolean]',
      dateTag = '[object Date]',
      errorTag = '[object Error]',
      funcTag = '[object Function]',
      genTag = '[object GeneratorFunction]',
      mapTag = '[object Map]',
      numberTag = '[object Number]',
      nullTag = '[object Null]',
      objectTag = '[object Object]',
      promiseTag = '[object Promise]',
      proxyTag = '[object Proxy]',
      regexpTag = '[object RegExp]',
      setTag = '[object Set]',
      stringTag = '[object String]',
      symbolTag = '[object Symbol]',
      undefinedTag = '[object Undefined]',
      weakMapTag = '[object WeakMap]';
  
  var arrayBufferTag = '[object ArrayBuffer]',
      dataViewTag = '[object DataView]',
      float32Tag = '[object Float32Array]',
      float64Tag = '[object Float64Array]',
      int8Tag = '[object Int8Array]',
      int16Tag = '[object Int16Array]',
      int32Tag = '[object Int32Array]',
      uint8Tag = '[object Uint8Array]',
      uint8ClampedTag = '[object Uint8ClampedArray]',
      uint16Tag = '[object Uint16Array]',
      uint32Tag = '[object Uint32Array]';
  
  /**
   * Used to match `RegExp`
   * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
   */
  var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
  
  /** Used to detect host constructors (Safari). */
  var reIsHostCtor = /^\[object .+?Constructor\]$/;
  
  /** Used to detect unsigned integer values. */
  var reIsUint = /^(?:0|[1-9]\d*)$/;
  
  /** Used to identify `toStringTag` values of typed arrays. */
  var typedArrayTags = {};
  typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
  typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
  typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
  typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
  typedArrayTags[uint32Tag] = true;
  typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
  typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
  typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
  typedArrayTags[errorTag] = typedArrayTags[funcTag] =
  typedArrayTags[mapTag] = typedArrayTags[numberTag] =
  typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
  typedArrayTags[setTag] = typedArrayTags[stringTag] =
  typedArrayTags[weakMapTag] = false;
  
  /** Detect free variable `global` from Node.js. */
  var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
  
  /** Detect free variable `self`. */
  var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
  
  /** Used as a reference to the global object. */
  var root = freeGlobal || freeSelf || Function('return this')();
  
  /** Detect free variable `exports`. */
  var freeExports =  exports && !exports.nodeType && exports;
  
  /** Detect free variable `module`. */
  var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
  
  /** Detect the popular CommonJS extension `module.exports`. */
  var moduleExports = freeModule && freeModule.exports === freeExports;
  
  /** Detect free variable `process` from Node.js. */
  var freeProcess = moduleExports && freeGlobal.process;
  
  /** Used to access faster Node.js helpers. */
  var nodeUtil = (function() {
    try {
      return freeProcess && freeProcess.binding && freeProcess.binding('util');
    } catch (e) {}
  }());
  
  /* Node.js helper references. */
  var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
  
  /**
   * A specialized version of `_.filter` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} predicate The function invoked per iteration.
   * @returns {Array} Returns the new filtered array.
   */
  function arrayFilter(array, predicate) {
    var index = -1,
        length = array == null ? 0 : array.length,
        resIndex = 0,
        result = [];
  
    while (++index < length) {
      var value = array[index];
      if (predicate(value, index, array)) {
        result[resIndex++] = value;
      }
    }
    return result;
  }
  
  /**
   * Appends the elements of `values` to `array`.
   *
   * @private
   * @param {Array} array The array to modify.
   * @param {Array} values The values to append.
   * @returns {Array} Returns `array`.
   */
  function arrayPush(array, values) {
    var index = -1,
        length = values.length,
        offset = array.length;
  
    while (++index < length) {
      array[offset + index] = values[index];
    }
    return array;
  }
  
  /**
   * A specialized version of `_.some` for arrays without support for iteratee
   * shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} predicate The function invoked per iteration.
   * @returns {boolean} Returns `true` if any element passes the predicate check,
   *  else `false`.
   */
  function arraySome(array, predicate) {
    var index = -1,
        length = array == null ? 0 : array.length;
  
    while (++index < length) {
      if (predicate(array[index], index, array)) {
        return true;
      }
    }
    return false;
  }
  
  /**
   * The base implementation of `_.times` without support for iteratee shorthands
   * or max array length checks.
   *
   * @private
   * @param {number} n The number of times to invoke `iteratee`.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns the array of results.
   */
  function baseTimes(n, iteratee) {
    var index = -1,
        result = Array(n);
  
    while (++index < n) {
      result[index] = iteratee(index);
    }
    return result;
  }
  
  /**
   * The base implementation of `_.unary` without support for storing metadata.
   *
   * @private
   * @param {Function} func The function to cap arguments for.
   * @returns {Function} Returns the new capped function.
   */
  function baseUnary(func) {
    return function(value) {
      return func(value);
    };
  }
  
  /**
   * Checks if a `cache` value for `key` exists.
   *
   * @private
   * @param {Object} cache The cache to query.
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function cacheHas(cache, key) {
    return cache.has(key);
  }
  
  /**
   * Gets the value at `key` of `object`.
   *
   * @private
   * @param {Object} [object] The object to query.
   * @param {string} key The key of the property to get.
   * @returns {*} Returns the property value.
   */
  function getValue(object, key) {
    return object == null ? undefined : object[key];
  }
  
  /**
   * Converts `map` to its key-value pairs.
   *
   * @private
   * @param {Object} map The map to convert.
   * @returns {Array} Returns the key-value pairs.
   */
  function mapToArray(map) {
    var index = -1,
        result = Array(map.size);
  
    map.forEach(function(value, key) {
      result[++index] = [key, value];
    });
    return result;
  }
  
  /**
   * Creates a unary function that invokes `func` with its argument transformed.
   *
   * @private
   * @param {Function} func The function to wrap.
   * @param {Function} transform The argument transform.
   * @returns {Function} Returns the new function.
   */
  function overArg(func, transform) {
    return function(arg) {
      return func(transform(arg));
    };
  }
  
  /**
   * Converts `set` to an array of its values.
   *
   * @private
   * @param {Object} set The set to convert.
   * @returns {Array} Returns the values.
   */
  function setToArray(set) {
    var index = -1,
        result = Array(set.size);
  
    set.forEach(function(value) {
      result[++index] = value;
    });
    return result;
  }
  
  /** Used for built-in method references. */
  var arrayProto = Array.prototype,
      funcProto = Function.prototype,
      objectProto = Object.prototype;
  
  /** Used to detect overreaching core-js shims. */
  var coreJsData = root['__core-js_shared__'];
  
  /** Used to resolve the decompiled source of functions. */
  var funcToString = funcProto.toString;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /** Used to detect methods masquerading as native. */
  var maskSrcKey = (function() {
    var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
    return uid ? ('Symbol(src)_1.' + uid) : '';
  }());
  
  /**
   * Used to resolve the
   * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
   * of values.
   */
  var nativeObjectToString = objectProto.toString;
  
  /** Used to detect if a method is native. */
  var reIsNative = RegExp('^' +
    funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
    .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );
  
  /** Built-in value references. */
  var Buffer = moduleExports ? root.Buffer : undefined,
      Symbol = root.Symbol,
      Uint8Array = root.Uint8Array,
      propertyIsEnumerable = objectProto.propertyIsEnumerable,
      splice = arrayProto.splice,
      symToStringTag = Symbol ? Symbol.toStringTag : undefined;
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeGetSymbols = Object.getOwnPropertySymbols,
      nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
      nativeKeys = overArg(Object.keys, Object);
  
  /* Built-in method references that are verified to be native. */
  var DataView = getNative(root, 'DataView'),
      Map = getNative(root, 'Map'),
      Promise = getNative(root, 'Promise'),
      Set = getNative(root, 'Set'),
      WeakMap = getNative(root, 'WeakMap'),
      nativeCreate = getNative(Object, 'create');
  
  /** Used to detect maps, sets, and weakmaps. */
  var dataViewCtorString = toSource(DataView),
      mapCtorString = toSource(Map),
      promiseCtorString = toSource(Promise),
      setCtorString = toSource(Set),
      weakMapCtorString = toSource(WeakMap);
  
  /** Used to convert symbols to primitives and strings. */
  var symbolProto = Symbol ? Symbol.prototype : undefined,
      symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
  
  /**
   * Creates a hash object.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function Hash(entries) {
    var index = -1,
        length = entries == null ? 0 : entries.length;
  
    this.clear();
    while (++index < length) {
      var entry = entries[index];
      this.set(entry[0], entry[1]);
    }
  }
  
  /**
   * Removes all key-value entries from the hash.
   *
   * @private
   * @name clear
   * @memberOf Hash
   */
  function hashClear() {
    this.__data__ = nativeCreate ? nativeCreate(null) : {};
    this.size = 0;
  }
  
  /**
   * Removes `key` and its value from the hash.
   *
   * @private
   * @name delete
   * @memberOf Hash
   * @param {Object} hash The hash to modify.
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function hashDelete(key) {
    var result = this.has(key) && delete this.__data__[key];
    this.size -= result ? 1 : 0;
    return result;
  }
  
  /**
   * Gets the hash value for `key`.
   *
   * @private
   * @name get
   * @memberOf Hash
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function hashGet(key) {
    var data = this.__data__;
    if (nativeCreate) {
      var result = data[key];
      return result === HASH_UNDEFINED ? undefined : result;
    }
    return hasOwnProperty.call(data, key) ? data[key] : undefined;
  }
  
  /**
   * Checks if a hash value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf Hash
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function hashHas(key) {
    var data = this.__data__;
    return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key);
  }
  
  /**
   * Sets the hash `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf Hash
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the hash instance.
   */
  function hashSet(key, value) {
    var data = this.__data__;
    this.size += this.has(key) ? 0 : 1;
    data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
    return this;
  }
  
  // Add methods to `Hash`.
  Hash.prototype.clear = hashClear;
  Hash.prototype['delete'] = hashDelete;
  Hash.prototype.get = hashGet;
  Hash.prototype.has = hashHas;
  Hash.prototype.set = hashSet;
  
  /**
   * Creates an list cache object.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function ListCache(entries) {
    var index = -1,
        length = entries == null ? 0 : entries.length;
  
    this.clear();
    while (++index < length) {
      var entry = entries[index];
      this.set(entry[0], entry[1]);
    }
  }
  
  /**
   * Removes all key-value entries from the list cache.
   *
   * @private
   * @name clear
   * @memberOf ListCache
   */
  function listCacheClear() {
    this.__data__ = [];
    this.size = 0;
  }
  
  /**
   * Removes `key` and its value from the list cache.
   *
   * @private
   * @name delete
   * @memberOf ListCache
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function listCacheDelete(key) {
    var data = this.__data__,
        index = assocIndexOf(data, key);
  
    if (index < 0) {
      return false;
    }
    var lastIndex = data.length - 1;
    if (index == lastIndex) {
      data.pop();
    } else {
      splice.call(data, index, 1);
    }
    --this.size;
    return true;
  }
  
  /**
   * Gets the list cache value for `key`.
   *
   * @private
   * @name get
   * @memberOf ListCache
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function listCacheGet(key) {
    var data = this.__data__,
        index = assocIndexOf(data, key);
  
    return index < 0 ? undefined : data[index][1];
  }
  
  /**
   * Checks if a list cache value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf ListCache
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function listCacheHas(key) {
    return assocIndexOf(this.__data__, key) > -1;
  }
  
  /**
   * Sets the list cache `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf ListCache
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the list cache instance.
   */
  function listCacheSet(key, value) {
    var data = this.__data__,
        index = assocIndexOf(data, key);
  
    if (index < 0) {
      ++this.size;
      data.push([key, value]);
    } else {
      data[index][1] = value;
    }
    return this;
  }
  
  // Add methods to `ListCache`.
  ListCache.prototype.clear = listCacheClear;
  ListCache.prototype['delete'] = listCacheDelete;
  ListCache.prototype.get = listCacheGet;
  ListCache.prototype.has = listCacheHas;
  ListCache.prototype.set = listCacheSet;
  
  /**
   * Creates a map cache object to store key-value pairs.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function MapCache(entries) {
    var index = -1,
        length = entries == null ? 0 : entries.length;
  
    this.clear();
    while (++index < length) {
      var entry = entries[index];
      this.set(entry[0], entry[1]);
    }
  }
  
  /**
   * Removes all key-value entries from the map.
   *
   * @private
   * @name clear
   * @memberOf MapCache
   */
  function mapCacheClear() {
    this.size = 0;
    this.__data__ = {
      'hash': new Hash,
      'map': new (Map || ListCache),
      'string': new Hash
    };
  }
  
  /**
   * Removes `key` and its value from the map.
   *
   * @private
   * @name delete
   * @memberOf MapCache
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function mapCacheDelete(key) {
    var result = getMapData(this, key)['delete'](key);
    this.size -= result ? 1 : 0;
    return result;
  }
  
  /**
   * Gets the map value for `key`.
   *
   * @private
   * @name get
   * @memberOf MapCache
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function mapCacheGet(key) {
    return getMapData(this, key).get(key);
  }
  
  /**
   * Checks if a map value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf MapCache
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function mapCacheHas(key) {
    return getMapData(this, key).has(key);
  }
  
  /**
   * Sets the map `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf MapCache
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the map cache instance.
   */
  function mapCacheSet(key, value) {
    var data = getMapData(this, key),
        size = data.size;
  
    data.set(key, value);
    this.size += data.size == size ? 0 : 1;
    return this;
  }
  
  // Add methods to `MapCache`.
  MapCache.prototype.clear = mapCacheClear;
  MapCache.prototype['delete'] = mapCacheDelete;
  MapCache.prototype.get = mapCacheGet;
  MapCache.prototype.has = mapCacheHas;
  MapCache.prototype.set = mapCacheSet;
  
  /**
   *
   * Creates an array cache object to store unique values.
   *
   * @private
   * @constructor
   * @param {Array} [values] The values to cache.
   */
  function SetCache(values) {
    var index = -1,
        length = values == null ? 0 : values.length;
  
    this.__data__ = new MapCache;
    while (++index < length) {
      this.add(values[index]);
    }
  }
  
  /**
   * Adds `value` to the array cache.
   *
   * @private
   * @name add
   * @memberOf SetCache
   * @alias push
   * @param {*} value The value to cache.
   * @returns {Object} Returns the cache instance.
   */
  function setCacheAdd(value) {
    this.__data__.set(value, HASH_UNDEFINED);
    return this;
  }
  
  /**
   * Checks if `value` is in the array cache.
   *
   * @private
   * @name has
   * @memberOf SetCache
   * @param {*} value The value to search for.
   * @returns {number} Returns `true` if `value` is found, else `false`.
   */
  function setCacheHas(value) {
    return this.__data__.has(value);
  }
  
  // Add methods to `SetCache`.
  SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
  SetCache.prototype.has = setCacheHas;
  
  /**
   * Creates a stack cache object to store key-value pairs.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function Stack(entries) {
    var data = this.__data__ = new ListCache(entries);
    this.size = data.size;
  }
  
  /**
   * Removes all key-value entries from the stack.
   *
   * @private
   * @name clear
   * @memberOf Stack
   */
  function stackClear() {
    this.__data__ = new ListCache;
    this.size = 0;
  }
  
  /**
   * Removes `key` and its value from the stack.
   *
   * @private
   * @name delete
   * @memberOf Stack
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function stackDelete(key) {
    var data = this.__data__,
        result = data['delete'](key);
  
    this.size = data.size;
    return result;
  }
  
  /**
   * Gets the stack value for `key`.
   *
   * @private
   * @name get
   * @memberOf Stack
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function stackGet(key) {
    return this.__data__.get(key);
  }
  
  /**
   * Checks if a stack value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf Stack
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function stackHas(key) {
    return this.__data__.has(key);
  }
  
  /**
   * Sets the stack `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf Stack
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the stack cache instance.
   */
  function stackSet(key, value) {
    var data = this.__data__;
    if (data instanceof ListCache) {
      var pairs = data.__data__;
      if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
        pairs.push([key, value]);
        this.size = ++data.size;
        return this;
      }
      data = this.__data__ = new MapCache(pairs);
    }
    data.set(key, value);
    this.size = data.size;
    return this;
  }
  
  // Add methods to `Stack`.
  Stack.prototype.clear = stackClear;
  Stack.prototype['delete'] = stackDelete;
  Stack.prototype.get = stackGet;
  Stack.prototype.has = stackHas;
  Stack.prototype.set = stackSet;
  
  /**
   * Creates an array of the enumerable property names of the array-like `value`.
   *
   * @private
   * @param {*} value The value to query.
   * @param {boolean} inherited Specify returning inherited property names.
   * @returns {Array} Returns the array of property names.
   */
  function arrayLikeKeys(value, inherited) {
    var isArr = isArray(value),
        isArg = !isArr && isArguments(value),
        isBuff = !isArr && !isArg && isBuffer(value),
        isType = !isArr && !isArg && !isBuff && isTypedArray(value),
        skipIndexes = isArr || isArg || isBuff || isType,
        result = skipIndexes ? baseTimes(value.length, String) : [],
        length = result.length;
  
    for (var key in value) {
      if ((inherited || hasOwnProperty.call(value, key)) &&
          !(skipIndexes && (
             // Safari 9 has enumerable `arguments.length` in strict mode.
             key == 'length' ||
             // Node.js 0.10 has enumerable non-index properties on buffers.
             (isBuff && (key == 'offset' || key == 'parent')) ||
             // PhantomJS 2 has enumerable non-index properties on typed arrays.
             (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
             // Skip index properties.
             isIndex(key, length)
          ))) {
        result.push(key);
      }
    }
    return result;
  }
  
  /**
   * Gets the index at which the `key` is found in `array` of key-value pairs.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} key The key to search for.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function assocIndexOf(array, key) {
    var length = array.length;
    while (length--) {
      if (eq(array[length][0], key)) {
        return length;
      }
    }
    return -1;
  }
  
  /**
   * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
   * `keysFunc` and `symbolsFunc` to get the enumerable property names and
   * symbols of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {Function} keysFunc The function to get the keys of `object`.
   * @param {Function} symbolsFunc The function to get the symbols of `object`.
   * @returns {Array} Returns the array of property names and symbols.
   */
  function baseGetAllKeys(object, keysFunc, symbolsFunc) {
    var result = keysFunc(object);
    return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
  }
  
  /**
   * The base implementation of `getTag` without fallbacks for buggy environments.
   *
   * @private
   * @param {*} value The value to query.
   * @returns {string} Returns the `toStringTag`.
   */
  function baseGetTag(value) {
    if (value == null) {
      return value === undefined ? undefinedTag : nullTag;
    }
    return (symToStringTag && symToStringTag in Object(value))
      ? getRawTag(value)
      : objectToString(value);
  }
  
  /**
   * The base implementation of `_.isArguments`.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an `arguments` object,
   */
  function baseIsArguments(value) {
    return isObjectLike(value) && baseGetTag(value) == argsTag;
  }
  
  /**
   * The base implementation of `_.isEqual` which supports partial comparisons
   * and tracks traversed objects.
   *
   * @private
   * @param {*} value The value to compare.
   * @param {*} other The other value to compare.
   * @param {boolean} bitmask The bitmask flags.
   *  1 - Unordered comparison
   *  2 - Partial comparison
   * @param {Function} [customizer] The function to customize comparisons.
   * @param {Object} [stack] Tracks traversed `value` and `other` objects.
   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
   */
  function baseIsEqual(value, other, bitmask, customizer, stack) {
    if (value === other) {
      return true;
    }
    if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) {
      return value !== value && other !== other;
    }
    return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
  }
  
  /**
   * A specialized version of `baseIsEqual` for arrays and objects which performs
   * deep comparisons and tracks traversed objects enabling objects with circular
   * references to be compared.
   *
   * @private
   * @param {Object} object The object to compare.
   * @param {Object} other The other object to compare.
   * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
   * @param {Function} customizer The function to customize comparisons.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Object} [stack] Tracks traversed `object` and `other` objects.
   * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
   */
  function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
    var objIsArr = isArray(object),
        othIsArr = isArray(other),
        objTag = objIsArr ? arrayTag : getTag(object),
        othTag = othIsArr ? arrayTag : getTag(other);
  
    objTag = objTag == argsTag ? objectTag : objTag;
    othTag = othTag == argsTag ? objectTag : othTag;
  
    var objIsObj = objTag == objectTag,
        othIsObj = othTag == objectTag,
        isSameTag = objTag == othTag;
  
    if (isSameTag && isBuffer(object)) {
      if (!isBuffer(other)) {
        return false;
      }
      objIsArr = true;
      objIsObj = false;
    }
    if (isSameTag && !objIsObj) {
      stack || (stack = new Stack);
      return (objIsArr || isTypedArray(object))
        ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
        : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
    }
    if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
      var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
          othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
  
      if (objIsWrapped || othIsWrapped) {
        var objUnwrapped = objIsWrapped ? object.value() : object,
            othUnwrapped = othIsWrapped ? other.value() : other;
  
        stack || (stack = new Stack);
        return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
      }
    }
    if (!isSameTag) {
      return false;
    }
    stack || (stack = new Stack);
    return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
  }
  
  /**
   * The base implementation of `_.isNative` without bad shim checks.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a native function,
   *  else `false`.
   */
  function baseIsNative(value) {
    if (!isObject(value) || isMasked(value)) {
      return false;
    }
    var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
    return pattern.test(toSource(value));
  }
  
  /**
   * The base implementation of `_.isTypedArray` without Node.js optimizations.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
   */
  function baseIsTypedArray(value) {
    return isObjectLike(value) &&
      isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
  }
  
  /**
   * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   */
  function baseKeys(object) {
    if (!isPrototype(object)) {
      return nativeKeys(object);
    }
    var result = [];
    for (var key in Object(object)) {
      if (hasOwnProperty.call(object, key) && key != 'constructor') {
        result.push(key);
      }
    }
    return result;
  }
  
  /**
   * A specialized version of `baseIsEqualDeep` for arrays with support for
   * partial deep comparisons.
   *
   * @private
   * @param {Array} array The array to compare.
   * @param {Array} other The other array to compare.
   * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
   * @param {Function} customizer The function to customize comparisons.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Object} stack Tracks traversed `array` and `other` objects.
   * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
   */
  function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
    var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
        arrLength = array.length,
        othLength = other.length;
  
    if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
      return false;
    }
    // Assume cyclic values are equal.
    var stacked = stack.get(array);
    if (stacked && stack.get(other)) {
      return stacked == other;
    }
    var index = -1,
        result = true,
        seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
  
    stack.set(array, other);
    stack.set(other, array);
  
    // Ignore non-index properties.
    while (++index < arrLength) {
      var arrValue = array[index],
          othValue = other[index];
  
      if (customizer) {
        var compared = isPartial
          ? customizer(othValue, arrValue, index, other, array, stack)
          : customizer(arrValue, othValue, index, array, other, stack);
      }
      if (compared !== undefined) {
        if (compared) {
          continue;
        }
        result = false;
        break;
      }
      // Recursively compare arrays (susceptible to call stack limits).
      if (seen) {
        if (!arraySome(other, function(othValue, othIndex) {
              if (!cacheHas(seen, othIndex) &&
                  (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
                return seen.push(othIndex);
              }
            })) {
          result = false;
          break;
        }
      } else if (!(
            arrValue === othValue ||
              equalFunc(arrValue, othValue, bitmask, customizer, stack)
          )) {
        result = false;
        break;
      }
    }
    stack['delete'](array);
    stack['delete'](other);
    return result;
  }
  
  /**
   * A specialized version of `baseIsEqualDeep` for comparing objects of
   * the same `toStringTag`.
   *
   * **Note:** This function only supports comparing values with tags of
   * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
   *
   * @private
   * @param {Object} object The object to compare.
   * @param {Object} other The other object to compare.
   * @param {string} tag The `toStringTag` of the objects to compare.
   * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
   * @param {Function} customizer The function to customize comparisons.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Object} stack Tracks traversed `object` and `other` objects.
   * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
   */
  function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
    switch (tag) {
      case dataViewTag:
        if ((object.byteLength != other.byteLength) ||
            (object.byteOffset != other.byteOffset)) {
          return false;
        }
        object = object.buffer;
        other = other.buffer;
  
      case arrayBufferTag:
        if ((object.byteLength != other.byteLength) ||
            !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
          return false;
        }
        return true;
  
      case boolTag:
      case dateTag:
      case numberTag:
        // Coerce booleans to `1` or `0` and dates to milliseconds.
        // Invalid dates are coerced to `NaN`.
        return eq(+object, +other);
  
      case errorTag:
        return object.name == other.name && object.message == other.message;
  
      case regexpTag:
      case stringTag:
        // Coerce regexes to strings and treat strings, primitives and objects,
        // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
        // for more details.
        return object == (other + '');
  
      case mapTag:
        var convert = mapToArray;
  
      case setTag:
        var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
        convert || (convert = setToArray);
  
        if (object.size != other.size && !isPartial) {
          return false;
        }
        // Assume cyclic values are equal.
        var stacked = stack.get(object);
        if (stacked) {
          return stacked == other;
        }
        bitmask |= COMPARE_UNORDERED_FLAG;
  
        // Recursively compare objects (susceptible to call stack limits).
        stack.set(object, other);
        var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
        stack['delete'](object);
        return result;
  
      case symbolTag:
        if (symbolValueOf) {
          return symbolValueOf.call(object) == symbolValueOf.call(other);
        }
    }
    return false;
  }
  
  /**
   * A specialized version of `baseIsEqualDeep` for objects with support for
   * partial deep comparisons.
   *
   * @private
   * @param {Object} object The object to compare.
   * @param {Object} other The other object to compare.
   * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
   * @param {Function} customizer The function to customize comparisons.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Object} stack Tracks traversed `object` and `other` objects.
   * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
   */
  function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
    var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
        objProps = getAllKeys(object),
        objLength = objProps.length,
        othProps = getAllKeys(other),
        othLength = othProps.length;
  
    if (objLength != othLength && !isPartial) {
      return false;
    }
    var index = objLength;
    while (index--) {
      var key = objProps[index];
      if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
        return false;
      }
    }
    // Assume cyclic values are equal.
    var stacked = stack.get(object);
    if (stacked && stack.get(other)) {
      return stacked == other;
    }
    var result = true;
    stack.set(object, other);
    stack.set(other, object);
  
    var skipCtor = isPartial;
    while (++index < objLength) {
      key = objProps[index];
      var objValue = object[key],
          othValue = other[key];
  
      if (customizer) {
        var compared = isPartial
          ? customizer(othValue, objValue, key, other, object, stack)
          : customizer(objValue, othValue, key, object, other, stack);
      }
      // Recursively compare objects (susceptible to call stack limits).
      if (!(compared === undefined
            ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
            : compared
          )) {
        result = false;
        break;
      }
      skipCtor || (skipCtor = key == 'constructor');
    }
    if (result && !skipCtor) {
      var objCtor = object.constructor,
          othCtor = other.constructor;
  
      // Non `Object` object instances with different constructors are not equal.
      if (objCtor != othCtor &&
          ('constructor' in object && 'constructor' in other) &&
          !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
            typeof othCtor == 'function' && othCtor instanceof othCtor)) {
        result = false;
      }
    }
    stack['delete'](object);
    stack['delete'](other);
    return result;
  }
  
  /**
   * Creates an array of own enumerable property names and symbols of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names and symbols.
   */
  function getAllKeys(object) {
    return baseGetAllKeys(object, keys, getSymbols);
  }
  
  /**
   * Gets the data for `map`.
   *
   * @private
   * @param {Object} map The map to query.
   * @param {string} key The reference key.
   * @returns {*} Returns the map data.
   */
  function getMapData(map, key) {
    var data = map.__data__;
    return isKeyable(key)
      ? data[typeof key == 'string' ? 'string' : 'hash']
      : data.map;
  }
  
  /**
   * Gets the native function at `key` of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {string} key The key of the method to get.
   * @returns {*} Returns the function if it's native, else `undefined`.
   */
  function getNative(object, key) {
    var value = getValue(object, key);
    return baseIsNative(value) ? value : undefined;
  }
  
  /**
   * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
   *
   * @private
   * @param {*} value The value to query.
   * @returns {string} Returns the raw `toStringTag`.
   */
  function getRawTag(value) {
    var isOwn = hasOwnProperty.call(value, symToStringTag),
        tag = value[symToStringTag];
  
    try {
      value[symToStringTag] = undefined;
      var unmasked = true;
    } catch (e) {}
  
    var result = nativeObjectToString.call(value);
    if (unmasked) {
      if (isOwn) {
        value[symToStringTag] = tag;
      } else {
        delete value[symToStringTag];
      }
    }
    return result;
  }
  
  /**
   * Creates an array of the own enumerable symbols of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of symbols.
   */
  var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
    if (object == null) {
      return [];
    }
    object = Object(object);
    return arrayFilter(nativeGetSymbols(object), function(symbol) {
      return propertyIsEnumerable.call(object, symbol);
    });
  };
  
  /**
   * Gets the `toStringTag` of `value`.
   *
   * @private
   * @param {*} value The value to query.
   * @returns {string} Returns the `toStringTag`.
   */
  var getTag = baseGetTag;
  
  // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
  if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
      (Map && getTag(new Map) != mapTag) ||
      (Promise && getTag(Promise.resolve()) != promiseTag) ||
      (Set && getTag(new Set) != setTag) ||
      (WeakMap && getTag(new WeakMap) != weakMapTag)) {
    getTag = function(value) {
      var result = baseGetTag(value),
          Ctor = result == objectTag ? value.constructor : undefined,
          ctorString = Ctor ? toSource(Ctor) : '';
  
      if (ctorString) {
        switch (ctorString) {
          case dataViewCtorString: return dataViewTag;
          case mapCtorString: return mapTag;
          case promiseCtorString: return promiseTag;
          case setCtorString: return setTag;
          case weakMapCtorString: return weakMapTag;
        }
      }
      return result;
    };
  }
  
  /**
   * Checks if `value` is a valid array-like index.
   *
   * @private
   * @param {*} value The value to check.
   * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
   * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
   */
  function isIndex(value, length) {
    length = length == null ? MAX_SAFE_INTEGER : length;
    return !!length &&
      (typeof value == 'number' || reIsUint.test(value)) &&
      (value > -1 && value % 1 == 0 && value < length);
  }
  
  /**
   * Checks if `value` is suitable for use as unique object key.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
   */
  function isKeyable(value) {
    var type = typeof value;
    return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
      ? (value !== '__proto__')
      : (value === null);
  }
  
  /**
   * Checks if `func` has its source masked.
   *
   * @private
   * @param {Function} func The function to check.
   * @returns {boolean} Returns `true` if `func` is masked, else `false`.
   */
  function isMasked(func) {
    return !!maskSrcKey && (maskSrcKey in func);
  }
  
  /**
   * Checks if `value` is likely a prototype object.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
   */
  function isPrototype(value) {
    var Ctor = value && value.constructor,
        proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
  
    return value === proto;
  }
  
  /**
   * Converts `value` to a string using `Object.prototype.toString`.
   *
   * @private
   * @param {*} value The value to convert.
   * @returns {string} Returns the converted string.
   */
  function objectToString(value) {
    return nativeObjectToString.call(value);
  }
  
  /**
   * Converts `func` to its source code.
   *
   * @private
   * @param {Function} func The function to convert.
   * @returns {string} Returns the source code.
   */
  function toSource(func) {
    if (func != null) {
      try {
        return funcToString.call(func);
      } catch (e) {}
      try {
        return (func + '');
      } catch (e) {}
    }
    return '';
  }
  
  /**
   * Performs a
   * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
   * comparison between two values to determine if they are equivalent.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to compare.
   * @param {*} other The other value to compare.
   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
   * @example
   *
   * var object = { 'a': 1 };
   * var other = { 'a': 1 };
   *
   * _.eq(object, object);
   * // => true
   *
   * _.eq(object, other);
   * // => false
   *
   * _.eq('a', 'a');
   * // => true
   *
   * _.eq('a', Object('a'));
   * // => false
   *
   * _.eq(NaN, NaN);
   * // => true
   */
  function eq(value, other) {
    return value === other || (value !== value && other !== other);
  }
  
  /**
   * Checks if `value` is likely an `arguments` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an `arguments` object,
   *  else `false`.
   * @example
   *
   * _.isArguments(function() { return arguments; }());
   * // => true
   *
   * _.isArguments([1, 2, 3]);
   * // => false
   */
  var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
    return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
      !propertyIsEnumerable.call(value, 'callee');
  };
  
  /**
   * Checks if `value` is classified as an `Array` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an array, else `false`.
   * @example
   *
   * _.isArray([1, 2, 3]);
   * // => true
   *
   * _.isArray(document.body.children);
   * // => false
   *
   * _.isArray('abc');
   * // => false
   *
   * _.isArray(_.noop);
   * // => false
   */
  var isArray = Array.isArray;
  
  /**
   * Checks if `value` is array-like. A value is considered array-like if it's
   * not a function and has a `value.length` that's an integer greater than or
   * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
   * @example
   *
   * _.isArrayLike([1, 2, 3]);
   * // => true
   *
   * _.isArrayLike(document.body.children);
   * // => true
   *
   * _.isArrayLike('abc');
   * // => true
   *
   * _.isArrayLike(_.noop);
   * // => false
   */
  function isArrayLike(value) {
    return value != null && isLength(value.length) && !isFunction(value);
  }
  
  /**
   * Checks if `value` is a buffer.
   *
   * @static
   * @memberOf _
   * @since 4.3.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
   * @example
   *
   * _.isBuffer(new Buffer(2));
   * // => true
   *
   * _.isBuffer(new Uint8Array(2));
   * // => false
   */
  var isBuffer = nativeIsBuffer || stubFalse;
  
  /**
   * Performs a deep comparison between two values to determine if they are
   * equivalent.
   *
   * **Note:** This method supports comparing arrays, array buffers, booleans,
   * date objects, error objects, maps, numbers, `Object` objects, regexes,
   * sets, strings, symbols, and typed arrays. `Object` objects are compared
   * by their own, not inherited, enumerable properties. Functions and DOM
   * nodes are compared by strict equality, i.e. `===`.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to compare.
   * @param {*} other The other value to compare.
   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
   * @example
   *
   * var object = { 'a': 1 };
   * var other = { 'a': 1 };
   *
   * _.isEqual(object, other);
   * // => true
   *
   * object === other;
   * // => false
   */
  function isEqual(value, other) {
    return baseIsEqual(value, other);
  }
  
  /**
   * Checks if `value` is classified as a `Function` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a function, else `false`.
   * @example
   *
   * _.isFunction(_);
   * // => true
   *
   * _.isFunction(/abc/);
   * // => false
   */
  function isFunction(value) {
    if (!isObject(value)) {
      return false;
    }
    // The use of `Object#toString` avoids issues with the `typeof` operator
    // in Safari 9 which returns 'object' for typed arrays and other constructors.
    var tag = baseGetTag(value);
    return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
  }
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This method is loosely based on
   * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
   * @example
   *
   * _.isLength(3);
   * // => true
   *
   * _.isLength(Number.MIN_VALUE);
   * // => false
   *
   * _.isLength(Infinity);
   * // => false
   *
   * _.isLength('3');
   * // => false
   */
  function isLength(value) {
    return typeof value == 'number' &&
      value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  /**
   * Checks if `value` is the
   * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
   * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(_.noop);
   * // => true
   *
   * _.isObject(null);
   * // => false
   */
  function isObject(value) {
    var type = typeof value;
    return value != null && (type == 'object' || type == 'function');
  }
  
  /**
   * Checks if `value` is object-like. A value is object-like if it's not `null`
   * and has a `typeof` result of "object".
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   * @example
   *
   * _.isObjectLike({});
   * // => true
   *
   * _.isObjectLike([1, 2, 3]);
   * // => true
   *
   * _.isObjectLike(_.noop);
   * // => false
   *
   * _.isObjectLike(null);
   * // => false
   */
  function isObjectLike(value) {
    return value != null && typeof value == 'object';
  }
  
  /**
   * Checks if `value` is classified as a typed array.
   *
   * @static
   * @memberOf _
   * @since 3.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
   * @example
   *
   * _.isTypedArray(new Uint8Array);
   * // => true
   *
   * _.isTypedArray([]);
   * // => false
   */
  var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
  
  /**
   * Creates an array of the own enumerable property names of `object`.
   *
   * **Note:** Non-object values are coerced to objects. See the
   * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
   * for more details.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Object
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.keys(new Foo);
   * // => ['a', 'b'] (iteration order is not guaranteed)
   *
   * _.keys('hi');
   * // => ['0', '1']
   */
  function keys(object) {
    return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
  }
  
  /**
   * This method returns a new empty array.
   *
   * @static
   * @memberOf _
   * @since 4.13.0
   * @category Util
   * @returns {Array} Returns the new empty array.
   * @example
   *
   * var arrays = _.times(2, _.stubArray);
   *
   * console.log(arrays);
   * // => [[], []]
   *
   * console.log(arrays[0] === arrays[1]);
   * // => false
   */
  function stubArray() {
    return [];
  }
  
  /**
   * This method returns `false`.
   *
   * @static
   * @memberOf _
   * @since 4.13.0
   * @category Util
   * @returns {boolean} Returns `false`.
   * @example
   *
   * _.times(2, _.stubFalse);
   * // => [false, false]
   */
  function stubFalse() {
    return false;
  }
  
  module.exports = isEqual;
  });
  
  var lodash_clone = createCommonjsModule(function (module, exports) {
  /**
   * lodash (Custom Build) <https://lodash.com/>
   * Build: `lodash modularize exports="npm" -o ./`
   * Copyright jQuery Foundation and other contributors <https://jquery.org/>
   * Released under MIT license <https://lodash.com/license>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   */
  
  /** Used as the size to enable large array optimizations. */
  var LARGE_ARRAY_SIZE = 200;
  
  /** Used to stand-in for `undefined` hash values. */
  var HASH_UNDEFINED = '__lodash_hash_undefined__';
  
  /** Used as references for various `Number` constants. */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /** `Object#toString` result references. */
  var argsTag = '[object Arguments]',
      arrayTag = '[object Array]',
      boolTag = '[object Boolean]',
      dateTag = '[object Date]',
      errorTag = '[object Error]',
      funcTag = '[object Function]',
      genTag = '[object GeneratorFunction]',
      mapTag = '[object Map]',
      numberTag = '[object Number]',
      objectTag = '[object Object]',
      promiseTag = '[object Promise]',
      regexpTag = '[object RegExp]',
      setTag = '[object Set]',
      stringTag = '[object String]',
      symbolTag = '[object Symbol]',
      weakMapTag = '[object WeakMap]';
  
  var arrayBufferTag = '[object ArrayBuffer]',
      dataViewTag = '[object DataView]',
      float32Tag = '[object Float32Array]',
      float64Tag = '[object Float64Array]',
      int8Tag = '[object Int8Array]',
      int16Tag = '[object Int16Array]',
      int32Tag = '[object Int32Array]',
      uint8Tag = '[object Uint8Array]',
      uint8ClampedTag = '[object Uint8ClampedArray]',
      uint16Tag = '[object Uint16Array]',
      uint32Tag = '[object Uint32Array]';
  
  /**
   * Used to match `RegExp`
   * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
   */
  var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
  
  /** Used to match `RegExp` flags from their coerced string values. */
  var reFlags = /\w*$/;
  
  /** Used to detect host constructors (Safari). */
  var reIsHostCtor = /^\[object .+?Constructor\]$/;
  
  /** Used to detect unsigned integer values. */
  var reIsUint = /^(?:0|[1-9]\d*)$/;
  
  /** Used to identify `toStringTag` values supported by `_.clone`. */
  var cloneableTags = {};
  cloneableTags[argsTag] = cloneableTags[arrayTag] =
  cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
  cloneableTags[boolTag] = cloneableTags[dateTag] =
  cloneableTags[float32Tag] = cloneableTags[float64Tag] =
  cloneableTags[int8Tag] = cloneableTags[int16Tag] =
  cloneableTags[int32Tag] = cloneableTags[mapTag] =
  cloneableTags[numberTag] = cloneableTags[objectTag] =
  cloneableTags[regexpTag] = cloneableTags[setTag] =
  cloneableTags[stringTag] = cloneableTags[symbolTag] =
  cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
  cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
  cloneableTags[errorTag] = cloneableTags[funcTag] =
  cloneableTags[weakMapTag] = false;
  
  /** Detect free variable `global` from Node.js. */
  var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
  
  /** Detect free variable `self`. */
  var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
  
  /** Used as a reference to the global object. */
  var root = freeGlobal || freeSelf || Function('return this')();
  
  /** Detect free variable `exports`. */
  var freeExports =  exports && !exports.nodeType && exports;
  
  /** Detect free variable `module`. */
  var freeModule = freeExports && 'object' == 'object' && module && !module.nodeType && module;
  
  /** Detect the popular CommonJS extension `module.exports`. */
  var moduleExports = freeModule && freeModule.exports === freeExports;
  
  /**
   * Adds the key-value `pair` to `map`.
   *
   * @private
   * @param {Object} map The map to modify.
   * @param {Array} pair The key-value pair to add.
   * @returns {Object} Returns `map`.
   */
  function addMapEntry(map, pair) {
    // Don't return `map.set` because it's not chainable in IE 11.
    map.set(pair[0], pair[1]);
    return map;
  }
  
  /**
   * Adds `value` to `set`.
   *
   * @private
   * @param {Object} set The set to modify.
   * @param {*} value The value to add.
   * @returns {Object} Returns `set`.
   */
  function addSetEntry(set, value) {
    // Don't return `set.add` because it's not chainable in IE 11.
    set.add(value);
    return set;
  }
  
  /**
   * A specialized version of `_.forEach` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns `array`.
   */
  function arrayEach(array, iteratee) {
    var index = -1,
        length = array ? array.length : 0;
  
    while (++index < length) {
      if (iteratee(array[index], index, array) === false) {
        break;
      }
    }
    return array;
  }
  
  /**
   * Appends the elements of `values` to `array`.
   *
   * @private
   * @param {Array} array The array to modify.
   * @param {Array} values The values to append.
   * @returns {Array} Returns `array`.
   */
  function arrayPush(array, values) {
    var index = -1,
        length = values.length,
        offset = array.length;
  
    while (++index < length) {
      array[offset + index] = values[index];
    }
    return array;
  }
  
  /**
   * A specialized version of `_.reduce` for arrays without support for
   * iteratee shorthands.
   *
   * @private
   * @param {Array} [array] The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @param {*} [accumulator] The initial value.
   * @param {boolean} [initAccum] Specify using the first element of `array` as
   *  the initial value.
   * @returns {*} Returns the accumulated value.
   */
  function arrayReduce(array, iteratee, accumulator, initAccum) {
    var index = -1,
        length = array ? array.length : 0;
  
    if (initAccum && length) {
      accumulator = array[++index];
    }
    while (++index < length) {
      accumulator = iteratee(accumulator, array[index], index, array);
    }
    return accumulator;
  }
  
  /**
   * The base implementation of `_.times` without support for iteratee shorthands
   * or max array length checks.
   *
   * @private
   * @param {number} n The number of times to invoke `iteratee`.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns the array of results.
   */
  function baseTimes(n, iteratee) {
    var index = -1,
        result = Array(n);
  
    while (++index < n) {
      result[index] = iteratee(index);
    }
    return result;
  }
  
  /**
   * Gets the value at `key` of `object`.
   *
   * @private
   * @param {Object} [object] The object to query.
   * @param {string} key The key of the property to get.
   * @returns {*} Returns the property value.
   */
  function getValue(object, key) {
    return object == null ? undefined : object[key];
  }
  
  /**
   * Checks if `value` is a host object in IE < 9.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
   */
  function isHostObject(value) {
    // Many host objects are `Object` objects that can coerce to strings
    // despite having improperly defined `toString` methods.
    var result = false;
    if (value != null && typeof value.toString != 'function') {
      try {
        result = !!(value + '');
      } catch (e) {}
    }
    return result;
  }
  
  /**
   * Converts `map` to its key-value pairs.
   *
   * @private
   * @param {Object} map The map to convert.
   * @returns {Array} Returns the key-value pairs.
   */
  function mapToArray(map) {
    var index = -1,
        result = Array(map.size);
  
    map.forEach(function(value, key) {
      result[++index] = [key, value];
    });
    return result;
  }
  
  /**
   * Creates a unary function that invokes `func` with its argument transformed.
   *
   * @private
   * @param {Function} func The function to wrap.
   * @param {Function} transform The argument transform.
   * @returns {Function} Returns the new function.
   */
  function overArg(func, transform) {
    return function(arg) {
      return func(transform(arg));
    };
  }
  
  /**
   * Converts `set` to an array of its values.
   *
   * @private
   * @param {Object} set The set to convert.
   * @returns {Array} Returns the values.
   */
  function setToArray(set) {
    var index = -1,
        result = Array(set.size);
  
    set.forEach(function(value) {
      result[++index] = value;
    });
    return result;
  }
  
  /** Used for built-in method references. */
  var arrayProto = Array.prototype,
      funcProto = Function.prototype,
      objectProto = Object.prototype;
  
  /** Used to detect overreaching core-js shims. */
  var coreJsData = root['__core-js_shared__'];
  
  /** Used to detect methods masquerading as native. */
  var maskSrcKey = (function() {
    var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
    return uid ? ('Symbol(src)_1.' + uid) : '';
  }());
  
  /** Used to resolve the decompiled source of functions. */
  var funcToString = funcProto.toString;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Used to resolve the
   * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
   * of values.
   */
  var objectToString = objectProto.toString;
  
  /** Used to detect if a method is native. */
  var reIsNative = RegExp('^' +
    funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
    .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );
  
  /** Built-in value references. */
  var Buffer = moduleExports ? root.Buffer : undefined,
      Symbol = root.Symbol,
      Uint8Array = root.Uint8Array,
      getPrototype = overArg(Object.getPrototypeOf, Object),
      objectCreate = Object.create,
      propertyIsEnumerable = objectProto.propertyIsEnumerable,
      splice = arrayProto.splice;
  
  /* Built-in method references for those with the same name as other `lodash` methods. */
  var nativeGetSymbols = Object.getOwnPropertySymbols,
      nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
      nativeKeys = overArg(Object.keys, Object);
  
  /* Built-in method references that are verified to be native. */
  var DataView = getNative(root, 'DataView'),
      Map = getNative(root, 'Map'),
      Promise = getNative(root, 'Promise'),
      Set = getNative(root, 'Set'),
      WeakMap = getNative(root, 'WeakMap'),
      nativeCreate = getNative(Object, 'create');
  
  /** Used to detect maps, sets, and weakmaps. */
  var dataViewCtorString = toSource(DataView),
      mapCtorString = toSource(Map),
      promiseCtorString = toSource(Promise),
      setCtorString = toSource(Set),
      weakMapCtorString = toSource(WeakMap);
  
  /** Used to convert symbols to primitives and strings. */
  var symbolProto = Symbol ? Symbol.prototype : undefined,
      symbolValueOf = symbolProto ? symbolProto.valueOf : undefined;
  
  /**
   * Creates a hash object.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function Hash(entries) {
    var index = -1,
        length = entries ? entries.length : 0;
  
    this.clear();
    while (++index < length) {
      var entry = entries[index];
      this.set(entry[0], entry[1]);
    }
  }
  
  /**
   * Removes all key-value entries from the hash.
   *
   * @private
   * @name clear
   * @memberOf Hash
   */
  function hashClear() {
    this.__data__ = nativeCreate ? nativeCreate(null) : {};
  }
  
  /**
   * Removes `key` and its value from the hash.
   *
   * @private
   * @name delete
   * @memberOf Hash
   * @param {Object} hash The hash to modify.
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function hashDelete(key) {
    return this.has(key) && delete this.__data__[key];
  }
  
  /**
   * Gets the hash value for `key`.
   *
   * @private
   * @name get
   * @memberOf Hash
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function hashGet(key) {
    var data = this.__data__;
    if (nativeCreate) {
      var result = data[key];
      return result === HASH_UNDEFINED ? undefined : result;
    }
    return hasOwnProperty.call(data, key) ? data[key] : undefined;
  }
  
  /**
   * Checks if a hash value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf Hash
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function hashHas(key) {
    var data = this.__data__;
    return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
  }
  
  /**
   * Sets the hash `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf Hash
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the hash instance.
   */
  function hashSet(key, value) {
    var data = this.__data__;
    data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
    return this;
  }
  
  // Add methods to `Hash`.
  Hash.prototype.clear = hashClear;
  Hash.prototype['delete'] = hashDelete;
  Hash.prototype.get = hashGet;
  Hash.prototype.has = hashHas;
  Hash.prototype.set = hashSet;
  
  /**
   * Creates an list cache object.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function ListCache(entries) {
    var index = -1,
        length = entries ? entries.length : 0;
  
    this.clear();
    while (++index < length) {
      var entry = entries[index];
      this.set(entry[0], entry[1]);
    }
  }
  
  /**
   * Removes all key-value entries from the list cache.
   *
   * @private
   * @name clear
   * @memberOf ListCache
   */
  function listCacheClear() {
    this.__data__ = [];
  }
  
  /**
   * Removes `key` and its value from the list cache.
   *
   * @private
   * @name delete
   * @memberOf ListCache
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function listCacheDelete(key) {
    var data = this.__data__,
        index = assocIndexOf(data, key);
  
    if (index < 0) {
      return false;
    }
    var lastIndex = data.length - 1;
    if (index == lastIndex) {
      data.pop();
    } else {
      splice.call(data, index, 1);
    }
    return true;
  }
  
  /**
   * Gets the list cache value for `key`.
   *
   * @private
   * @name get
   * @memberOf ListCache
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function listCacheGet(key) {
    var data = this.__data__,
        index = assocIndexOf(data, key);
  
    return index < 0 ? undefined : data[index][1];
  }
  
  /**
   * Checks if a list cache value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf ListCache
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function listCacheHas(key) {
    return assocIndexOf(this.__data__, key) > -1;
  }
  
  /**
   * Sets the list cache `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf ListCache
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the list cache instance.
   */
  function listCacheSet(key, value) {
    var data = this.__data__,
        index = assocIndexOf(data, key);
  
    if (index < 0) {
      data.push([key, value]);
    } else {
      data[index][1] = value;
    }
    return this;
  }
  
  // Add methods to `ListCache`.
  ListCache.prototype.clear = listCacheClear;
  ListCache.prototype['delete'] = listCacheDelete;
  ListCache.prototype.get = listCacheGet;
  ListCache.prototype.has = listCacheHas;
  ListCache.prototype.set = listCacheSet;
  
  /**
   * Creates a map cache object to store key-value pairs.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function MapCache(entries) {
    var index = -1,
        length = entries ? entries.length : 0;
  
    this.clear();
    while (++index < length) {
      var entry = entries[index];
      this.set(entry[0], entry[1]);
    }
  }
  
  /**
   * Removes all key-value entries from the map.
   *
   * @private
   * @name clear
   * @memberOf MapCache
   */
  function mapCacheClear() {
    this.__data__ = {
      'hash': new Hash,
      'map': new (Map || ListCache),
      'string': new Hash
    };
  }
  
  /**
   * Removes `key` and its value from the map.
   *
   * @private
   * @name delete
   * @memberOf MapCache
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function mapCacheDelete(key) {
    return getMapData(this, key)['delete'](key);
  }
  
  /**
   * Gets the map value for `key`.
   *
   * @private
   * @name get
   * @memberOf MapCache
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function mapCacheGet(key) {
    return getMapData(this, key).get(key);
  }
  
  /**
   * Checks if a map value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf MapCache
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function mapCacheHas(key) {
    return getMapData(this, key).has(key);
  }
  
  /**
   * Sets the map `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf MapCache
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the map cache instance.
   */
  function mapCacheSet(key, value) {
    getMapData(this, key).set(key, value);
    return this;
  }
  
  // Add methods to `MapCache`.
  MapCache.prototype.clear = mapCacheClear;
  MapCache.prototype['delete'] = mapCacheDelete;
  MapCache.prototype.get = mapCacheGet;
  MapCache.prototype.has = mapCacheHas;
  MapCache.prototype.set = mapCacheSet;
  
  /**
   * Creates a stack cache object to store key-value pairs.
   *
   * @private
   * @constructor
   * @param {Array} [entries] The key-value pairs to cache.
   */
  function Stack(entries) {
    this.__data__ = new ListCache(entries);
  }
  
  /**
   * Removes all key-value entries from the stack.
   *
   * @private
   * @name clear
   * @memberOf Stack
   */
  function stackClear() {
    this.__data__ = new ListCache;
  }
  
  /**
   * Removes `key` and its value from the stack.
   *
   * @private
   * @name delete
   * @memberOf Stack
   * @param {string} key The key of the value to remove.
   * @returns {boolean} Returns `true` if the entry was removed, else `false`.
   */
  function stackDelete(key) {
    return this.__data__['delete'](key);
  }
  
  /**
   * Gets the stack value for `key`.
   *
   * @private
   * @name get
   * @memberOf Stack
   * @param {string} key The key of the value to get.
   * @returns {*} Returns the entry value.
   */
  function stackGet(key) {
    return this.__data__.get(key);
  }
  
  /**
   * Checks if a stack value for `key` exists.
   *
   * @private
   * @name has
   * @memberOf Stack
   * @param {string} key The key of the entry to check.
   * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
   */
  function stackHas(key) {
    return this.__data__.has(key);
  }
  
  /**
   * Sets the stack `key` to `value`.
   *
   * @private
   * @name set
   * @memberOf Stack
   * @param {string} key The key of the value to set.
   * @param {*} value The value to set.
   * @returns {Object} Returns the stack cache instance.
   */
  function stackSet(key, value) {
    var cache = this.__data__;
    if (cache instanceof ListCache) {
      var pairs = cache.__data__;
      if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
        pairs.push([key, value]);
        return this;
      }
      cache = this.__data__ = new MapCache(pairs);
    }
    cache.set(key, value);
    return this;
  }
  
  // Add methods to `Stack`.
  Stack.prototype.clear = stackClear;
  Stack.prototype['delete'] = stackDelete;
  Stack.prototype.get = stackGet;
  Stack.prototype.has = stackHas;
  Stack.prototype.set = stackSet;
  
  /**
   * Creates an array of the enumerable property names of the array-like `value`.
   *
   * @private
   * @param {*} value The value to query.
   * @param {boolean} inherited Specify returning inherited property names.
   * @returns {Array} Returns the array of property names.
   */
  function arrayLikeKeys(value, inherited) {
    // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
    // Safari 9 makes `arguments.length` enumerable in strict mode.
    var result = (isArray(value) || isArguments(value))
      ? baseTimes(value.length, String)
      : [];
  
    var length = result.length,
        skipIndexes = !!length;
  
    for (var key in value) {
      if ((inherited || hasOwnProperty.call(value, key)) &&
          !(skipIndexes && (key == 'length' || isIndex(key, length)))) {
        result.push(key);
      }
    }
    return result;
  }
  
  /**
   * Assigns `value` to `key` of `object` if the existing value is not equivalent
   * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
   * for equality comparisons.
   *
   * @private
   * @param {Object} object The object to modify.
   * @param {string} key The key of the property to assign.
   * @param {*} value The value to assign.
   */
  function assignValue(object, key, value) {
    var objValue = object[key];
    if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
        (value === undefined && !(key in object))) {
      object[key] = value;
    }
  }
  
  /**
   * Gets the index at which the `key` is found in `array` of key-value pairs.
   *
   * @private
   * @param {Array} array The array to inspect.
   * @param {*} key The key to search for.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function assocIndexOf(array, key) {
    var length = array.length;
    while (length--) {
      if (eq(array[length][0], key)) {
        return length;
      }
    }
    return -1;
  }
  
  /**
   * The base implementation of `_.assign` without support for multiple sources
   * or `customizer` functions.
   *
   * @private
   * @param {Object} object The destination object.
   * @param {Object} source The source object.
   * @returns {Object} Returns `object`.
   */
  function baseAssign(object, source) {
    return object && copyObject(source, keys(source), object);
  }
  
  /**
   * The base implementation of `_.clone` and `_.cloneDeep` which tracks
   * traversed objects.
   *
   * @private
   * @param {*} value The value to clone.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @param {boolean} [isFull] Specify a clone including symbols.
   * @param {Function} [customizer] The function to customize cloning.
   * @param {string} [key] The key of `value`.
   * @param {Object} [object] The parent object of `value`.
   * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
   * @returns {*} Returns the cloned value.
   */
  function baseClone(value, isDeep, isFull, customizer, key, object, stack) {
    var result;
    if (customizer) {
      result = object ? customizer(value, key, object, stack) : customizer(value);
    }
    if (result !== undefined) {
      return result;
    }
    if (!isObject(value)) {
      return value;
    }
    var isArr = isArray(value);
    if (isArr) {
      result = initCloneArray(value);
      if (!isDeep) {
        return copyArray(value, result);
      }
    } else {
      var tag = getTag(value),
          isFunc = tag == funcTag || tag == genTag;
  
      if (isBuffer(value)) {
        return cloneBuffer(value, isDeep);
      }
      if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
        if (isHostObject(value)) {
          return object ? value : {};
        }
        result = initCloneObject(isFunc ? {} : value);
        if (!isDeep) {
          return copySymbols(value, baseAssign(result, value));
        }
      } else {
        if (!cloneableTags[tag]) {
          return object ? value : {};
        }
        result = initCloneByTag(value, tag, baseClone, isDeep);
      }
    }
    // Check for circular references and return its corresponding clone.
    stack || (stack = new Stack);
    var stacked = stack.get(value);
    if (stacked) {
      return stacked;
    }
    stack.set(value, result);
  
    if (!isArr) {
      var props = isFull ? getAllKeys(value) : keys(value);
    }
    arrayEach(props || value, function(subValue, key) {
      if (props) {
        key = subValue;
        subValue = value[key];
      }
      // Recursively populate clone (susceptible to call stack limits).
      assignValue(result, key, baseClone(subValue, isDeep, isFull, customizer, key, value, stack));
    });
    return result;
  }
  
  /**
   * The base implementation of `_.create` without support for assigning
   * properties to the created object.
   *
   * @private
   * @param {Object} prototype The object to inherit from.
   * @returns {Object} Returns the new object.
   */
  function baseCreate(proto) {
    return isObject(proto) ? objectCreate(proto) : {};
  }
  
  /**
   * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
   * `keysFunc` and `symbolsFunc` to get the enumerable property names and
   * symbols of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {Function} keysFunc The function to get the keys of `object`.
   * @param {Function} symbolsFunc The function to get the symbols of `object`.
   * @returns {Array} Returns the array of property names and symbols.
   */
  function baseGetAllKeys(object, keysFunc, symbolsFunc) {
    var result = keysFunc(object);
    return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
  }
  
  /**
   * The base implementation of `getTag`.
   *
   * @private
   * @param {*} value The value to query.
   * @returns {string} Returns the `toStringTag`.
   */
  function baseGetTag(value) {
    return objectToString.call(value);
  }
  
  /**
   * The base implementation of `_.isNative` without bad shim checks.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a native function,
   *  else `false`.
   */
  function baseIsNative(value) {
    if (!isObject(value) || isMasked(value)) {
      return false;
    }
    var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
    return pattern.test(toSource(value));
  }
  
  /**
   * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   */
  function baseKeys(object) {
    if (!isPrototype(object)) {
      return nativeKeys(object);
    }
    var result = [];
    for (var key in Object(object)) {
      if (hasOwnProperty.call(object, key) && key != 'constructor') {
        result.push(key);
      }
    }
    return result;
  }
  
  /**
   * Creates a clone of  `buffer`.
   *
   * @private
   * @param {Buffer} buffer The buffer to clone.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Buffer} Returns the cloned buffer.
   */
  function cloneBuffer(buffer, isDeep) {
    if (isDeep) {
      return buffer.slice();
    }
    var result = new buffer.constructor(buffer.length);
    buffer.copy(result);
    return result;
  }
  
  /**
   * Creates a clone of `arrayBuffer`.
   *
   * @private
   * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
   * @returns {ArrayBuffer} Returns the cloned array buffer.
   */
  function cloneArrayBuffer(arrayBuffer) {
    var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
    new Uint8Array(result).set(new Uint8Array(arrayBuffer));
    return result;
  }
  
  /**
   * Creates a clone of `dataView`.
   *
   * @private
   * @param {Object} dataView The data view to clone.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Object} Returns the cloned data view.
   */
  function cloneDataView(dataView, isDeep) {
    var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
    return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
  }
  
  /**
   * Creates a clone of `map`.
   *
   * @private
   * @param {Object} map The map to clone.
   * @param {Function} cloneFunc The function to clone values.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Object} Returns the cloned map.
   */
  function cloneMap(map, isDeep, cloneFunc) {
    var array = isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map);
    return arrayReduce(array, addMapEntry, new map.constructor);
  }
  
  /**
   * Creates a clone of `regexp`.
   *
   * @private
   * @param {Object} regexp The regexp to clone.
   * @returns {Object} Returns the cloned regexp.
   */
  function cloneRegExp(regexp) {
    var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
    result.lastIndex = regexp.lastIndex;
    return result;
  }
  
  /**
   * Creates a clone of `set`.
   *
   * @private
   * @param {Object} set The set to clone.
   * @param {Function} cloneFunc The function to clone values.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Object} Returns the cloned set.
   */
  function cloneSet(set, isDeep, cloneFunc) {
    var array = isDeep ? cloneFunc(setToArray(set), true) : setToArray(set);
    return arrayReduce(array, addSetEntry, new set.constructor);
  }
  
  /**
   * Creates a clone of the `symbol` object.
   *
   * @private
   * @param {Object} symbol The symbol object to clone.
   * @returns {Object} Returns the cloned symbol object.
   */
  function cloneSymbol(symbol) {
    return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
  }
  
  /**
   * Creates a clone of `typedArray`.
   *
   * @private
   * @param {Object} typedArray The typed array to clone.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Object} Returns the cloned typed array.
   */
  function cloneTypedArray(typedArray, isDeep) {
    var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
    return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
  }
  
  /**
   * Copies the values of `source` to `array`.
   *
   * @private
   * @param {Array} source The array to copy values from.
   * @param {Array} [array=[]] The array to copy values to.
   * @returns {Array} Returns `array`.
   */
  function copyArray(source, array) {
    var index = -1,
        length = source.length;
  
    array || (array = Array(length));
    while (++index < length) {
      array[index] = source[index];
    }
    return array;
  }
  
  /**
   * Copies properties of `source` to `object`.
   *
   * @private
   * @param {Object} source The object to copy properties from.
   * @param {Array} props The property identifiers to copy.
   * @param {Object} [object={}] The object to copy properties to.
   * @param {Function} [customizer] The function to customize copied values.
   * @returns {Object} Returns `object`.
   */
  function copyObject(source, props, object, customizer) {
    object || (object = {});
  
    var index = -1,
        length = props.length;
  
    while (++index < length) {
      var key = props[index];
  
      var newValue = customizer
        ? customizer(object[key], source[key], key, object, source)
        : undefined;
  
      assignValue(object, key, newValue === undefined ? source[key] : newValue);
    }
    return object;
  }
  
  /**
   * Copies own symbol properties of `source` to `object`.
   *
   * @private
   * @param {Object} source The object to copy symbols from.
   * @param {Object} [object={}] The object to copy symbols to.
   * @returns {Object} Returns `object`.
   */
  function copySymbols(source, object) {
    return copyObject(source, getSymbols(source), object);
  }
  
  /**
   * Creates an array of own enumerable property names and symbols of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names and symbols.
   */
  function getAllKeys(object) {
    return baseGetAllKeys(object, keys, getSymbols);
  }
  
  /**
   * Gets the data for `map`.
   *
   * @private
   * @param {Object} map The map to query.
   * @param {string} key The reference key.
   * @returns {*} Returns the map data.
   */
  function getMapData(map, key) {
    var data = map.__data__;
    return isKeyable(key)
      ? data[typeof key == 'string' ? 'string' : 'hash']
      : data.map;
  }
  
  /**
   * Gets the native function at `key` of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {string} key The key of the method to get.
   * @returns {*} Returns the function if it's native, else `undefined`.
   */
  function getNative(object, key) {
    var value = getValue(object, key);
    return baseIsNative(value) ? value : undefined;
  }
  
  /**
   * Creates an array of the own enumerable symbol properties of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of symbols.
   */
  var getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray;
  
  /**
   * Gets the `toStringTag` of `value`.
   *
   * @private
   * @param {*} value The value to query.
   * @returns {string} Returns the `toStringTag`.
   */
  var getTag = baseGetTag;
  
  // Fallback for data views, maps, sets, and weak maps in IE 11,
  // for data views in Edge < 14, and promises in Node.js.
  if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
      (Map && getTag(new Map) != mapTag) ||
      (Promise && getTag(Promise.resolve()) != promiseTag) ||
      (Set && getTag(new Set) != setTag) ||
      (WeakMap && getTag(new WeakMap) != weakMapTag)) {
    getTag = function(value) {
      var result = objectToString.call(value),
          Ctor = result == objectTag ? value.constructor : undefined,
          ctorString = Ctor ? toSource(Ctor) : undefined;
  
      if (ctorString) {
        switch (ctorString) {
          case dataViewCtorString: return dataViewTag;
          case mapCtorString: return mapTag;
          case promiseCtorString: return promiseTag;
          case setCtorString: return setTag;
          case weakMapCtorString: return weakMapTag;
        }
      }
      return result;
    };
  }
  
  /**
   * Initializes an array clone.
   *
   * @private
   * @param {Array} array The array to clone.
   * @returns {Array} Returns the initialized clone.
   */
  function initCloneArray(array) {
    var length = array.length,
        result = array.constructor(length);
  
    // Add properties assigned by `RegExp#exec`.
    if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
      result.index = array.index;
      result.input = array.input;
    }
    return result;
  }
  
  /**
   * Initializes an object clone.
   *
   * @private
   * @param {Object} object The object to clone.
   * @returns {Object} Returns the initialized clone.
   */
  function initCloneObject(object) {
    return (typeof object.constructor == 'function' && !isPrototype(object))
      ? baseCreate(getPrototype(object))
      : {};
  }
  
  /**
   * Initializes an object clone based on its `toStringTag`.
   *
   * **Note:** This function only supports cloning values with tags of
   * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
   *
   * @private
   * @param {Object} object The object to clone.
   * @param {string} tag The `toStringTag` of the object to clone.
   * @param {Function} cloneFunc The function to clone values.
   * @param {boolean} [isDeep] Specify a deep clone.
   * @returns {Object} Returns the initialized clone.
   */
  function initCloneByTag(object, tag, cloneFunc, isDeep) {
    var Ctor = object.constructor;
    switch (tag) {
      case arrayBufferTag:
        return cloneArrayBuffer(object);
  
      case boolTag:
      case dateTag:
        return new Ctor(+object);
  
      case dataViewTag:
        return cloneDataView(object, isDeep);
  
      case float32Tag: case float64Tag:
      case int8Tag: case int16Tag: case int32Tag:
      case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
        return cloneTypedArray(object, isDeep);
  
      case mapTag:
        return cloneMap(object, isDeep, cloneFunc);
  
      case numberTag:
      case stringTag:
        return new Ctor(object);
  
      case regexpTag:
        return cloneRegExp(object);
  
      case setTag:
        return cloneSet(object, isDeep, cloneFunc);
  
      case symbolTag:
        return cloneSymbol(object);
    }
  }
  
  /**
   * Checks if `value` is a valid array-like index.
   *
   * @private
   * @param {*} value The value to check.
   * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
   * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
   */
  function isIndex(value, length) {
    length = length == null ? MAX_SAFE_INTEGER : length;
    return !!length &&
      (typeof value == 'number' || reIsUint.test(value)) &&
      (value > -1 && value % 1 == 0 && value < length);
  }
  
  /**
   * Checks if `value` is suitable for use as unique object key.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
   */
  function isKeyable(value) {
    var type = typeof value;
    return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
      ? (value !== '__proto__')
      : (value === null);
  }
  
  /**
   * Checks if `func` has its source masked.
   *
   * @private
   * @param {Function} func The function to check.
   * @returns {boolean} Returns `true` if `func` is masked, else `false`.
   */
  function isMasked(func) {
    return !!maskSrcKey && (maskSrcKey in func);
  }
  
  /**
   * Checks if `value` is likely a prototype object.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
   */
  function isPrototype(value) {
    var Ctor = value && value.constructor,
        proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
  
    return value === proto;
  }
  
  /**
   * Converts `func` to its source code.
   *
   * @private
   * @param {Function} func The function to process.
   * @returns {string} Returns the source code.
   */
  function toSource(func) {
    if (func != null) {
      try {
        return funcToString.call(func);
      } catch (e) {}
      try {
        return (func + '');
      } catch (e) {}
    }
    return '';
  }
  
  /**
   * Creates a shallow clone of `value`.
   *
   * **Note:** This method is loosely based on the
   * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
   * and supports cloning arrays, array buffers, booleans, date objects, maps,
   * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
   * arrays. The own enumerable properties of `arguments` objects are cloned
   * as plain objects. An empty object is returned for uncloneable values such
   * as error objects, functions, DOM nodes, and WeakMaps.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to clone.
   * @returns {*} Returns the cloned value.
   * @see _.cloneDeep
   * @example
   *
   * var objects = [{ 'a': 1 }, { 'b': 2 }];
   *
   * var shallow = _.clone(objects);
   * console.log(shallow[0] === objects[0]);
   * // => true
   */
  function clone(value) {
    return baseClone(value, false, true);
  }
  
  /**
   * Performs a
   * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
   * comparison between two values to determine if they are equivalent.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to compare.
   * @param {*} other The other value to compare.
   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
   * @example
   *
   * var object = { 'a': 1 };
   * var other = { 'a': 1 };
   *
   * _.eq(object, object);
   * // => true
   *
   * _.eq(object, other);
   * // => false
   *
   * _.eq('a', 'a');
   * // => true
   *
   * _.eq('a', Object('a'));
   * // => false
   *
   * _.eq(NaN, NaN);
   * // => true
   */
  function eq(value, other) {
    return value === other || (value !== value && other !== other);
  }
  
  /**
   * Checks if `value` is likely an `arguments` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an `arguments` object,
   *  else `false`.
   * @example
   *
   * _.isArguments(function() { return arguments; }());
   * // => true
   *
   * _.isArguments([1, 2, 3]);
   * // => false
   */
  function isArguments(value) {
    // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
    return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
      (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
  }
  
  /**
   * Checks if `value` is classified as an `Array` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an array, else `false`.
   * @example
   *
   * _.isArray([1, 2, 3]);
   * // => true
   *
   * _.isArray(document.body.children);
   * // => false
   *
   * _.isArray('abc');
   * // => false
   *
   * _.isArray(_.noop);
   * // => false
   */
  var isArray = Array.isArray;
  
  /**
   * Checks if `value` is array-like. A value is considered array-like if it's
   * not a function and has a `value.length` that's an integer greater than or
   * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
   * @example
   *
   * _.isArrayLike([1, 2, 3]);
   * // => true
   *
   * _.isArrayLike(document.body.children);
   * // => true
   *
   * _.isArrayLike('abc');
   * // => true
   *
   * _.isArrayLike(_.noop);
   * // => false
   */
  function isArrayLike(value) {
    return value != null && isLength(value.length) && !isFunction(value);
  }
  
  /**
   * This method is like `_.isArrayLike` except that it also checks if `value`
   * is an object.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an array-like object,
   *  else `false`.
   * @example
   *
   * _.isArrayLikeObject([1, 2, 3]);
   * // => true
   *
   * _.isArrayLikeObject(document.body.children);
   * // => true
   *
   * _.isArrayLikeObject('abc');
   * // => false
   *
   * _.isArrayLikeObject(_.noop);
   * // => false
   */
  function isArrayLikeObject(value) {
    return isObjectLike(value) && isArrayLike(value);
  }
  
  /**
   * Checks if `value` is a buffer.
   *
   * @static
   * @memberOf _
   * @since 4.3.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
   * @example
   *
   * _.isBuffer(new Buffer(2));
   * // => true
   *
   * _.isBuffer(new Uint8Array(2));
   * // => false
   */
  var isBuffer = nativeIsBuffer || stubFalse;
  
  /**
   * Checks if `value` is classified as a `Function` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a function, else `false`.
   * @example
   *
   * _.isFunction(_);
   * // => true
   *
   * _.isFunction(/abc/);
   * // => false
   */
  function isFunction(value) {
    // The use of `Object#toString` avoids issues with the `typeof` operator
    // in Safari 8-9 which returns 'object' for typed array and other constructors.
    var tag = isObject(value) ? objectToString.call(value) : '';
    return tag == funcTag || tag == genTag;
  }
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This method is loosely based on
   * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
   * @example
   *
   * _.isLength(3);
   * // => true
   *
   * _.isLength(Number.MIN_VALUE);
   * // => false
   *
   * _.isLength(Infinity);
   * // => false
   *
   * _.isLength('3');
   * // => false
   */
  function isLength(value) {
    return typeof value == 'number' &&
      value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  /**
   * Checks if `value` is the
   * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
   * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(_.noop);
   * // => true
   *
   * _.isObject(null);
   * // => false
   */
  function isObject(value) {
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  /**
   * Checks if `value` is object-like. A value is object-like if it's not `null`
   * and has a `typeof` result of "object".
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   * @example
   *
   * _.isObjectLike({});
   * // => true
   *
   * _.isObjectLike([1, 2, 3]);
   * // => true
   *
   * _.isObjectLike(_.noop);
   * // => false
   *
   * _.isObjectLike(null);
   * // => false
   */
  function isObjectLike(value) {
    return !!value && typeof value == 'object';
  }
  
  /**
   * Creates an array of the own enumerable property names of `object`.
   *
   * **Note:** Non-object values are coerced to objects. See the
   * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
   * for more details.
   *
   * @static
   * @since 0.1.0
   * @memberOf _
   * @category Object
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.keys(new Foo);
   * // => ['a', 'b'] (iteration order is not guaranteed)
   *
   * _.keys('hi');
   * // => ['0', '1']
   */
  function keys(object) {
    return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
  }
  
  /**
   * This method returns a new empty array.
   *
   * @static
   * @memberOf _
   * @since 4.13.0
   * @category Util
   * @returns {Array} Returns the new empty array.
   * @example
   *
   * var arrays = _.times(2, _.stubArray);
   *
   * console.log(arrays);
   * // => [[], []]
   *
   * console.log(arrays[0] === arrays[1]);
   * // => false
   */
  function stubArray() {
    return [];
  }
  
  /**
   * This method returns `false`.
   *
   * @static
   * @memberOf _
   * @since 4.13.0
   * @category Util
   * @returns {boolean} Returns `false`.
   * @example
   *
   * _.times(2, _.stubFalse);
   * // => [false, false]
   */
  function stubFalse() {
    return false;
  }
  
  module.exports = clone;
  });
  
  var pluralize = createCommonjsModule(function (module, exports) {
  /* global define */
  
  (function (root, pluralize) {
    /* istanbul ignore else */
    if (typeof commonjsRequire === 'function' && 'object' === 'object' && 'object' === 'object') {
      // Node.
      module.exports = pluralize();
    } else {
      // Browser global.
      root.pluralize = pluralize();
    }
  })(commonjsGlobal, function () {
    // Rule storage - pluralize and singularize need to be run sequentially,
    // while other rules can be optimized using an object for instant lookups.
    var pluralRules = [];
    var singularRules = [];
    var uncountables = {};
    var irregularPlurals = {};
    var irregularSingles = {};
  
    /**
     * Sanitize a pluralization rule to a usable regular expression.
     *
     * @param  {(RegExp|string)} rule
     * @return {RegExp}
     */
    function sanitizeRule (rule) {
      if (typeof rule === 'string') {
        return new RegExp('^' + rule + '$', 'i');
      }
  
      return rule;
    }
  
    /**
     * Pass in a word token to produce a function that can replicate the case on
     * another word.
     *
     * @param  {string}   word
     * @param  {string}   token
     * @return {Function}
     */
    function restoreCase (word, token) {
      // Tokens are an exact match.
      if (word === token) return token;
  
      // Upper cased words. E.g. "HELLO".
      if (word === word.toUpperCase()) return token.toUpperCase();
  
      // Title cased words. E.g. "Title".
      if (word[0] === word[0].toUpperCase()) {
        return token.charAt(0).toUpperCase() + token.substr(1).toLowerCase();
      }
  
      // Lower cased words. E.g. "test".
      return token.toLowerCase();
    }
  
    /**
     * Interpolate a regexp string.
     *
     * @param  {string} str
     * @param  {Array}  args
     * @return {string}
     */
    function interpolate (str, args) {
      return str.replace(/\$(\d{1,2})/g, function (match, index) {
        return args[index] || '';
      });
    }
  
    /**
     * Replace a word using a rule.
     *
     * @param  {string} word
     * @param  {Array}  rule
     * @return {string}
     */
    function replace (word, rule) {
      return word.replace(rule[0], function (match, index) {
        var result = interpolate(rule[1], arguments);
  
        if (match === '') {
          return restoreCase(word[index - 1], result);
        }
  
        return restoreCase(match, result);
      });
    }
  
    /**
     * Sanitize a word by passing in the word and sanitization rules.
     *
     * @param  {string}   token
     * @param  {string}   word
     * @param  {Array}    rules
     * @return {string}
     */
    function sanitizeWord (token, word, rules) {
      // Empty string or doesn't need fixing.
      if (!token.length || uncountables.hasOwnProperty(token)) {
        return word;
      }
  
      var len = rules.length;
  
      // Iterate over the sanitization rules and use the first one to match.
      while (len--) {
        var rule = rules[len];
  
        if (rule[0].test(word)) return replace(word, rule);
      }
  
      return word;
    }
  
    /**
     * Replace a word with the updated word.
     *
     * @param  {Object}   replaceMap
     * @param  {Object}   keepMap
     * @param  {Array}    rules
     * @return {Function}
     */
    function replaceWord (replaceMap, keepMap, rules) {
      return function (word) {
        // Get the correct token and case restoration functions.
        var token = word.toLowerCase();
  
        // Check against the keep object map.
        if (keepMap.hasOwnProperty(token)) {
          return restoreCase(word, token);
        }
  
        // Check against the replacement map for a direct word replacement.
        if (replaceMap.hasOwnProperty(token)) {
          return restoreCase(word, replaceMap[token]);
        }
  
        // Run all the rules against the word.
        return sanitizeWord(token, word, rules);
      };
    }
  
    /**
     * Check if a word is part of the map.
     */
    function checkWord (replaceMap, keepMap, rules, bool) {
      return function (word) {
        var token = word.toLowerCase();
  
        if (keepMap.hasOwnProperty(token)) return true;
        if (replaceMap.hasOwnProperty(token)) return false;
  
        return sanitizeWord(token, token, rules) === token;
      };
    }
  
    /**
     * Pluralize or singularize a word based on the passed in count.
     *
     * @param  {string}  word
     * @param  {number}  count
     * @param  {boolean} inclusive
     * @return {string}
     */
    function pluralize (word, count, inclusive) {
      var pluralized = count === 1
        ? pluralize.singular(word) : pluralize.plural(word);
  
      return (inclusive ? count + ' ' : '') + pluralized;
    }
  
    /**
     * Pluralize a word.
     *
     * @type {Function}
     */
    pluralize.plural = replaceWord(
      irregularSingles, irregularPlurals, pluralRules
    );
  
    /**
     * Check if a word is plural.
     *
     * @type {Function}
     */
    pluralize.isPlural = checkWord(
      irregularSingles, irregularPlurals, pluralRules
    );
  
    /**
     * Singularize a word.
     *
     * @type {Function}
     */
    pluralize.singular = replaceWord(
      irregularPlurals, irregularSingles, singularRules
    );
  
    /**
     * Check if a word is singular.
     *
     * @type {Function}
     */
    pluralize.isSingular = checkWord(
      irregularPlurals, irregularSingles, singularRules
    );
  
    /**
     * Add a pluralization rule to the collection.
     *
     * @param {(string|RegExp)} rule
     * @param {string}          replacement
     */
    pluralize.addPluralRule = function (rule, replacement) {
      pluralRules.push([sanitizeRule(rule), replacement]);
    };
  
    /**
     * Add a singularization rule to the collection.
     *
     * @param {(string|RegExp)} rule
     * @param {string}          replacement
     */
    pluralize.addSingularRule = function (rule, replacement) {
      singularRules.push([sanitizeRule(rule), replacement]);
    };
  
    /**
     * Add an uncountable word rule.
     *
     * @param {(string|RegExp)} word
     */
    pluralize.addUncountableRule = function (word) {
      if (typeof word === 'string') {
        uncountables[word.toLowerCase()] = true;
        return;
      }
  
      // Set singular and plural references for the word.
      pluralize.addPluralRule(word, '$0');
      pluralize.addSingularRule(word, '$0');
    };
  
    /**
     * Add an irregular word definition.
     *
     * @param {string} single
     * @param {string} plural
     */
    pluralize.addIrregularRule = function (single, plural) {
      plural = plural.toLowerCase();
      single = single.toLowerCase();
  
      irregularSingles[single] = plural;
      irregularPlurals[plural] = single;
    };
  
    /**
     * Irregular rules.
     */
    [
      // Pronouns.
      ['I', 'we'],
      ['me', 'us'],
      ['he', 'they'],
      ['she', 'they'],
      ['them', 'them'],
      ['myself', 'ourselves'],
      ['yourself', 'yourselves'],
      ['itself', 'themselves'],
      ['herself', 'themselves'],
      ['himself', 'themselves'],
      ['themself', 'themselves'],
      ['is', 'are'],
      ['was', 'were'],
      ['has', 'have'],
      ['this', 'these'],
      ['that', 'those'],
      // Words ending in with a consonant and `o`.
      ['echo', 'echoes'],
      ['dingo', 'dingoes'],
      ['volcano', 'volcanoes'],
      ['tornado', 'tornadoes'],
      ['torpedo', 'torpedoes'],
      // Ends with `us`.
      ['genus', 'genera'],
      ['viscus', 'viscera'],
      // Ends with `ma`.
      ['stigma', 'stigmata'],
      ['stoma', 'stomata'],
      ['dogma', 'dogmata'],
      ['lemma', 'lemmata'],
      ['schema', 'schemata'],
      ['anathema', 'anathemata'],
      // Other irregular rules.
      ['ox', 'oxen'],
      ['axe', 'axes'],
      ['die', 'dice'],
      ['yes', 'yeses'],
      ['foot', 'feet'],
      ['eave', 'eaves'],
      ['goose', 'geese'],
      ['tooth', 'teeth'],
      ['quiz', 'quizzes'],
      ['human', 'humans'],
      ['proof', 'proofs'],
      ['carve', 'carves'],
      ['valve', 'valves'],
      ['looey', 'looies'],
      ['thief', 'thieves'],
      ['groove', 'grooves'],
      ['pickaxe', 'pickaxes'],
      ['whiskey', 'whiskies']
    ].forEach(function (rule) {
      return pluralize.addIrregularRule(rule[0], rule[1]);
    });
  
    /**
     * Pluralization rules.
     */
    [
      [/s?$/i, 's'],
      [/[^\u0000-\u007F]$/i, '$0'],
      [/([^aeiou]ese)$/i, '$1'],
      [/(ax|test)is$/i, '$1es'],
      [/(alias|[^aou]us|tlas|gas|ris)$/i, '$1es'],
      [/(e[mn]u)s?$/i, '$1s'],
      [/([^l]ias|[aeiou]las|[emjzr]as|[iu]am)$/i, '$1'],
      [/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1i'],
      [/(alumn|alg|vertebr)(?:a|ae)$/i, '$1ae'],
      [/(seraph|cherub)(?:im)?$/i, '$1im'],
      [/(her|at|gr)o$/i, '$1oes'],
      [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|automat|quor)(?:a|um)$/i, '$1a'],
      [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)(?:a|on)$/i, '$1a'],
      [/sis$/i, 'ses'],
      [/(?:(kni|wi|li)fe|(ar|l|ea|eo|oa|hoo)f)$/i, '$1$2ves'],
      [/([^aeiouy]|qu)y$/i, '$1ies'],
      [/([^ch][ieo][ln])ey$/i, '$1ies'],
      [/(x|ch|ss|sh|zz)$/i, '$1es'],
      [/(matr|cod|mur|sil|vert|ind|append)(?:ix|ex)$/i, '$1ices'],
      [/(m|l)(?:ice|ouse)$/i, '$1ice'],
      [/(pe)(?:rson|ople)$/i, '$1ople'],
      [/(child)(?:ren)?$/i, '$1ren'],
      [/eaux$/i, '$0'],
      [/m[ae]n$/i, 'men'],
      ['thou', 'you']
    ].forEach(function (rule) {
      return pluralize.addPluralRule(rule[0], rule[1]);
    });
  
    /**
     * Singularization rules.
     */
    [
      [/s$/i, ''],
      [/(ss)$/i, '$1'],
      [/(wi|kni|(?:after|half|high|low|mid|non|night|[^\w]|^)li)ves$/i, '$1fe'],
      [/(ar|(?:wo|[ae])l|[eo][ao])ves$/i, '$1f'],
      [/ies$/i, 'y'],
      [/\b([pl]|zomb|(?:neck|cross)?t|coll|faer|food|gen|goon|group|lass|talk|goal|cut)ies$/i, '$1ie'],
      [/\b(mon|smil)ies$/i, '$1ey'],
      [/(m|l)ice$/i, '$1ouse'],
      [/(seraph|cherub)im$/i, '$1'],
      [/(x|ch|ss|sh|zz|tto|go|cho|alias|[^aou]us|tlas|gas|(?:her|at|gr)o|ris)(?:es)?$/i, '$1'],
      [/(analy|ba|diagno|parenthe|progno|synop|the|empha|cri)(?:sis|ses)$/i, '$1sis'],
      [/(movie|twelve|abuse|e[mn]u)s$/i, '$1'],
      [/(test)(?:is|es)$/i, '$1is'],
      [/(alumn|syllab|octop|vir|radi|nucle|fung|cact|stimul|termin|bacill|foc|uter|loc|strat)(?:us|i)$/i, '$1us'],
      [/(agend|addend|millenni|dat|extrem|bacteri|desiderat|strat|candelabr|errat|ov|symposi|curricul|quor)a$/i, '$1um'],
      [/(apheli|hyperbat|periheli|asyndet|noumen|phenomen|criteri|organ|prolegomen|hedr|automat)a$/i, '$1on'],
      [/(alumn|alg|vertebr)ae$/i, '$1a'],
      [/(cod|mur|sil|vert|ind)ices$/i, '$1ex'],
      [/(matr|append)ices$/i, '$1ix'],
      [/(pe)(rson|ople)$/i, '$1rson'],
      [/(child)ren$/i, '$1'],
      [/(eau)x?$/i, '$1'],
      [/men$/i, 'man']
    ].forEach(function (rule) {
      return pluralize.addSingularRule(rule[0], rule[1]);
    });
  
    /**
     * Uncountable rules.
     */
    [
      // Singular words with no plurals.
      'adulthood',
      'advice',
      'agenda',
      'aid',
      'alcohol',
      'ammo',
      'anime',
      'athletics',
      'audio',
      'bison',
      'blood',
      'bream',
      'buffalo',
      'butter',
      'carp',
      'cash',
      'chassis',
      'chess',
      'clothing',
      'cod',
      'commerce',
      'cooperation',
      'corps',
      'debris',
      'diabetes',
      'digestion',
      'elk',
      'energy',
      'equipment',
      'excretion',
      'expertise',
      'flounder',
      'fun',
      'gallows',
      'garbage',
      'graffiti',
      'headquarters',
      'health',
      'herpes',
      'highjinks',
      'homework',
      'housework',
      'information',
      'jeans',
      'justice',
      'kudos',
      'labour',
      'literature',
      'machinery',
      'mackerel',
      'mail',
      'media',
      'mews',
      'moose',
      'music',
      'manga',
      'news',
      'pike',
      'plankton',
      'pliers',
      'pollution',
      'premises',
      'rain',
      'research',
      'rice',
      'salmon',
      'scissors',
      'series',
      'sewage',
      'shambles',
      'shrimp',
      'species',
      'staff',
      'swine',
      'tennis',
      'traffic',
      'transporation',
      'trout',
      'tuna',
      'wealth',
      'welfare',
      'whiting',
      'wildebeest',
      'wildlife',
      'you',
      // Regexes.
      /[^aeiou]ese$/i, // "chinese", "japanese"
      /deer$/i, // "deer", "reindeer"
      /fish$/i, // "fish", "blowfish", "angelfish"
      /measles$/i,
      /o[iu]s$/i, // "carnivorous"
      /pox$/i, // "chickpox", "smallpox"
      /sheep$/i
    ].forEach(pluralize.addUncountableRule);
  
    return pluralize;
  });
  });
  
  var pluralize$1 = pluralize.plural;
  var singularize = pluralize.singular;
  /**
   * Capitalizes the first letter of the given string.
   *
   * @param {string} input
   * @returns {string}
   */
  function upcaseFirstLetter(input) {
      return input.charAt(0).toUpperCase() + input.slice(1);
  }
  /**
   * Down cases the first letter of the given string.
   *
   * @param {string} input
   * @returns {string}
   */
  function downcaseFirstLetter(input) {
      return input.charAt(0).toLowerCase() + input.slice(1);
  }
  /**
   * Takes a string with a graphql query and formats it. Useful for debug output and the tests.
   * @param {string} query
   * @returns {string}
   */
  function prettify(query) {
      return print(parseQuery(query));
  }
  /**
   * Returns a parsed query as GraphQL AST DocumentNode.
   *
   * @param {string | DocumentNode} query - Query as string or GraphQL AST DocumentNode.
   *
   * @returns {DocumentNode} Query as GraphQL AST DocumentNode.
   */
  function parseQuery(query) {
      return typeof query === "string" ? parse(query) : query;
  }
  /**
   * @param {DocumentNode} query - The GraphQL AST DocumentNode.
   *
   * @returns {string} the GraphQL query within a DocumentNode as a plain string.
   */
  function graphQlDocumentToString(query) {
      return query.loc.source.body;
  }
  /**
   * Tells if a object is just a simple object.
   *
   * @param {any} obj - Value to check.
   */
  function isPlainObject(obj) {
      // Basic check for Type object that's not null
      return obj !== null && !(obj instanceof Array) && typeof obj === "object";
  }
  /**
   * Creates an object composed of the picked `object` properties.
   * @param {object} object - Object.
   * @param {array} props - Properties to pick.
   */
  function pick(object, props) {
      if (!object) {
          return {};
      }
      var index = -1;
      var length = props.length;
      var result = {};
      while (++index < length) {
          var prop = props[index];
          result[prop] = object[prop];
      }
      return result;
  }
  function isEqual(a, b) {
      // Couldn' find a simpler working implementation yet.
      return lodash_isequal(a, b);
  }
  function clone(input) {
      // Couldn' find a simpler working implementation yet.
      return lodash_clone(input);
  }
  function takeWhile(array, predicate) {
      var index = -1;
      while (++index < array.length && predicate(array[index], index, array)) {
          // just increase index
      }
      return array.slice(0, index);
  }
  function removeSymbols(input) {
      return JSON.parse(JSON.stringify(input));
  }
  /**
   * Converts the argument into a number.
   */
  function toPrimaryKey(input) {
      if (input === null)
          return 0;
      if (typeof input === "string" && (input.startsWith("$uid") || isGuid(input))) {
          return input;
      }
      return parseInt(input.toString(), 10);
  }
  function isGuid(value) {
      var regex = /[a-f0-9]{8}(?:-?[a-f0-9]{4}){3}-?[a-f0-9]{12}/i;
      var match = regex.exec(value);
      return match !== null;
  }
  
  /**
   * Vuex-ORM-Apollo Debug Logger.
   * Wraps console and only logs if enabled.
   *
   * Also contains some methods to format graphql queries for the output
   */
  var Logger = /** @class */ (function () {
      /**
       * @constructor
       * @param {boolean} enabled Tells if any logging should happen
       */
      function Logger(enabled) {
          /**
           * Fancy Vuex-ORM-Apollo prefix for all log messages.
           * @type {string[]}
           */
          this.PREFIX = [
              "%c Vuex-ORM: GraphQL Plugin %c",
              "background: #35495e; padding: 1px 0; border-radius: 3px; color: #eee;",
              "background: transparent;"
          ];
          this.enabled = enabled;
          this.log("Logging is enabled.");
      }
      /**
       * Wraps console.group. In TEST env console.log is used instead because console.group doesn't work on CLI.
       * If available console.groupCollapsed will be used instead.
       * @param {Array<any>} messages
       */
      Logger.prototype.group = function () {
          var messages = [];
          for (var _i = 0; _i < arguments.length; _i++) {
              messages[_i] = arguments[_i];
          }
          if (this.enabled) {
              if (console.groupCollapsed) {
                  console.groupCollapsed.apply(console, __spreadArrays(this.PREFIX, messages));
              }
              else {
                  console.log.apply(console, __spreadArrays(this.PREFIX, messages));
              }
          }
      };
      /**
       * Wrapper for console.groupEnd. In TEST env nothing happens because console.groupEnd doesn't work on CLI.
       */
      Logger.prototype.groupEnd = function () {
          if (this.enabled && console.groupEnd)
              console.groupEnd();
      };
      /**
       * Wrapper for console.log.
       * @param {Array<any>} messages
       */
      Logger.prototype.log = function () {
          var messages = [];
          for (var _i = 0; _i < arguments.length; _i++) {
              messages[_i] = arguments[_i];
          }
          if (this.enabled) {
              console.log.apply(console, __spreadArrays(this.PREFIX, messages));
          }
      };
      /**
       * Wrapper for console.warn.
       * @param {Array<any>} messages
       */
      Logger.prototype.warn = function () {
          var messages = [];
          for (var _i = 0; _i < arguments.length; _i++) {
              messages[_i] = arguments[_i];
          }
          if (this.enabled) {
              console.warn.apply(console, __spreadArrays(this.PREFIX, messages));
          }
      };
      /**
       * Logs a graphql query in a readable format and with all information like fetch policy and variables.
       * @param {string | DocumentNode} query
       * @param {Arguments} variables
       * @param {FetchPolicy} fetchPolicy
       */
      Logger.prototype.logQuery = function (query, variables, fetchPolicy) {
          if (this.enabled) {
              try {
                  var prettified = "";
                  if (isPlainObject(query) && query.loc) {
                      prettified = prettify(query.loc.source.body);
                  }
                  else {
                      prettified = prettify(query);
                  }
                  this.group("Sending query:", prettified
                      .split("\n")[1]
                      .replace("{", "")
                      .trim());
                  console.log(prettified);
                  if (variables)
                      console.log("VARIABLES:", variables);
                  if (fetchPolicy)
                      console.log("FETCH POLICY:", fetchPolicy);
                  this.groupEnd();
              }
              catch (e) {
                  console.error("[Vuex-ORM-Apollo] There is a syntax error in the query!", e, query);
              }
          }
      };
      return Logger;
  }());
  
  /**
   * Wrapper around a Vuex-ORM model with some useful methods.
   *
   * Also provides a mock system, to define mocking responses for actions.
   */
  var Model = /** @class */ (function () {
      /**
       * @constructor
       * @param {Model} baseModel The original Vuex-ORM model
       */
      function Model(baseModel) {
          var _this = this;
          /**
           * The fields of the model
           * @type {Map<string, Field>}
           */
          this.fields = new Map();
          /**
           * Container for the mocks.
           * @type {Object}
           */
          this.mocks = {};
          this.baseModel = baseModel;
          // Generate name variants
          this.singularName = this.baseModel["singularName"] || singularize(this.baseModel.entity);
          this.pluralName = this.baseModel["pluralName"] || pluralize$1(this.baseModel.entity);
          // Cache the fields of the model in this.fields
          var fields = this.baseModel.fields();
          Object.keys(fields).forEach(function (name) {
              _this.fields.set(name, fields[name]);
          });
      }
      /**
       * Tells if a field is a numeric field.
       *
       * @param {Field | undefined} field
       * @returns {boolean}
       */
      Model.isFieldNumber = function (field) {
          if (!field)
              return false;
          var context = Context.getInstance();
          return field instanceof context.components.Number || field instanceof context.components.Uid;
      };
      /**
       * Tells if a field is a attribute (and thus not a relation)
       * @param {Field} field
       * @returns {boolean}
       */
      Model.isFieldAttribute = function (field) {
          var context = Context.getInstance();
          return (field instanceof context.components.Uid ||
              field instanceof context.components.Attr ||
              field instanceof context.components.String ||
              field instanceof context.components.Number ||
              field instanceof context.components.Boolean);
      };
      /**
       * Tells if a field which represents a relation is a connection (multiple).
       * @param {Field} field
       * @returns {boolean}
       */
      Model.isConnection = function (field) {
          var context = Context.getInstance();
          return !(field instanceof context.components.BelongsTo ||
              field instanceof context.components.HasOne ||
              field instanceof context.components.MorphTo ||
              field instanceof context.components.MorphOne);
      };
      /**
       * Adds $isPersisted and other meta fields to the model.
       *
       * TODO: This feels rather hacky currently and may break anytime the internal structure of
       * the core changes. Maybe in the future there will be a feature in the core that allows to add
       * those meta fields by plugins.
       * @param {Model} model
       */
      Model.augment = function (model) {
          var baseModel = model.baseModel;
          baseModel.getFields();
          baseModel.cachedFields[baseModel.entity]["$isPersisted"] = baseModel.boolean(false);
      };
      /**
       * Returns the related model for a relation.
       * @param {Field|undefined} relation Relation field.
       * @returns {Model|null}
       */
      Model.getRelatedModel = function (relation) {
          if (relation === undefined)
              return null;
          var context = Context.getInstance();
          if (relation instanceof context.components.BelongsToMany ||
              relation instanceof context.components.HasMany ||
              relation instanceof context.components.HasManyThrough ||
              relation instanceof context.components.MorphedByMany ||
              relation instanceof context.components.MorphMany ||
              relation instanceof context.components.MorphOne ||
              relation instanceof context.components.MorphToMany ||
              relation instanceof context.components.HasOne) {
              return context.getModel(relation.related.entity, true);
          }
          else if (relation instanceof context.components.BelongsTo ||
              relation instanceof context.components.HasManyBy) {
              return context.getModel(relation.parent.entity, true);
          }
          else if (relation instanceof context.components.MorphTo) {
              return context.getModel(relation.type, true);
          }
          else {
              console.warn("Failed relation", typeof relation, relation);
              throw new Error("Can't find related model for relation of type " + typeof relation + "!");
          }
      };
      /**
       * Returns all fields which should be included in a graphql query: All attributes which are not included in the
       * skipFields array or start with $.
       * @returns {Array<string>} field names which should be queried
       */
      Model.prototype.getQueryFields = function () {
          var _this = this;
          var fields = [];
          this.fields.forEach(function (field, name) {
              if (Model.isFieldAttribute(field) && !_this.skipField(name)) {
                  fields.push(name);
              }
          });
          return fields;
      };
      /**
       * Tells if a field should be ignored. This is true for fields that start with a `$` or is it is within the skipField
       * property or is the foreignKey of a belongsTo/hasOne relation.
       *
       * @param {string} field
       * @returns {boolean}
       */
      Model.prototype.skipField = function (field) {
          if (field.startsWith("$"))
              return true;
          if (this.baseModel.skipFields && this.baseModel.skipFields.indexOf(field) >= 0)
              return true;
          var context = Context.getInstance();
          var shouldSkipField = false;
          this.getRelations().forEach(function (relation) {
              if ((relation instanceof context.components.BelongsTo ||
                  relation instanceof context.components.HasOne) &&
                  relation.foreignKey === field) {
                  shouldSkipField = true;
                  return false;
              }
              return true;
          });
          return shouldSkipField;
      };
      /**
       * @returns {Map<string, Relation>} all relations of the model.
       */
      Model.prototype.getRelations = function () {
          var relations = new Map();
          this.fields.forEach(function (field, name) {
              if (!Model.isFieldAttribute(field)) {
                  relations.set(name, field);
              }
          });
          return relations;
      };
      /**
       * This accepts a field like `subjectType` and checks if this is just randomly named `...Type` or it is part
       * of a polymorphic relation.
       * @param {string} name
       * @returns {boolean}
       */
      Model.prototype.isTypeFieldOfPolymorphicRelation = function (name) {
          var _this = this;
          var context = Context.getInstance();
          var found = false;
          context.models.forEach(function (model) {
              if (found)
                  return false;
              model.getRelations().forEach(function (relation) {
                  if (relation instanceof context.components.MorphMany ||
                      relation instanceof context.components.MorphedByMany ||
                      relation instanceof context.components.MorphOne ||
                      relation instanceof context.components.MorphTo ||
                      relation instanceof context.components.MorphToMany) {
                      var related = relation.related;
                      if (relation.type === name && related && related.entity === _this.baseModel.entity) {
                          found = true;
                          return false; // break
                      }
                  }
                  return true;
              });
              return true;
          });
          return found;
      };
      /**
       * Returns a record of this model with the given ID.
       * @param {number|string} id
       * @returns {any}
       */
      Model.prototype.getRecordWithId = function (id) {
          return this.baseModel
              .query()
              .withAllRecursive()
              .where("id", toPrimaryKey(id))
              .first();
      };
      /**
       * Determines if we should eager load (means: add as a field in the graphql query) a related entity. belongsTo,
       * hasOne and morphOne related entities are always eager loaded. Others can be added to the `eagerLoad` array
       * or `eagerSync` of the model.
       *
       * @param {string} fieldName Name of the field
       * @param {Relation} relation Relation field
       * @param {Model} relatedModel Related model
       * @returns {boolean}
       */
      Model.prototype.shouldEagerLoadRelation = function (fieldName, relation, relatedModel) {
          var context = Context.getInstance();
          // HasOne, BelongsTo and MorphOne are always eager loaded
          if (relation instanceof context.components.HasOne ||
              relation instanceof context.components.BelongsTo ||
              relation instanceof context.components.MorphOne) {
              return true;
          }
          // Create a list of all relations that have to be eager loaded
          var eagerLoadList = this.baseModel.eagerLoad || [];
          Array.prototype.push.apply(eagerLoadList, this.baseModel.eagerSync || []);
          // Check if the name of the related model or the fieldName is included in the eagerLoadList.
          return (eagerLoadList.find(function (n) {
              return n === relatedModel.singularName || n === relatedModel.pluralName || n === fieldName;
          }) !== undefined);
      };
      /**
       * Determines if we should eager save (means: add as a field in the graphql mutation) a related entity. belongsTo
       * related entities are always eager saved. Others can be added to the `eagerSave` or `eagerSync` array of the model.
       *
       * @param {string} fieldName Name of the field
       * @param {Relation} relation Relation field
       * @param {Model} relatedModel Related model
       * @returns {boolean}
       */
      Model.prototype.shouldEagerSaveRelation = function (fieldName, relation, relatedModel) {
          var context = Context.getInstance();
          // BelongsTo is always eager saved
          if (relation instanceof context.components.BelongsTo) {
              return true;
          }
          // Create a list of all relations that have to be eager saved
          var eagerSaveList = this.baseModel.eagerSave || [];
          Array.prototype.push.apply(eagerSaveList, this.baseModel.eagerSync || []);
          // Check if the name of the related model or the fieldName is included in the eagerSaveList.
          return (eagerSaveList.find(function (n) {
              return n === relatedModel.singularName || n === relatedModel.pluralName || n === fieldName;
          }) !== undefined);
      };
      /**
       * Adds a mock.
       *
       * @param {Mock} mock - Mock config.
       * @returns {boolean}
       */
      Model.prototype.$addMock = function (mock) {
          if (this.$findMock(mock.action, mock.options))
              return false;
          if (!this.mocks[mock.action])
              this.mocks[mock.action] = [];
          this.mocks[mock.action].push(mock);
          return true;
      };
      /**
       * Finds a mock for the given action and options.
       *
       * @param {string} action - Name of the action like 'fetch'.
       * @param {MockOptions} options - MockOptions like { variables: { id: 42 } }.
       * @returns {Mock | null} null when no mock was found.
       */
      Model.prototype.$findMock = function (action, options) {
          if (this.mocks[action]) {
              return (this.mocks[action].find(function (m) {
                  if (!m.options || !options)
                      return true;
                  var relevantOptions = pick(options, Object.keys(m.options));
                  return isEqual(relevantOptions, m.options || {});
              }) || null);
          }
          return null;
      };
      /**
       * Hook to be called by all actions in order to get the mock returnValue.
       *
       * @param {string} action - Name of the action like 'fetch'.
       * @param {MockOptions} options - MockOptions.
       * @returns {any} null when no mock was found.
       */
      Model.prototype.$mockHook = function (action, options) {
          var _a;
          var returnValue = null;
          var mock = this.$findMock(action, options);
          if (mock) {
              if (mock.returnValue instanceof Function) {
                  returnValue = mock.returnValue();
              }
              else {
                  returnValue = mock.returnValue || null;
              }
          }
          if (returnValue) {
              if (returnValue instanceof Array) {
                  returnValue.forEach(function (r) { return (r.$isPersisted = true); });
              }
              else {
                  returnValue.$isPersisted = true;
              }
              return _a = {}, _a[this.pluralName] = returnValue, _a;
          }
          return null;
      };
      return Model;
  }());
  
  var genericMessage = "Invariant Violation";
  var _a = Object.setPrototypeOf, setPrototypeOf = _a === void 0 ? function (obj, proto) {
      obj.__proto__ = proto;
      return obj;
  } : _a;
  var InvariantError = /** @class */ (function (_super) {
      __extends(InvariantError, _super);
      function InvariantError(message) {
          if (message === void 0) { message = genericMessage; }
          var _this = _super.call(this, typeof message === "number"
              ? genericMessage + ": " + message + " (see https://github.com/apollographql/invariant-packages)"
              : message) || this;
          _this.framesToPop = 1;
          _this.name = genericMessage;
          setPrototypeOf(_this, InvariantError.prototype);
          return _this;
      }
      return InvariantError;
  }(Error));
  function invariant(condition, message) {
      if (!condition) {
          throw new InvariantError(message);
      }
  }
  function wrapConsoleMethod(method) {
      return function () {
          return console[method].apply(console, arguments);
      };
  }
  (function (invariant) {
      invariant.warn = wrapConsoleMethod("warn");
      invariant.error = wrapConsoleMethod("error");
  })(invariant || (invariant = {}));
  // Code that uses ts-invariant with rollup-plugin-invariant may want to
  // import this process stub to avoid errors evaluating process.env.NODE_ENV.
  // However, because most ESM-to-CJS compilers will rewrite the process import
  // as tsInvariant.process, which prevents proper replacement by minifiers, we
  // also attempt to define the stub globally when it is not already defined.
  var processStub = { env: {} };
  if (typeof process === "object") {
      processStub = process;
  }
  else
      try {
          // Using Function to evaluate this assignment in global scope also escapes
          // the strict mode of the current module, thereby allowing the assignment.
          // Inspired by https://github.com/facebook/regenerator/pull/369.
          Function("stub", "process = stub")(processStub);
      }
      catch (atLeastWeTried) {
          // The assignment can fail if a Content Security Policy heavy-handedly
          // forbids Function usage. In those environments, developers should take
          // extra care to replace process.env.NODE_ENV in their production builds,
          // or define an appropriate global.process polyfill.
      }
  
  var fastJsonStableStringify = function (data, opts) {
      if (!opts) opts = {};
      if (typeof opts === 'function') opts = { cmp: opts };
      var cycles = (typeof opts.cycles === 'boolean') ? opts.cycles : false;
  
      var cmp = opts.cmp && (function (f) {
          return function (node) {
              return function (a, b) {
                  var aobj = { key: a, value: node[a] };
                  var bobj = { key: b, value: node[b] };
                  return f(aobj, bobj);
              };
          };
      })(opts.cmp);
  
      var seen = [];
      return (function stringify (node) {
          if (node && node.toJSON && typeof node.toJSON === 'function') {
              node = node.toJSON();
          }
  
          if (node === undefined) return;
          if (typeof node == 'number') return isFinite(node) ? '' + node : 'null';
          if (typeof node !== 'object') return JSON.stringify(node);
  
          var i, out;
          if (Array.isArray(node)) {
              out = '[';
              for (i = 0; i < node.length; i++) {
                  if (i) out += ',';
                  out += stringify(node[i]) || 'null';
              }
              return out + ']';
          }
  
          if (node === null) return 'null';
  
          if (seen.indexOf(node) !== -1) {
              if (cycles) return JSON.stringify('__cycle__');
              throw new TypeError('Converting circular structure to JSON');
          }
  
          var seenIndex = seen.push(node) - 1;
          var keys = Object.keys(node).sort(cmp && cmp(node));
          out = '';
          for (i = 0; i < keys.length; i++) {
              var key = keys[i];
              var value = stringify(node[key]);
  
              if (!value) continue;
              if (out) out += ',';
              out += JSON.stringify(key) + ':' + value;
          }
          seen.splice(seenIndex, 1);
          return '{' + out + '}';
      })(data);
  };
  
  var _a$1 = Object.prototype, toString = _a$1.toString, hasOwnProperty = _a$1.hasOwnProperty;
  var previousComparisons = new Map();
  /**
   * Performs a deep equality check on two JavaScript values, tolerating cycles.
   */
  function equal(a, b) {
      try {
          return check(a, b);
      }
      finally {
          previousComparisons.clear();
      }
  }
  function check(a, b) {
      // If the two values are strictly equal, our job is easy.
      if (a === b) {
          return true;
      }
      // Object.prototype.toString returns a representation of the runtime type of
      // the given value that is considerably more precise than typeof.
      var aTag = toString.call(a);
      var bTag = toString.call(b);
      // If the runtime types of a and b are different, they could maybe be equal
      // under some interpretation of equality, but for simplicity and performance
      // we just return false instead.
      if (aTag !== bTag) {
          return false;
      }
      switch (aTag) {
          case '[object Array]':
              // Arrays are a lot like other objects, but we can cheaply compare their
              // lengths as a short-cut before comparing their elements.
              if (a.length !== b.length)
                  return false;
          // Fall through to object case...
          case '[object Object]': {
              if (previouslyCompared(a, b))
                  return true;
              var aKeys = Object.keys(a);
              var bKeys = Object.keys(b);
              // If `a` and `b` have a different number of enumerable keys, they
              // must be different.
              var keyCount = aKeys.length;
              if (keyCount !== bKeys.length)
                  return false;
              // Now make sure they have the same keys.
              for (var k = 0; k < keyCount; ++k) {
                  if (!hasOwnProperty.call(b, aKeys[k])) {
                      return false;
                  }
              }
              // Finally, check deep equality of all child properties.
              for (var k = 0; k < keyCount; ++k) {
                  var key = aKeys[k];
                  if (!check(a[key], b[key])) {
                      return false;
                  }
              }
              return true;
          }
          case '[object Error]':
              return a.name === b.name && a.message === b.message;
          case '[object Number]':
              // Handle NaN, which is !== itself.
              if (a !== a)
                  return b !== b;
          // Fall through to shared +a === +b case...
          case '[object Boolean]':
          case '[object Date]':
              return +a === +b;
          case '[object RegExp]':
          case '[object String]':
              return a == "" + b;
          case '[object Map]':
          case '[object Set]': {
              if (a.size !== b.size)
                  return false;
              if (previouslyCompared(a, b))
                  return true;
              var aIterator = a.entries();
              var isMap = aTag === '[object Map]';
              while (true) {
                  var info = aIterator.next();
                  if (info.done)
                      break;
                  // If a instanceof Set, aValue === aKey.
                  var _a = info.value, aKey = _a[0], aValue = _a[1];
                  // So this works the same way for both Set and Map.
                  if (!b.has(aKey)) {
                      return false;
                  }
                  // However, we care about deep equality of values only when dealing
                  // with Map structures.
                  if (isMap && !check(aValue, b.get(aKey))) {
                      return false;
                  }
              }
              return true;
          }
      }
      // Otherwise the values are not equal.
      return false;
  }
  function previouslyCompared(a, b) {
      // Though cyclic references can make an object graph appear infinite from the
      // perspective of a depth-first traversal, the graph still contains a finite
      // number of distinct object references. We use the previousComparisons cache
      // to avoid comparing the same pair of object references more than once, which
      // guarantees termination (even if we end up comparing every object in one
      // graph to every object in the other graph, which is extremely unlikely),
      // while still allowing weird isomorphic structures (like rings with different
      // lengths) a chance to pass the equality test.
      var bSet = previousComparisons.get(a);
      if (bSet) {
          // Return true here because we can be sure false will be returned somewhere
          // else if the objects are not equivalent.
          if (bSet.has(b))
              return true;
      }
      else {
          previousComparisons.set(a, bSet = new Set);
      }
      bSet.add(b);
      return false;
  }
  
  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 InvariantError(17) : new 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 = fastJsonStableStringify(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 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 = {}; }
      return getInclusionDirectives(selection.directives).every(function (_a) {
          var directive = _a.directive, ifArgument = _a.ifArgument;
          var evaledValue = false;
          if (ifArgument.value.kind === 'Variable') {
              evaledValue = variables[ifArgument.value.name.value];
              process.env.NODE_ENV === "production" ? invariant(evaledValue !== void 0, 13) : invariant(evaledValue !== void 0, "Invalid variable referenced in @" + directive.name.value + " directive.");
          }
          else {
              evaledValue = ifArgument.value.value;
          }
          return directive.name.value === 'skip' ? !evaledValue : evaledValue;
      });
  }
  function getDirectiveNames(doc) {
      var names = [];
      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 isInclusionDirective(_a) {
      var value = _a.name.value;
      return value === 'skip' || value === 'include';
  }
  function getInclusionDirectives(directives) {
      return directives ? directives.filter(isInclusionDirective).map(function (directive) {
          var directiveArguments = directive.arguments;
          var directiveName = directive.name.value;
          process.env.NODE_ENV === "production" ? invariant(directiveArguments && directiveArguments.length === 1, 14) : invariant(directiveArguments && directiveArguments.length === 1, "Incorrect number of arguments for the @" + directiveName + " directive.");
          var ifArgument = directiveArguments[0];
          process.env.NODE_ENV === "production" ? invariant(ifArgument.name && ifArgument.name.value === 'if', 15) : invariant(ifArgument.name && ifArgument.name.value === 'if', "Invalid argument for the @" + directiveName + " directive.");
          var ifValue = ifArgument.value;
          process.env.NODE_ENV === "production" ? invariant(ifValue &&
              (ifValue.kind === 'Variable' || ifValue.kind === 'BooleanValue'), 16) : invariant(ifValue &&
              (ifValue.kind === 'Variable' || ifValue.kind === 'BooleanValue'), "Argument for the @" + directiveName + " directive must be a variable or a boolean value.");
          return { directive: directive, ifArgument: ifArgument };
      }) : [];
  }
  
  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 InvariantError(11) : new 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" ? invariant(fragments.length === 1, 12) : 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 = __assign(__assign({}, document), { definitions: __spreadArrays([
              {
                  kind: 'OperationDefinition',
                  operation: 'query',
                  selectionSet: {
                      kind: 'SelectionSet',
                      selections: [
                          {
                              kind: 'FragmentSpread',
                              name: {
                                  kind: 'Name',
                                  value: actualFragmentName,
                              },
                          },
                      ],
                  },
              }
          ], 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 checkDocument(doc) {
      process.env.NODE_ENV === "production" ? invariant(doc && doc.kind === 'Document', 2) : 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 InvariantError(3) : new InvariantError("Schema type definitions not allowed in queries. Found: \"" + definition.kind + "\"");
          }
          return definition;
      });
      process.env.NODE_ENV === "production" ? invariant(operations.length <= 1, 4) : 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 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" ? invariant(queryDef && queryDef.operation === 'query', 6) : invariant(queryDef && queryDef.operation === 'query', 'Must contain a query definition.');
      return queryDef;
  }
  function getFragmentDefinition(doc) {
      process.env.NODE_ENV === "production" ? invariant(doc.kind === 'Document', 7) : 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" ? invariant(doc.definitions.length <= 1, 8) : invariant(doc.definitions.length <= 1, 'Fragment must have exactly one definition.');
      var fragmentDef = doc.definitions[0];
      process.env.NODE_ENV === "production" ? invariant(fragmentDef.kind === 'FragmentDefinition', 9) : 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 InvariantError(10) : new 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, __spreadArrays([{}], defaultValues));
      }
      return {};
  }
  
  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(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 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 (isField(selection) &&
                          (selection.name.value === '__typename' ||
                              selection.name.value.lastIndexOf('__', 0) === 0));
                  });
                  if (skip) {
                      return;
                  }
                  var field = parent;
                  if (isField(field) &&
                      field.directives &&
                      field.directives.some(function (d) { return d.name.value === 'export'; })) {
                      return;
                  }
                  return __assign(__assign({}, node), { selections: __spreadArrays(selections, [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'; })) {
                  process.env.NODE_ENV === "production" || invariant.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 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(visit(doc, {
          OperationDefinition: {
              enter: function (node) {
                  return __assign(__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(visit(doc, {
          FragmentSpread: { enter: enter },
          FragmentDefinition: { enter: enter },
      }));
  }
  function getAllFragmentSpreadsFromSelectionSet(selectionSet) {
      var allFragments = [];
      selectionSet.selections.forEach(function (selection) {
          if ((isField(selection) || isInlineFragment(selection)) &&
              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 = visit(document, {
          OperationDefinition: {
              enter: function (node) {
                  return __assign(__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 = visit(modifiedDoc, {
              FragmentDefinition: {
                  enter: function (node) {
                      if (node.selectionSet) {
                          var isTypenameOnly = node.selectionSet.selections.every(function (selection) {
                              return isField(selection) && selection.name.value === '__typename';
                          });
                          if (isTypenameOnly) {
                              return null;
                          }
                      }
                  },
              },
          });
      }
      return modifiedDoc;
  }
  
  var canUseWeakMap = typeof WeakMap === 'function' && !(typeof navigator === 'object' &&
      navigator.product === 'ReactNative');
  
  var toString$1 = Object.prototype.toString;
  function cloneDeep(value) {
      return cloneDeepHelper(value, new Map());
  }
  function cloneDeepHelper(val, seen) {
      switch (toString$1.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 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$1 = 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$1.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 = __assign({ __proto__: Object.getPrototypeOf(value) }, value);
          }
          pastCopies.push(value);
      }
      return value;
  }
  
  var Observable_1 = createCommonjsModule(function (module, exports) {
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.Observable = void 0;
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  
  // === Symbol Support ===
  var hasSymbols = function () {
    return typeof Symbol === 'function';
  };
  
  var hasSymbol = function (name) {
    return hasSymbols() && Boolean(Symbol[name]);
  };
  
  var getSymbol = function (name) {
    return hasSymbol(name) ? Symbol[name] : '@@' + name;
  };
  
  if (hasSymbols() && !hasSymbol('observable')) {
    Symbol.observable = Symbol('observable');
  }
  
  var SymbolIterator = getSymbol('iterator');
  var SymbolObservable = getSymbol('observable');
  var SymbolSpecies = getSymbol('species'); // === Abstract Operations ===
  
  function getMethod(obj, key) {
    var value = obj[key];
    if (value == null) return undefined;
    if (typeof value !== 'function') throw new TypeError(value + ' is not a function');
    return value;
  }
  
  function getSpecies(obj) {
    var ctor = obj.constructor;
  
    if (ctor !== undefined) {
      ctor = ctor[SymbolSpecies];
  
      if (ctor === null) {
        ctor = undefined;
      }
    }
  
    return ctor !== undefined ? ctor : Observable;
  }
  
  function isObservable(x) {
    return x instanceof Observable; // SPEC: Brand check
  }
  
  function hostReportError(e) {
    if (hostReportError.log) {
      hostReportError.log(e);
    } else {
      setTimeout(function () {
        throw e;
      });
    }
  }
  
  function enqueue(fn) {
    Promise.resolve().then(function () {
      try {
        fn();
      } catch (e) {
        hostReportError(e);
      }
    });
  }
  
  function cleanupSubscription(subscription) {
    var cleanup = subscription._cleanup;
    if (cleanup === undefined) return;
    subscription._cleanup = undefined;
  
    if (!cleanup) {
      return;
    }
  
    try {
      if (typeof cleanup === 'function') {
        cleanup();
      } else {
        var unsubscribe = getMethod(cleanup, 'unsubscribe');
  
        if (unsubscribe) {
          unsubscribe.call(cleanup);
        }
      }
    } catch (e) {
      hostReportError(e);
    }
  }
  
  function closeSubscription(subscription) {
    subscription._observer = undefined;
    subscription._queue = undefined;
    subscription._state = 'closed';
  }
  
  function flushSubscription(subscription) {
    var queue = subscription._queue;
  
    if (!queue) {
      return;
    }
  
    subscription._queue = undefined;
    subscription._state = 'ready';
  
    for (var i = 0; i < queue.length; ++i) {
      notifySubscription(subscription, queue[i].type, queue[i].value);
      if (subscription._state === 'closed') break;
    }
  }
  
  function notifySubscription(subscription, type, value) {
    subscription._state = 'running';
    var observer = subscription._observer;
  
    try {
      var m = getMethod(observer, type);
  
      switch (type) {
        case 'next':
          if (m) m.call(observer, value);
          break;
  
        case 'error':
          closeSubscription(subscription);
          if (m) m.call(observer, value);else throw value;
          break;
  
        case 'complete':
          closeSubscription(subscription);
          if (m) m.call(observer);
          break;
      }
    } catch (e) {
      hostReportError(e);
    }
  
    if (subscription._state === 'closed') cleanupSubscription(subscription);else if (subscription._state === 'running') subscription._state = 'ready';
  }
  
  function onNotify(subscription, type, value) {
    if (subscription._state === 'closed') return;
  
    if (subscription._state === 'buffering') {
      subscription._queue.push({
        type: type,
        value: value
      });
  
      return;
    }
  
    if (subscription._state !== 'ready') {
      subscription._state = 'buffering';
      subscription._queue = [{
        type: type,
        value: value
      }];
      enqueue(function () {
        return flushSubscription(subscription);
      });
      return;
    }
  
    notifySubscription(subscription, type, value);
  }
  
  var Subscription =
  /*#__PURE__*/
  function () {
    function Subscription(observer, subscriber) {
      _classCallCheck(this, Subscription);
  
      // ASSERT: observer is an object
      // ASSERT: subscriber is callable
      this._cleanup = undefined;
      this._observer = observer;
      this._queue = undefined;
      this._state = 'initializing';
      var subscriptionObserver = new SubscriptionObserver(this);
  
      try {
        this._cleanup = subscriber.call(undefined, subscriptionObserver);
      } catch (e) {
        subscriptionObserver.error(e);
      }
  
      if (this._state === 'initializing') this._state = 'ready';
    }
  
    _createClass(Subscription, [{
      key: "unsubscribe",
      value: function unsubscribe() {
        if (this._state !== 'closed') {
          closeSubscription(this);
          cleanupSubscription(this);
        }
      }
    }, {
      key: "closed",
      get: function () {
        return this._state === 'closed';
      }
    }]);
  
    return Subscription;
  }();
  
  var SubscriptionObserver =
  /*#__PURE__*/
  function () {
    function SubscriptionObserver(subscription) {
      _classCallCheck(this, SubscriptionObserver);
  
      this._subscription = subscription;
    }
  
    _createClass(SubscriptionObserver, [{
      key: "next",
      value: function next(value) {
        onNotify(this._subscription, 'next', value);
      }
    }, {
      key: "error",
      value: function error(value) {
        onNotify(this._subscription, 'error', value);
      }
    }, {
      key: "complete",
      value: function complete() {
        onNotify(this._subscription, 'complete');
      }
    }, {
      key: "closed",
      get: function () {
        return this._subscription._state === 'closed';
      }
    }]);
  
    return SubscriptionObserver;
  }();
  
  var Observable =
  /*#__PURE__*/
  function () {
    function Observable(subscriber) {
      _classCallCheck(this, Observable);
  
      if (!(this instanceof Observable)) throw new TypeError('Observable cannot be called as a function');
      if (typeof subscriber !== 'function') throw new TypeError('Observable initializer must be a function');
      this._subscriber = subscriber;
    }
  
    _createClass(Observable, [{
      key: "subscribe",
      value: function subscribe(observer) {
        if (typeof observer !== 'object' || observer === null) {
          observer = {
            next: observer,
            error: arguments[1],
            complete: arguments[2]
          };
        }
  
        return new Subscription(observer, this._subscriber);
      }
    }, {
      key: "forEach",
      value: function forEach(fn) {
        var _this = this;
  
        return new Promise(function (resolve, reject) {
          if (typeof fn !== 'function') {
            reject(new TypeError(fn + ' is not a function'));
            return;
          }
  
          function done() {
            subscription.unsubscribe();
            resolve();
          }
  
          var subscription = _this.subscribe({
            next: function (value) {
              try {
                fn(value, done);
              } catch (e) {
                reject(e);
                subscription.unsubscribe();
              }
            },
            error: reject,
            complete: resolve
          });
        });
      }
    }, {
      key: "map",
      value: function map(fn) {
        var _this2 = this;
  
        if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
        var C = getSpecies(this);
        return new C(function (observer) {
          return _this2.subscribe({
            next: function (value) {
              try {
                value = fn(value);
              } catch (e) {
                return observer.error(e);
              }
  
              observer.next(value);
            },
            error: function (e) {
              observer.error(e);
            },
            complete: function () {
              observer.complete();
            }
          });
        });
      }
    }, {
      key: "filter",
      value: function filter(fn) {
        var _this3 = this;
  
        if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
        var C = getSpecies(this);
        return new C(function (observer) {
          return _this3.subscribe({
            next: function (value) {
              try {
                if (!fn(value)) return;
              } catch (e) {
                return observer.error(e);
              }
  
              observer.next(value);
            },
            error: function (e) {
              observer.error(e);
            },
            complete: function () {
              observer.complete();
            }
          });
        });
      }
    }, {
      key: "reduce",
      value: function reduce(fn) {
        var _this4 = this;
  
        if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
        var C = getSpecies(this);
        var hasSeed = arguments.length > 1;
        var hasValue = false;
        var seed = arguments[1];
        var acc = seed;
        return new C(function (observer) {
          return _this4.subscribe({
            next: function (value) {
              var first = !hasValue;
              hasValue = true;
  
              if (!first || hasSeed) {
                try {
                  acc = fn(acc, value);
                } catch (e) {
                  return observer.error(e);
                }
              } else {
                acc = value;
              }
            },
            error: function (e) {
              observer.error(e);
            },
            complete: function () {
              if (!hasValue && !hasSeed) return observer.error(new TypeError('Cannot reduce an empty sequence'));
              observer.next(acc);
              observer.complete();
            }
          });
        });
      }
    }, {
      key: "concat",
      value: function concat() {
        var _this5 = this;
  
        for (var _len = arguments.length, sources = new Array(_len), _key = 0; _key < _len; _key++) {
          sources[_key] = arguments[_key];
        }
  
        var C = getSpecies(this);
        return new C(function (observer) {
          var subscription;
          var index = 0;
  
          function startNext(next) {
            subscription = next.subscribe({
              next: function (v) {
                observer.next(v);
              },
              error: function (e) {
                observer.error(e);
              },
              complete: function () {
                if (index === sources.length) {
                  subscription = undefined;
                  observer.complete();
                } else {
                  startNext(C.from(sources[index++]));
                }
              }
            });
          }
  
          startNext(_this5);
          return function () {
            if (subscription) {
              subscription.unsubscribe();
              subscription = undefined;
            }
          };
        });
      }
    }, {
      key: "flatMap",
      value: function flatMap(fn) {
        var _this6 = this;
  
        if (typeof fn !== 'function') throw new TypeError(fn + ' is not a function');
        var C = getSpecies(this);
        return new C(function (observer) {
          var subscriptions = [];
  
          var outer = _this6.subscribe({
            next: function (value) {
              if (fn) {
                try {
                  value = fn(value);
                } catch (e) {
                  return observer.error(e);
                }
              }
  
              var inner = C.from(value).subscribe({
                next: function (value) {
                  observer.next(value);
                },
                error: function (e) {
                  observer.error(e);
                },
                complete: function () {
                  var i = subscriptions.indexOf(inner);
                  if (i >= 0) subscriptions.splice(i, 1);
                  completeIfDone();
                }
              });
              subscriptions.push(inner);
            },
            error: function (e) {
              observer.error(e);
            },
            complete: function () {
              completeIfDone();
            }
          });
  
          function completeIfDone() {
            if (outer.closed && subscriptions.length === 0) observer.complete();
          }
  
          return function () {
            subscriptions.forEach(function (s) {
              return s.unsubscribe();
            });
            outer.unsubscribe();
          };
        });
      }
    }, {
      key: SymbolObservable,
      value: function () {
        return this;
      }
    }], [{
      key: "from",
      value: function from(x) {
        var C = typeof this === 'function' ? this : Observable;
        if (x == null) throw new TypeError(x + ' is not an object');
        var method = getMethod(x, SymbolObservable);
  
        if (method) {
          var observable = method.call(x);
          if (Object(observable) !== observable) throw new TypeError(observable + ' is not an object');
          if (isObservable(observable) && observable.constructor === C) return observable;
          return new C(function (observer) {
            return observable.subscribe(observer);
          });
        }
  
        if (hasSymbol('iterator')) {
          method = getMethod(x, SymbolIterator);
  
          if (method) {
            return new C(function (observer) {
              enqueue(function () {
                if (observer.closed) return;
                var _iteratorNormalCompletion = true;
                var _didIteratorError = false;
                var _iteratorError = undefined;
  
                try {
                  for (var _iterator = method.call(x)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                    var _item = _step.value;
                    observer.next(_item);
                    if (observer.closed) return;
                  }
                } catch (err) {
                  _didIteratorError = true;
                  _iteratorError = err;
                } finally {
                  try {
                    if (!_iteratorNormalCompletion && _iterator.return != null) {
                      _iterator.return();
                    }
                  } finally {
                    if (_didIteratorError) {
                      throw _iteratorError;
                    }
                  }
                }
  
                observer.complete();
              });
            });
          }
        }
  
        if (Array.isArray(x)) {
          return new C(function (observer) {
            enqueue(function () {
              if (observer.closed) return;
  
              for (var i = 0; i < x.length; ++i) {
                observer.next(x[i]);
                if (observer.closed) return;
              }
  
              observer.complete();
            });
          });
        }
  
        throw new TypeError(x + ' is not observable');
      }
    }, {
      key: "of",
      value: function of() {
        for (var _len2 = arguments.length, items = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
          items[_key2] = arguments[_key2];
        }
  
        var C = typeof this === 'function' ? this : Observable;
        return new C(function (observer) {
          enqueue(function () {
            if (observer.closed) return;
  
            for (var i = 0; i < items.length; ++i) {
              observer.next(items[i]);
              if (observer.closed) return;
            }
  
            observer.complete();
          });
        });
      }
    }, {
      key: SymbolSpecies,
      get: function () {
        return this;
      }
    }]);
  
    return Observable;
  }();
  
  exports.Observable = Observable;
  
  if (hasSymbols()) {
    Object.defineProperty(Observable, Symbol('extensions'), {
      value: {
        symbol: SymbolObservable,
        hostReportError: hostReportError
      },
      configurable: true
    });
  }
  });
  
  unwrapExports(Observable_1);
  Observable_1.Observable;
  
  var zenObservable = Observable_1.Observable;
  
  var Observable = zenObservable;
  
  function validateOperation(operation) {
      var OPERATION_FIELDS = [
          'query',
          'operationName',
          'variables',
          'extensions',
          'context',
      ];
      for (var _i = 0, _a = Object.keys(operation); _i < _a.length; _i++) {
          var key = _a[_i];
          if (OPERATION_FIELDS.indexOf(key) < 0) {
              throw process.env.NODE_ENV === "production" ? new InvariantError(2) : new InvariantError("illegal argument: " + key);
          }
      }
      return operation;
  }
  var LinkError = (function (_super) {
      __extends(LinkError, _super);
      function LinkError(message, link) {
          var _this = _super.call(this, message) || this;
          _this.link = link;
          return _this;
      }
      return LinkError;
  }(Error));
  function isTerminating(link) {
      return link.request.length <= 1;
  }
  function fromError(errorValue) {
      return new Observable(function (observer) {
          observer.error(errorValue);
      });
  }
  function transformOperation(operation) {
      var transformedOperation = {
          variables: operation.variables || {},
          extensions: operation.extensions || {},
          operationName: operation.operationName,
          query: operation.query,
      };
      if (!transformedOperation.operationName) {
          transformedOperation.operationName =
              typeof transformedOperation.query !== 'string'
                  ? getOperationName(transformedOperation.query)
                  : '';
      }
      return transformedOperation;
  }
  function createOperation(starting, operation) {
      var context = __assign({}, starting);
      var setContext = function (next) {
          if (typeof next === 'function') {
              context = __assign({}, context, next(context));
          }
          else {
              context = __assign({}, context, next);
          }
      };
      var getContext = function () { return (__assign({}, context)); };
      Object.defineProperty(operation, 'setContext', {
          enumerable: false,
          value: setContext,
      });
      Object.defineProperty(operation, 'getContext', {
          enumerable: false,
          value: getContext,
      });
      Object.defineProperty(operation, 'toKey', {
          enumerable: false,
          value: function () { return getKey(operation); },
      });
      return operation;
  }
  function getKey(operation) {
      var query = operation.query, variables = operation.variables, operationName = operation.operationName;
      return JSON.stringify([operationName, query, variables]);
  }
  
  function passthrough(op, forward) {
      return forward ? forward(op) : Observable.of();
  }
  function toLink(handler) {
      return typeof handler === 'function' ? new ApolloLink(handler) : handler;
  }
  function empty() {
      return new ApolloLink(function () { return Observable.of(); });
  }
  function from(links) {
      if (links.length === 0)
          return empty();
      return links.map(toLink).reduce(function (x, y) { return x.concat(y); });
  }
  function split(test, left, right) {
      var leftLink = toLink(left);
      var rightLink = toLink(right || new ApolloLink(passthrough));
      if (isTerminating(leftLink) && isTerminating(rightLink)) {
          return new ApolloLink(function (operation) {
              return test(operation)
                  ? leftLink.request(operation) || Observable.of()
                  : rightLink.request(operation) || Observable.of();
          });
      }
      else {
          return new ApolloLink(function (operation, forward) {
              return test(operation)
                  ? leftLink.request(operation, forward) || Observable.of()
                  : rightLink.request(operation, forward) || Observable.of();
          });
      }
  }
  var concat = function (first, second) {
      var firstLink = toLink(first);
      if (isTerminating(firstLink)) {
          process.env.NODE_ENV === "production" || invariant.warn(new LinkError("You are calling concat on a terminating link, which will have no effect", firstLink));
          return firstLink;
      }
      var nextLink = toLink(second);
      if (isTerminating(nextLink)) {
          return new ApolloLink(function (operation) {
              return firstLink.request(operation, function (op) { return nextLink.request(op) || Observable.of(); }) || Observable.of();
          });
      }
      else {
          return new ApolloLink(function (operation, forward) {
              return (firstLink.request(operation, function (op) {
                  return nextLink.request(op, forward) || Observable.of();
              }) || Observable.of());
          });
      }
  };
  var ApolloLink = (function () {
      function ApolloLink(request) {
          if (request)
              this.request = request;
      }
      ApolloLink.prototype.split = function (test, left, right) {
          return this.concat(split(test, left, right || new ApolloLink(passthrough)));
      };
      ApolloLink.prototype.concat = function (next) {
          return concat(this, next);
      };
      ApolloLink.prototype.request = function (operation, forward) {
          throw process.env.NODE_ENV === "production" ? new InvariantError(1) : new InvariantError('request is not implemented');
      };
      ApolloLink.empty = empty;
      ApolloLink.from = from;
      ApolloLink.split = split;
      ApolloLink.execute = execute;
      return ApolloLink;
  }());
  function execute(link, operation) {
      return (link.request(createOperation(operation.context, transformOperation(validateOperation(operation)))) || Observable.of());
  }
  
  function symbolObservablePonyfill(root) {
  	var result;
  	var Symbol = root.Symbol;
  
  	if (typeof Symbol === 'function') {
  		if (Symbol.observable) {
  			result = Symbol.observable;
  		} else {
  			result = Symbol('observable');
  			Symbol.observable = result;
  		}
  	} else {
  		result = '@@observable';
  	}
  
  	return result;
  }
  
  /* global window */
  
  var root;
  
  if (typeof self !== 'undefined') {
    root = self;
  } else if (typeof window !== 'undefined') {
    root = window;
  } else if (typeof global !== 'undefined') {
    root = global;
  } else if (typeof module !== 'undefined') {
    root = module;
  } else {
    root = Function('return this')();
  }
  
  var result = symbolObservablePonyfill(root);
  
  var NetworkStatus;
  (function (NetworkStatus) {
      NetworkStatus[NetworkStatus["loading"] = 1] = "loading";
      NetworkStatus[NetworkStatus["setVariables"] = 2] = "setVariables";
      NetworkStatus[NetworkStatus["fetchMore"] = 3] = "fetchMore";
      NetworkStatus[NetworkStatus["refetch"] = 4] = "refetch";
      NetworkStatus[NetworkStatus["poll"] = 6] = "poll";
      NetworkStatus[NetworkStatus["ready"] = 7] = "ready";
      NetworkStatus[NetworkStatus["error"] = 8] = "error";
  })(NetworkStatus || (NetworkStatus = {}));
  function isNetworkRequestInFlight(networkStatus) {
      return networkStatus < 7;
  }
  
  var Observable$1 = (function (_super) {
      __extends(Observable, _super);
      function Observable() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      Observable.prototype[result] = function () {
          return this;
      };
      Observable.prototype['@@observable'] = function () {
          return this;
      };
      return Observable;
  }(Observable));
  
  function isNonEmptyArray(value) {
      return Array.isArray(value) && value.length > 0;
  }
  
  function isApolloError(err) {
      return err.hasOwnProperty('graphQLErrors');
  }
  var generateErrorMessage = function (err) {
      var message = '';
      if (isNonEmptyArray(err.graphQLErrors)) {
          err.graphQLErrors.forEach(function (graphQLError) {
              var errorMessage = graphQLError
                  ? graphQLError.message
                  : 'Error message not found.';
              message += "GraphQL error: " + errorMessage + "\n";
          });
      }
      if (err.networkError) {
          message += 'Network error: ' + err.networkError.message + '\n';
      }
      message = message.replace(/\n$/, '');
      return message;
  };
  var ApolloError = (function (_super) {
      __extends(ApolloError, _super);
      function ApolloError(_a) {
          var graphQLErrors = _a.graphQLErrors, networkError = _a.networkError, errorMessage = _a.errorMessage, extraInfo = _a.extraInfo;
          var _this = _super.call(this, errorMessage) || this;
          _this.graphQLErrors = graphQLErrors || [];
          _this.networkError = networkError || null;
          if (!errorMessage) {
              _this.message = generateErrorMessage(_this);
          }
          else {
              _this.message = errorMessage;
          }
          _this.extraInfo = extraInfo;
          _this.__proto__ = ApolloError.prototype;
          return _this;
      }
      return ApolloError;
  }(Error));
  
  var FetchType;
  (function (FetchType) {
      FetchType[FetchType["normal"] = 1] = "normal";
      FetchType[FetchType["refetch"] = 2] = "refetch";
      FetchType[FetchType["poll"] = 3] = "poll";
  })(FetchType || (FetchType = {}));
  
  var hasError = function (storeValue, policy) {
      if (policy === void 0) { policy = 'none'; }
      return storeValue && (storeValue.networkError ||
          (policy === 'none' && isNonEmptyArray(storeValue.graphQLErrors)));
  };
  var ObservableQuery = (function (_super) {
      __extends(ObservableQuery, _super);
      function ObservableQuery(_a) {
          var queryManager = _a.queryManager, options = _a.options, _b = _a.shouldSubscribe, shouldSubscribe = _b === void 0 ? true : _b;
          var _this = _super.call(this, function (observer) {
              return _this.onSubscribe(observer);
          }) || this;
          _this.observers = new Set();
          _this.subscriptions = new Set();
          _this.isTornDown = false;
          _this.options = options;
          _this.variables = options.variables || {};
          _this.queryId = queryManager.generateQueryId();
          _this.shouldSubscribe = shouldSubscribe;
          var opDef = getOperationDefinition(options.query);
          _this.queryName = opDef && opDef.name && opDef.name.value;
          _this.queryManager = queryManager;
          return _this;
      }
      ObservableQuery.prototype.result = function () {
          var _this = this;
          return new Promise(function (resolve, reject) {
              var observer = {
                  next: function (result) {
                      resolve(result);
                      _this.observers.delete(observer);
                      if (!_this.observers.size) {
                          _this.queryManager.removeQuery(_this.queryId);
                      }
                      setTimeout(function () {
                          subscription.unsubscribe();
                      }, 0);
                  },
                  error: reject,
              };
              var subscription = _this.subscribe(observer);
          });
      };
      ObservableQuery.prototype.currentResult = function () {
          var result = this.getCurrentResult();
          if (result.data === undefined) {
              result.data = {};
          }
          return result;
      };
      ObservableQuery.prototype.getCurrentResult = function () {
          if (this.isTornDown) {
              var lastResult = this.lastResult;
              return {
                  data: !this.lastError && lastResult && lastResult.data || void 0,
                  error: this.lastError,
                  loading: false,
                  networkStatus: NetworkStatus.error,
              };
          }
          var _a = this.queryManager.getCurrentQueryResult(this), data = _a.data, partial = _a.partial;
          var queryStoreValue = this.queryManager.queryStore.get(this.queryId);
          var result;
          var fetchPolicy = this.options.fetchPolicy;
          var isNetworkFetchPolicy = fetchPolicy === 'network-only' ||
              fetchPolicy === 'no-cache';
          if (queryStoreValue) {
              var networkStatus = queryStoreValue.networkStatus;
              if (hasError(queryStoreValue, this.options.errorPolicy)) {
                  return {
                      data: void 0,
                      loading: false,
                      networkStatus: networkStatus,
                      error: new ApolloError({
                          graphQLErrors: queryStoreValue.graphQLErrors,
                          networkError: queryStoreValue.networkError,
                      }),
                  };
              }
              if (queryStoreValue.variables) {
                  this.options.variables = __assign(__assign({}, this.options.variables), queryStoreValue.variables);
                  this.variables = this.options.variables;
              }
              result = {
                  data: data,
                  loading: isNetworkRequestInFlight(networkStatus),
                  networkStatus: networkStatus,
              };
              if (queryStoreValue.graphQLErrors && this.options.errorPolicy === 'all') {
                  result.errors = queryStoreValue.graphQLErrors;
              }
          }
          else {
              var loading = isNetworkFetchPolicy ||
                  (partial && fetchPolicy !== 'cache-only');
              result = {
                  data: data,
                  loading: loading,
                  networkStatus: loading ? NetworkStatus.loading : NetworkStatus.ready,
              };
          }
          if (!partial) {
              this.updateLastResult(__assign(__assign({}, result), { stale: false }));
          }
          return __assign(__assign({}, result), { partial: partial });
      };
      ObservableQuery.prototype.isDifferentFromLastResult = function (newResult) {
          var snapshot = this.lastResultSnapshot;
          return !(snapshot &&
              newResult &&
              snapshot.networkStatus === newResult.networkStatus &&
              snapshot.stale === newResult.stale &&
              equal(snapshot.data, newResult.data));
      };
      ObservableQuery.prototype.getLastResult = function () {
          return this.lastResult;
      };
      ObservableQuery.prototype.getLastError = function () {
          return this.lastError;
      };
      ObservableQuery.prototype.resetLastResults = function () {
          delete this.lastResult;
          delete this.lastResultSnapshot;
          delete this.lastError;
          this.isTornDown = false;
      };
      ObservableQuery.prototype.resetQueryStoreErrors = function () {
          var queryStore = this.queryManager.queryStore.get(this.queryId);
          if (queryStore) {
              queryStore.networkError = null;
              queryStore.graphQLErrors = [];
          }
      };
      ObservableQuery.prototype.refetch = function (variables) {
          var fetchPolicy = this.options.fetchPolicy;
          if (fetchPolicy === 'cache-only') {
              return Promise.reject(process.env.NODE_ENV === "production" ? new InvariantError(1) : new InvariantError('cache-only fetchPolicy option should not be used together with query refetch.'));
          }
          if (fetchPolicy !== 'no-cache' &&
              fetchPolicy !== 'cache-and-network') {
              fetchPolicy = 'network-only';
          }
          if (!equal(this.variables, variables)) {
              this.variables = __assign(__assign({}, this.variables), variables);
          }
          if (!equal(this.options.variables, this.variables)) {
              this.options.variables = __assign(__assign({}, this.options.variables), this.variables);
          }
          return this.queryManager.fetchQuery(this.queryId, __assign(__assign({}, this.options), { fetchPolicy: fetchPolicy }), FetchType.refetch);
      };
      ObservableQuery.prototype.fetchMore = function (fetchMoreOptions) {
          var _this = this;
          process.env.NODE_ENV === "production" ? invariant(fetchMoreOptions.updateQuery, 2) : invariant(fetchMoreOptions.updateQuery, 'updateQuery option is required. This function defines how to update the query data with the new results.');
          var combinedOptions = __assign(__assign({}, (fetchMoreOptions.query ? fetchMoreOptions : __assign(__assign(__assign({}, this.options), fetchMoreOptions), { variables: __assign(__assign({}, this.variables), fetchMoreOptions.variables) }))), { fetchPolicy: 'network-only' });
          var qid = this.queryManager.generateQueryId();
          return this.queryManager
              .fetchQuery(qid, combinedOptions, FetchType.normal, this.queryId)
              .then(function (fetchMoreResult) {
              _this.updateQuery(function (previousResult) {
                  return fetchMoreOptions.updateQuery(previousResult, {
                      fetchMoreResult: fetchMoreResult.data,
                      variables: combinedOptions.variables,
                  });
              });
              _this.queryManager.stopQuery(qid);
              return fetchMoreResult;
          }, function (error) {
              _this.queryManager.stopQuery(qid);
              throw error;
          });
      };
      ObservableQuery.prototype.subscribeToMore = function (options) {
          var _this = this;
          var subscription = this.queryManager
              .startGraphQLSubscription({
              query: options.document,
              variables: options.variables,
          })
              .subscribe({
              next: function (subscriptionData) {
                  var updateQuery = options.updateQuery;
                  if (updateQuery) {
                      _this.updateQuery(function (previous, _a) {
                          var variables = _a.variables;
                          return updateQuery(previous, {
                              subscriptionData: subscriptionData,
                              variables: variables,
                          });
                      });
                  }
              },
              error: function (err) {
                  if (options.onError) {
                      options.onError(err);
                      return;
                  }
                  process.env.NODE_ENV === "production" || invariant.error('Unhandled GraphQL subscription error', err);
              },
          });
          this.subscriptions.add(subscription);
          return function () {
              if (_this.subscriptions.delete(subscription)) {
                  subscription.unsubscribe();
              }
          };
      };
      ObservableQuery.prototype.setOptions = function (opts) {
          var oldFetchPolicy = this.options.fetchPolicy;
          this.options = __assign(__assign({}, this.options), opts);
          if (opts.pollInterval) {
              this.startPolling(opts.pollInterval);
          }
          else if (opts.pollInterval === 0) {
              this.stopPolling();
          }
          var fetchPolicy = opts.fetchPolicy;
          return this.setVariables(this.options.variables, oldFetchPolicy !== fetchPolicy && (oldFetchPolicy === 'cache-only' ||
              oldFetchPolicy === 'standby' ||
              fetchPolicy === 'network-only'), opts.fetchResults);
      };
      ObservableQuery.prototype.setVariables = function (variables, tryFetch, fetchResults) {
          if (tryFetch === void 0) { tryFetch = false; }
          if (fetchResults === void 0) { fetchResults = true; }
          this.isTornDown = false;
          variables = variables || this.variables;
          if (!tryFetch && equal(variables, this.variables)) {
              return this.observers.size && fetchResults
                  ? this.result()
                  : Promise.resolve();
          }
          this.variables = this.options.variables = variables;
          if (!this.observers.size) {
              return Promise.resolve();
          }
          return this.queryManager.fetchQuery(this.queryId, this.options);
      };
      ObservableQuery.prototype.updateQuery = function (mapFn) {
          var queryManager = this.queryManager;
          var _a = queryManager.getQueryWithPreviousResult(this.queryId), previousResult = _a.previousResult, variables = _a.variables, document = _a.document;
          var newResult = tryFunctionOrLogError(function () {
              return mapFn(previousResult, { variables: variables });
          });
          if (newResult) {
              queryManager.dataStore.markUpdateQueryResult(document, variables, newResult);
              queryManager.broadcastQueries();
          }
      };
      ObservableQuery.prototype.stopPolling = function () {
          this.queryManager.stopPollingQuery(this.queryId);
          this.options.pollInterval = undefined;
      };
      ObservableQuery.prototype.startPolling = function (pollInterval) {
          assertNotCacheFirstOrOnly(this);
          this.options.pollInterval = pollInterval;
          this.queryManager.startPollingQuery(this.options, this.queryId);
      };
      ObservableQuery.prototype.updateLastResult = function (newResult) {
          var previousResult = this.lastResult;
          this.lastResult = newResult;
          this.lastResultSnapshot = this.queryManager.assumeImmutableResults
              ? newResult
              : cloneDeep(newResult);
          return previousResult;
      };
      ObservableQuery.prototype.onSubscribe = function (observer) {
          var _this = this;
          try {
              var subObserver = observer._subscription._observer;
              if (subObserver && !subObserver.error) {
                  subObserver.error = defaultSubscriptionObserverErrorCallback;
              }
          }
          catch (_a) { }
          var first = !this.observers.size;
          this.observers.add(observer);
          if (observer.next && this.lastResult)
              observer.next(this.lastResult);
          if (observer.error && this.lastError)
              observer.error(this.lastError);
          if (first) {
              this.setUpQuery();
          }
          return function () {
              if (_this.observers.delete(observer) && !_this.observers.size) {
                  _this.tearDownQuery();
              }
          };
      };
      ObservableQuery.prototype.setUpQuery = function () {
          var _this = this;
          var _a = this, queryManager = _a.queryManager, queryId = _a.queryId;
          if (this.shouldSubscribe) {
              queryManager.addObservableQuery(queryId, this);
          }
          if (this.options.pollInterval) {
              assertNotCacheFirstOrOnly(this);
              queryManager.startPollingQuery(this.options, queryId);
          }
          var onError = function (error) {
              _this.updateLastResult(__assign(__assign({}, _this.lastResult), { errors: error.graphQLErrors, networkStatus: NetworkStatus.error, loading: false }));
              iterateObserversSafely(_this.observers, 'error', _this.lastError = error);
          };
          queryManager.observeQuery(queryId, this.options, {
              next: function (result) {
                  if (_this.lastError || _this.isDifferentFromLastResult(result)) {
                      var previousResult_1 = _this.updateLastResult(result);
                      var _a = _this.options, query_1 = _a.query, variables = _a.variables, fetchPolicy_1 = _a.fetchPolicy;
                      if (queryManager.transform(query_1).hasClientExports) {
                          queryManager.getLocalState().addExportedVariables(query_1, variables).then(function (variables) {
                              var previousVariables = _this.variables;
                              _this.variables = _this.options.variables = variables;
                              if (!result.loading &&
                                  previousResult_1 &&
                                  fetchPolicy_1 !== 'cache-only' &&
                                  queryManager.transform(query_1).serverQuery &&
                                  !equal(previousVariables, variables)) {
                                  _this.refetch();
                              }
                              else {
                                  iterateObserversSafely(_this.observers, 'next', result);
                              }
                          });
                      }
                      else {
                          iterateObserversSafely(_this.observers, 'next', result);
                      }
                  }
              },
              error: onError,
          }).catch(onError);
      };
      ObservableQuery.prototype.tearDownQuery = function () {
          var queryManager = this.queryManager;
          this.isTornDown = true;
          queryManager.stopPollingQuery(this.queryId);
          this.subscriptions.forEach(function (sub) { return sub.unsubscribe(); });
          this.subscriptions.clear();
          queryManager.removeObservableQuery(this.queryId);
          queryManager.stopQuery(this.queryId);
          this.observers.clear();
      };
      return ObservableQuery;
  }(Observable$1));
  function defaultSubscriptionObserverErrorCallback(error) {
      process.env.NODE_ENV === "production" || invariant.error('Unhandled error', error.message, error.stack);
  }
  function iterateObserversSafely(observers, method, argument) {
      var observersWithMethod = [];
      observers.forEach(function (obs) { return obs[method] && observersWithMethod.push(obs); });
      observersWithMethod.forEach(function (obs) { return obs[method](argument); });
  }
  function assertNotCacheFirstOrOnly(obsQuery) {
      var fetchPolicy = obsQuery.options.fetchPolicy;
      process.env.NODE_ENV === "production" ? invariant(fetchPolicy !== 'cache-first' && fetchPolicy !== 'cache-only', 3) : invariant(fetchPolicy !== 'cache-first' && fetchPolicy !== 'cache-only', 'Queries that specify the cache-first and cache-only fetchPolicies cannot also be polling queries.');
  }
  
  var MutationStore = (function () {
      function MutationStore() {
          this.store = {};
      }
      MutationStore.prototype.getStore = function () {
          return this.store;
      };
      MutationStore.prototype.get = function (mutationId) {
          return this.store[mutationId];
      };
      MutationStore.prototype.initMutation = function (mutationId, mutation, variables) {
          this.store[mutationId] = {
              mutation: mutation,
              variables: variables || {},
              loading: true,
              error: null,
          };
      };
      MutationStore.prototype.markMutationError = function (mutationId, error) {
          var mutation = this.store[mutationId];
          if (mutation) {
              mutation.loading = false;
              mutation.error = error;
          }
      };
      MutationStore.prototype.markMutationResult = function (mutationId) {
          var mutation = this.store[mutationId];
          if (mutation) {
              mutation.loading = false;
              mutation.error = null;
          }
      };
      MutationStore.prototype.reset = function () {
          this.store = {};
      };
      return MutationStore;
  }());
  
  var QueryStore = (function () {
      function QueryStore() {
          this.store = {};
      }
      QueryStore.prototype.getStore = function () {
          return this.store;
      };
      QueryStore.prototype.get = function (queryId) {
          return this.store[queryId];
      };
      QueryStore.prototype.initQuery = function (query) {
          var previousQuery = this.store[query.queryId];
          process.env.NODE_ENV === "production" ? invariant(!previousQuery ||
              previousQuery.document === query.document ||
              equal(previousQuery.document, query.document), 19) : invariant(!previousQuery ||
              previousQuery.document === query.document ||
              equal(previousQuery.document, query.document), 'Internal Error: may not update existing query string in store');
          var isSetVariables = false;
          var previousVariables = null;
          if (query.storePreviousVariables &&
              previousQuery &&
              previousQuery.networkStatus !== NetworkStatus.loading) {
              if (!equal(previousQuery.variables, query.variables)) {
                  isSetVariables = true;
                  previousVariables = previousQuery.variables;
              }
          }
          var networkStatus;
          if (isSetVariables) {
              networkStatus = NetworkStatus.setVariables;
          }
          else if (query.isPoll) {
              networkStatus = NetworkStatus.poll;
          }
          else if (query.isRefetch) {
              networkStatus = NetworkStatus.refetch;
          }
          else {
              networkStatus = NetworkStatus.loading;
          }
          var graphQLErrors = [];
          if (previousQuery && previousQuery.graphQLErrors) {
              graphQLErrors = previousQuery.graphQLErrors;
          }
          this.store[query.queryId] = {
              document: query.document,
              variables: query.variables,
              previousVariables: previousVariables,
              networkError: null,
              graphQLErrors: graphQLErrors,
              networkStatus: networkStatus,
              metadata: query.metadata,
          };
          if (typeof query.fetchMoreForQueryId === 'string' &&
              this.store[query.fetchMoreForQueryId]) {
              this.store[query.fetchMoreForQueryId].networkStatus =
                  NetworkStatus.fetchMore;
          }
      };
      QueryStore.prototype.markQueryResult = function (queryId, result, fetchMoreForQueryId) {
          if (!this.store || !this.store[queryId])
              return;
          this.store[queryId].networkError = null;
          this.store[queryId].graphQLErrors = isNonEmptyArray(result.errors) ? result.errors : [];
          this.store[queryId].previousVariables = null;
          this.store[queryId].networkStatus = NetworkStatus.ready;
          if (typeof fetchMoreForQueryId === 'string' &&
              this.store[fetchMoreForQueryId]) {
              this.store[fetchMoreForQueryId].networkStatus = NetworkStatus.ready;
          }
      };
      QueryStore.prototype.markQueryError = function (queryId, error, fetchMoreForQueryId) {
          if (!this.store || !this.store[queryId])
              return;
          this.store[queryId].networkError = error;
          this.store[queryId].networkStatus = NetworkStatus.error;
          if (typeof fetchMoreForQueryId === 'string') {
              this.markQueryResultClient(fetchMoreForQueryId, true);
          }
      };
      QueryStore.prototype.markQueryResultClient = function (queryId, complete) {
          var storeValue = this.store && this.store[queryId];
          if (storeValue) {
              storeValue.networkError = null;
              storeValue.previousVariables = null;
              if (complete) {
                  storeValue.networkStatus = NetworkStatus.ready;
              }
          }
      };
      QueryStore.prototype.stopQuery = function (queryId) {
          delete this.store[queryId];
      };
      QueryStore.prototype.reset = function (observableQueryIds) {
          var _this = this;
          Object.keys(this.store).forEach(function (queryId) {
              if (observableQueryIds.indexOf(queryId) < 0) {
                  _this.stopQuery(queryId);
              }
              else {
                  _this.store[queryId].networkStatus = NetworkStatus.loading;
              }
          });
      };
      return QueryStore;
  }());
  
  function capitalizeFirstLetter(str) {
      return str.charAt(0).toUpperCase() + str.slice(1);
  }
  
  var LocalState = (function () {
      function LocalState(_a) {
          var cache = _a.cache, client = _a.client, resolvers = _a.resolvers, fragmentMatcher = _a.fragmentMatcher;
          this.cache = cache;
          if (client) {
              this.client = client;
          }
          if (resolvers) {
              this.addResolvers(resolvers);
          }
          if (fragmentMatcher) {
              this.setFragmentMatcher(fragmentMatcher);
          }
      }
      LocalState.prototype.addResolvers = function (resolvers) {
          var _this = this;
          this.resolvers = this.resolvers || {};
          if (Array.isArray(resolvers)) {
              resolvers.forEach(function (resolverGroup) {
                  _this.resolvers = mergeDeep(_this.resolvers, resolverGroup);
              });
          }
          else {
              this.resolvers = mergeDeep(this.resolvers, resolvers);
          }
      };
      LocalState.prototype.setResolvers = function (resolvers) {
          this.resolvers = {};
          this.addResolvers(resolvers);
      };
      LocalState.prototype.getResolvers = function () {
          return this.resolvers || {};
      };
      LocalState.prototype.runResolvers = function (_a) {
          var document = _a.document, remoteResult = _a.remoteResult, context = _a.context, variables = _a.variables, _b = _a.onlyRunForcedResolvers, onlyRunForcedResolvers = _b === void 0 ? false : _b;
          return __awaiter(this, void 0, void 0, function () {
              return __generator(this, function (_c) {
                  if (document) {
                      return [2, this.resolveDocument(document, remoteResult.data, context, variables, this.fragmentMatcher, onlyRunForcedResolvers).then(function (localResult) { return (__assign(__assign({}, remoteResult), { data: localResult.result })); })];
                  }
                  return [2, remoteResult];
              });
          });
      };
      LocalState.prototype.setFragmentMatcher = function (fragmentMatcher) {
          this.fragmentMatcher = fragmentMatcher;
      };
      LocalState.prototype.getFragmentMatcher = function () {
          return this.fragmentMatcher;
      };
      LocalState.prototype.clientQuery = function (document) {
          if (hasDirectives(['client'], document)) {
              if (this.resolvers) {
                  return document;
              }
              process.env.NODE_ENV === "production" || invariant.warn('Found @client directives in a query but no ApolloClient resolvers ' +
                  'were specified. This means ApolloClient local resolver handling ' +
                  'has been disabled, and @client directives will be passed through ' +
                  'to your link chain.');
          }
          return null;
      };
      LocalState.prototype.serverQuery = function (document) {
          return this.resolvers ? removeClientSetsFromDocument(document) : document;
      };
      LocalState.prototype.prepareContext = function (context) {
          if (context === void 0) { context = {}; }
          var cache = this.cache;
          var newContext = __assign(__assign({}, context), { cache: cache, getCacheKey: function (obj) {
                  if (cache.config) {
                      return cache.config.dataIdFromObject(obj);
                  }
                  else {
                      process.env.NODE_ENV === "production" ? invariant(false, 6) : invariant(false, 'To use context.getCacheKey, you need to use a cache that has ' +
                          'a configurable dataIdFromObject, like apollo-cache-inmemory.');
                  }
              } });
          return newContext;
      };
      LocalState.prototype.addExportedVariables = function (document, variables, context) {
          if (variables === void 0) { variables = {}; }
          if (context === void 0) { context = {}; }
          return __awaiter(this, void 0, void 0, function () {
              return __generator(this, function (_a) {
                  if (document) {
                      return [2, this.resolveDocument(document, this.buildRootValueFromCache(document, variables) || {}, this.prepareContext(context), variables).then(function (data) { return (__assign(__assign({}, variables), data.exportedVariables)); })];
                  }
                  return [2, __assign({}, variables)];
              });
          });
      };
      LocalState.prototype.shouldForceResolvers = function (document) {
          var forceResolvers = false;
          visit(document, {
              Directive: {
                  enter: function (node) {
                      if (node.name.value === 'client' && node.arguments) {
                          forceResolvers = node.arguments.some(function (arg) {
                              return arg.name.value === 'always' &&
                                  arg.value.kind === 'BooleanValue' &&
                                  arg.value.value === true;
                          });
                          if (forceResolvers) {
                              return BREAK;
                          }
                      }
                  },
              },
          });
          return forceResolvers;
      };
      LocalState.prototype.buildRootValueFromCache = function (document, variables) {
          return this.cache.diff({
              query: buildQueryFromSelectionSet(document),
              variables: variables,
              returnPartialData: true,
              optimistic: false,
          }).result;
      };
      LocalState.prototype.resolveDocument = function (document, rootValue, context, variables, fragmentMatcher, onlyRunForcedResolvers) {
          if (context === void 0) { context = {}; }
          if (variables === void 0) { variables = {}; }
          if (fragmentMatcher === void 0) { fragmentMatcher = function () { return true; }; }
          if (onlyRunForcedResolvers === void 0) { onlyRunForcedResolvers = false; }
          return __awaiter(this, void 0, void 0, function () {
              var mainDefinition, fragments, fragmentMap, definitionOperation, defaultOperationType, _a, cache, client, execContext;
              return __generator(this, function (_b) {
                  mainDefinition = getMainDefinition(document);
                  fragments = getFragmentDefinitions(document);
                  fragmentMap = createFragmentMap(fragments);
                  definitionOperation = mainDefinition
                      .operation;
                  defaultOperationType = definitionOperation
                      ? capitalizeFirstLetter(definitionOperation)
                      : 'Query';
                  _a = this, cache = _a.cache, client = _a.client;
                  execContext = {
                      fragmentMap: fragmentMap,
                      context: __assign(__assign({}, context), { cache: cache,
                          client: client }),
                      variables: variables,
                      fragmentMatcher: fragmentMatcher,
                      defaultOperationType: defaultOperationType,
                      exportedVariables: {},
                      onlyRunForcedResolvers: onlyRunForcedResolvers,
                  };
                  return [2, this.resolveSelectionSet(mainDefinition.selectionSet, rootValue, execContext).then(function (result) { return ({
                          result: result,
                          exportedVariables: execContext.exportedVariables,
                      }); })];
              });
          });
      };
      LocalState.prototype.resolveSelectionSet = function (selectionSet, rootValue, execContext) {
          return __awaiter(this, void 0, void 0, function () {
              var fragmentMap, context, variables, resultsToMerge, execute;
              var _this = this;
              return __generator(this, function (_a) {
                  fragmentMap = execContext.fragmentMap, context = execContext.context, variables = execContext.variables;
                  resultsToMerge = [rootValue];
                  execute = function (selection) { return __awaiter(_this, void 0, void 0, function () {
                      var fragment, typeCondition;
                      return __generator(this, function (_a) {
                          if (!shouldInclude(selection, variables)) {
                              return [2];
                          }
                          if (isField(selection)) {
                              return [2, this.resolveField(selection, rootValue, execContext).then(function (fieldResult) {
                                      var _a;
                                      if (typeof fieldResult !== 'undefined') {
                                          resultsToMerge.push((_a = {},
                                              _a[resultKeyNameFromField(selection)] = fieldResult,
                                              _a));
                                      }
                                  })];
                          }
                          if (isInlineFragment(selection)) {
                              fragment = selection;
                          }
                          else {
                              fragment = fragmentMap[selection.name.value];
                              process.env.NODE_ENV === "production" ? invariant(fragment, 7) : invariant(fragment, "No fragment named " + selection.name.value);
                          }
                          if (fragment && fragment.typeCondition) {
                              typeCondition = fragment.typeCondition.name.value;
                              if (execContext.fragmentMatcher(rootValue, typeCondition, context)) {
                                  return [2, this.resolveSelectionSet(fragment.selectionSet, rootValue, execContext).then(function (fragmentResult) {
                                          resultsToMerge.push(fragmentResult);
                                      })];
                              }
                          }
                          return [2];
                      });
                  }); };
                  return [2, Promise.all(selectionSet.selections.map(execute)).then(function () {
                          return mergeDeepArray(resultsToMerge);
                      })];
              });
          });
      };
      LocalState.prototype.resolveField = function (field, rootValue, execContext) {
          return __awaiter(this, void 0, void 0, function () {
              var variables, fieldName, aliasedFieldName, aliasUsed, defaultResult, resultPromise, resolverType, resolverMap, resolve;
              var _this = this;
              return __generator(this, function (_a) {
                  variables = execContext.variables;
                  fieldName = field.name.value;
                  aliasedFieldName = resultKeyNameFromField(field);
                  aliasUsed = fieldName !== aliasedFieldName;
                  defaultResult = rootValue[aliasedFieldName] || rootValue[fieldName];
                  resultPromise = Promise.resolve(defaultResult);
                  if (!execContext.onlyRunForcedResolvers ||
                      this.shouldForceResolvers(field)) {
                      resolverType = rootValue.__typename || execContext.defaultOperationType;
                      resolverMap = this.resolvers && this.resolvers[resolverType];
                      if (resolverMap) {
                          resolve = resolverMap[aliasUsed ? fieldName : aliasedFieldName];
                          if (resolve) {
                              resultPromise = Promise.resolve(resolve(rootValue, argumentsObjectFromField(field, variables), execContext.context, { field: field, fragmentMap: execContext.fragmentMap }));
                          }
                      }
                  }
                  return [2, resultPromise.then(function (result) {
                          if (result === void 0) { result = defaultResult; }
                          if (field.directives) {
                              field.directives.forEach(function (directive) {
                                  if (directive.name.value === 'export' && directive.arguments) {
                                      directive.arguments.forEach(function (arg) {
                                          if (arg.name.value === 'as' && arg.value.kind === 'StringValue') {
                                              execContext.exportedVariables[arg.value.value] = result;
                                          }
                                      });
                                  }
                              });
                          }
                          if (!field.selectionSet) {
                              return result;
                          }
                          if (result == null) {
                              return result;
                          }
                          if (Array.isArray(result)) {
                              return _this.resolveSubSelectedArray(field, result, execContext);
                          }
                          if (field.selectionSet) {
                              return _this.resolveSelectionSet(field.selectionSet, result, execContext);
                          }
                      })];
              });
          });
      };
      LocalState.prototype.resolveSubSelectedArray = function (field, result, execContext) {
          var _this = this;
          return Promise.all(result.map(function (item) {
              if (item === null) {
                  return null;
              }
              if (Array.isArray(item)) {
                  return _this.resolveSubSelectedArray(field, item, execContext);
              }
              if (field.selectionSet) {
                  return _this.resolveSelectionSet(field.selectionSet, item, execContext);
              }
          }));
      };
      return LocalState;
  }());
  
  function multiplex(inner) {
      var observers = new Set();
      var sub = null;
      return new Observable$1(function (observer) {
          observers.add(observer);
          sub = sub || inner.subscribe({
              next: function (value) {
                  observers.forEach(function (obs) { return obs.next && obs.next(value); });
              },
              error: function (error) {
                  observers.forEach(function (obs) { return obs.error && obs.error(error); });
              },
              complete: function () {
                  observers.forEach(function (obs) { return obs.complete && obs.complete(); });
              },
          });
          return function () {
              if (observers.delete(observer) && !observers.size && sub) {
                  sub.unsubscribe();
                  sub = null;
              }
          };
      });
  }
  function asyncMap(observable, mapFn) {
      return new Observable$1(function (observer) {
          var next = observer.next, error = observer.error, complete = observer.complete;
          var activeNextCount = 0;
          var completed = false;
          var handler = {
              next: function (value) {
                  ++activeNextCount;
                  new Promise(function (resolve) {
                      resolve(mapFn(value));
                  }).then(function (result) {
                      --activeNextCount;
                      next && next.call(observer, result);
                      completed && handler.complete();
                  }, function (e) {
                      --activeNextCount;
                      error && error.call(observer, e);
                  });
              },
              error: function (e) {
                  error && error.call(observer, e);
              },
              complete: function () {
                  completed = true;
                  if (!activeNextCount) {
                      complete && complete.call(observer);
                  }
              },
          };
          var sub = observable.subscribe(handler);
          return function () { return sub.unsubscribe(); };
      });
  }
  
  var hasOwnProperty$2 = Object.prototype.hasOwnProperty;
  var QueryManager = (function () {
      function QueryManager(_a) {
          var link = _a.link, _b = _a.queryDeduplication, queryDeduplication = _b === void 0 ? false : _b, store = _a.store, _c = _a.onBroadcast, onBroadcast = _c === void 0 ? function () { return undefined; } : _c, _d = _a.ssrMode, ssrMode = _d === void 0 ? false : _d, _e = _a.clientAwareness, clientAwareness = _e === void 0 ? {} : _e, localState = _a.localState, assumeImmutableResults = _a.assumeImmutableResults;
          this.mutationStore = new MutationStore();
          this.queryStore = new QueryStore();
          this.clientAwareness = {};
          this.idCounter = 1;
          this.queries = new Map();
          this.fetchQueryRejectFns = new Map();
          this.transformCache = new (canUseWeakMap ? WeakMap : Map)();
          this.inFlightLinkObservables = new Map();
          this.pollingInfoByQueryId = new Map();
          this.link = link;
          this.queryDeduplication = queryDeduplication;
          this.dataStore = store;
          this.onBroadcast = onBroadcast;
          this.clientAwareness = clientAwareness;
          this.localState = localState || new LocalState({ cache: store.getCache() });
          this.ssrMode = ssrMode;
          this.assumeImmutableResults = !!assumeImmutableResults;
      }
      QueryManager.prototype.stop = function () {
          var _this = this;
          this.queries.forEach(function (_info, queryId) {
              _this.stopQueryNoBroadcast(queryId);
          });
          this.fetchQueryRejectFns.forEach(function (reject) {
              reject(process.env.NODE_ENV === "production" ? new InvariantError(8) : new InvariantError('QueryManager stopped while query was in flight'));
          });
      };
      QueryManager.prototype.mutate = function (_a) {
          var mutation = _a.mutation, variables = _a.variables, optimisticResponse = _a.optimisticResponse, updateQueriesByName = _a.updateQueries, _b = _a.refetchQueries, refetchQueries = _b === void 0 ? [] : _b, _c = _a.awaitRefetchQueries, awaitRefetchQueries = _c === void 0 ? false : _c, updateWithProxyFn = _a.update, _d = _a.errorPolicy, errorPolicy = _d === void 0 ? 'none' : _d, fetchPolicy = _a.fetchPolicy, _e = _a.context, context = _e === void 0 ? {} : _e;
          return __awaiter(this, void 0, void 0, function () {
              var mutationId, generateUpdateQueriesInfo, self;
              var _this = this;
              return __generator(this, function (_f) {
                  switch (_f.label) {
                      case 0:
                          process.env.NODE_ENV === "production" ? invariant(mutation, 9) : invariant(mutation, 'mutation option is required. You must specify your GraphQL document in the mutation option.');
                          process.env.NODE_ENV === "production" ? invariant(!fetchPolicy || fetchPolicy === 'no-cache', 10) : invariant(!fetchPolicy || fetchPolicy === 'no-cache', "Mutations only support a 'no-cache' fetchPolicy. If you don't want to disable the cache, remove your fetchPolicy setting to proceed with the default mutation behavior.");
                          mutationId = this.generateQueryId();
                          mutation = this.transform(mutation).document;
                          this.setQuery(mutationId, function () { return ({ document: mutation }); });
                          variables = this.getVariables(mutation, variables);
                          if (!this.transform(mutation).hasClientExports) return [3, 2];
                          return [4, this.localState.addExportedVariables(mutation, variables, context)];
                      case 1:
                          variables = _f.sent();
                          _f.label = 2;
                      case 2:
                          generateUpdateQueriesInfo = function () {
                              var ret = {};
                              if (updateQueriesByName) {
                                  _this.queries.forEach(function (_a, queryId) {
                                      var observableQuery = _a.observableQuery;
                                      if (observableQuery) {
                                          var queryName = observableQuery.queryName;
                                          if (queryName &&
                                              hasOwnProperty$2.call(updateQueriesByName, queryName)) {
                                              ret[queryId] = {
                                                  updater: updateQueriesByName[queryName],
                                                  query: _this.queryStore.get(queryId),
                                              };
                                          }
                                      }
                                  });
                              }
                              return ret;
                          };
                          this.mutationStore.initMutation(mutationId, mutation, variables);
                          this.dataStore.markMutationInit({
                              mutationId: mutationId,
                              document: mutation,
                              variables: variables,
                              updateQueries: generateUpdateQueriesInfo(),
                              update: updateWithProxyFn,
                              optimisticResponse: optimisticResponse,
                          });
                          this.broadcastQueries();
                          self = this;
                          return [2, new Promise(function (resolve, reject) {
                                  var storeResult;
                                  var error;
                                  self.getObservableFromLink(mutation, __assign(__assign({}, context), { optimisticResponse: optimisticResponse }), variables, false).subscribe({
                                      next: function (result) {
                                          if (graphQLResultHasError(result) && errorPolicy === 'none') {
                                              error = new ApolloError({
                                                  graphQLErrors: result.errors,
                                              });
                                              return;
                                          }
                                          self.mutationStore.markMutationResult(mutationId);
                                          if (fetchPolicy !== 'no-cache') {
                                              self.dataStore.markMutationResult({
                                                  mutationId: mutationId,
                                                  result: result,
                                                  document: mutation,
                                                  variables: variables,
                                                  updateQueries: generateUpdateQueriesInfo(),
                                                  update: updateWithProxyFn,
                                              });
                                          }
                                          storeResult = result;
                                      },
                                      error: function (err) {
                                          self.mutationStore.markMutationError(mutationId, err);
                                          self.dataStore.markMutationComplete({
                                              mutationId: mutationId,
                                              optimisticResponse: optimisticResponse,
                                          });
                                          self.broadcastQueries();
                                          self.setQuery(mutationId, function () { return ({ document: null }); });
                                          reject(new ApolloError({
                                              networkError: err,
                                          }));
                                      },
                                      complete: function () {
                                          if (error) {
                                              self.mutationStore.markMutationError(mutationId, error);
                                          }
                                          self.dataStore.markMutationComplete({
                                              mutationId: mutationId,
                                              optimisticResponse: optimisticResponse,
                                          });
                                          self.broadcastQueries();
                                          if (error) {
                                              reject(error);
                                              return;
                                          }
                                          if (typeof refetchQueries === 'function') {
                                              refetchQueries = refetchQueries(storeResult);
                                          }
                                          var refetchQueryPromises = [];
                                          if (isNonEmptyArray(refetchQueries)) {
                                              refetchQueries.forEach(function (refetchQuery) {
                                                  if (typeof refetchQuery === 'string') {
                                                      self.queries.forEach(function (_a) {
                                                          var observableQuery = _a.observableQuery;
                                                          if (observableQuery &&
                                                              observableQuery.queryName === refetchQuery) {
                                                              refetchQueryPromises.push(observableQuery.refetch());
                                                          }
                                                      });
                                                  }
                                                  else {
                                                      var queryOptions = {
                                                          query: refetchQuery.query,
                                                          variables: refetchQuery.variables,
                                                          fetchPolicy: 'network-only',
                                                      };
                                                      if (refetchQuery.context) {
                                                          queryOptions.context = refetchQuery.context;
                                                      }
                                                      refetchQueryPromises.push(self.query(queryOptions));
                                                  }
                                              });
                                          }
                                          Promise.all(awaitRefetchQueries ? refetchQueryPromises : []).then(function () {
                                              self.setQuery(mutationId, function () { return ({ document: null }); });
                                              if (errorPolicy === 'ignore' &&
                                                  storeResult &&
                                                  graphQLResultHasError(storeResult)) {
                                                  delete storeResult.errors;
                                              }
                                              resolve(storeResult);
                                          });
                                      },
                                  });
                              })];
                  }
              });
          });
      };
      QueryManager.prototype.fetchQuery = function (queryId, options, fetchType, fetchMoreForQueryId) {
          return __awaiter(this, void 0, void 0, function () {
              var _a, metadata, _b, fetchPolicy, _c, context, query, variables, storeResult, isNetworkOnly, needToFetch, _d, complete, result, shouldFetch, requestId, cancel, networkResult;
              var _this = this;
              return __generator(this, function (_e) {
                  switch (_e.label) {
                      case 0:
                          _a = options.metadata, metadata = _a === void 0 ? null : _a, _b = options.fetchPolicy, fetchPolicy = _b === void 0 ? 'cache-first' : _b, _c = options.context, context = _c === void 0 ? {} : _c;
                          query = this.transform(options.query).document;
                          variables = this.getVariables(query, options.variables);
                          if (!this.transform(query).hasClientExports) return [3, 2];
                          return [4, this.localState.addExportedVariables(query, variables, context)];
                      case 1:
                          variables = _e.sent();
                          _e.label = 2;
                      case 2:
                          options = __assign(__assign({}, options), { variables: variables });
                          isNetworkOnly = fetchPolicy === 'network-only' || fetchPolicy === 'no-cache';
                          needToFetch = isNetworkOnly;
                          if (!isNetworkOnly) {
                              _d = this.dataStore.getCache().diff({
                                  query: query,
                                  variables: variables,
                                  returnPartialData: true,
                                  optimistic: false,
                              }), complete = _d.complete, result = _d.result;
                              needToFetch = !complete || fetchPolicy === 'cache-and-network';
                              storeResult = result;
                          }
                          shouldFetch = needToFetch && fetchPolicy !== 'cache-only' && fetchPolicy !== 'standby';
                          if (hasDirectives(['live'], query))
                              shouldFetch = true;
                          requestId = this.idCounter++;
                          cancel = fetchPolicy !== 'no-cache'
                              ? this.updateQueryWatch(queryId, query, options)
                              : undefined;
                          this.setQuery(queryId, function () { return ({
                              document: query,
                              lastRequestId: requestId,
                              invalidated: true,
                              cancel: cancel,
                          }); });
                          this.invalidate(fetchMoreForQueryId);
                          this.queryStore.initQuery({
                              queryId: queryId,
                              document: query,
                              storePreviousVariables: shouldFetch,
                              variables: variables,
                              isPoll: fetchType === FetchType.poll,
                              isRefetch: fetchType === FetchType.refetch,
                              metadata: metadata,
                              fetchMoreForQueryId: fetchMoreForQueryId,
                          });
                          this.broadcastQueries();
                          if (shouldFetch) {
                              networkResult = this.fetchRequest({
                                  requestId: requestId,
                                  queryId: queryId,
                                  document: query,
                                  options: options,
                                  fetchMoreForQueryId: fetchMoreForQueryId,
                              }).catch(function (error) {
                                  if (isApolloError(error)) {
                                      throw error;
                                  }
                                  else {
                                      if (requestId >= _this.getQuery(queryId).lastRequestId) {
                                          _this.queryStore.markQueryError(queryId, error, fetchMoreForQueryId);
                                          _this.invalidate(queryId);
                                          _this.invalidate(fetchMoreForQueryId);
                                          _this.broadcastQueries();
                                      }
                                      throw new ApolloError({ networkError: error });
                                  }
                              });
                              if (fetchPolicy !== 'cache-and-network') {
                                  return [2, networkResult];
                              }
                              networkResult.catch(function () { });
                          }
                          this.queryStore.markQueryResultClient(queryId, !shouldFetch);
                          this.invalidate(queryId);
                          this.invalidate(fetchMoreForQueryId);
                          if (this.transform(query).hasForcedResolvers) {
                              return [2, this.localState.runResolvers({
                                      document: query,
                                      remoteResult: { data: storeResult },
                                      context: context,
                                      variables: variables,
                                      onlyRunForcedResolvers: true,
                                  }).then(function (result) {
                                      _this.markQueryResult(queryId, result, options, fetchMoreForQueryId);
                                      _this.broadcastQueries();
                                      return result;
                                  })];
                          }
                          this.broadcastQueries();
                          return [2, { data: storeResult }];
                  }
              });
          });
      };
      QueryManager.prototype.markQueryResult = function (queryId, result, _a, fetchMoreForQueryId) {
          var fetchPolicy = _a.fetchPolicy, variables = _a.variables, errorPolicy = _a.errorPolicy;
          if (fetchPolicy === 'no-cache') {
              this.setQuery(queryId, function () { return ({
                  newData: { result: result.data, complete: true },
              }); });
          }
          else {
              this.dataStore.markQueryResult(result, this.getQuery(queryId).document, variables, fetchMoreForQueryId, errorPolicy === 'ignore' || errorPolicy === 'all');
          }
      };
      QueryManager.prototype.queryListenerForObserver = function (queryId, options, observer) {
          var _this = this;
          function invoke(method, argument) {
              if (observer[method]) {
                  try {
                      observer[method](argument);
                  }
                  catch (e) {
                      process.env.NODE_ENV === "production" || invariant.error(e);
                  }
              }
              else if (method === 'error') {
                  process.env.NODE_ENV === "production" || invariant.error(argument);
              }
          }
          return function (queryStoreValue, newData) {
              _this.invalidate(queryId, false);
              if (!queryStoreValue)
                  return;
              var _a = _this.getQuery(queryId), observableQuery = _a.observableQuery, document = _a.document;
              var fetchPolicy = observableQuery
                  ? observableQuery.options.fetchPolicy
                  : options.fetchPolicy;
              if (fetchPolicy === 'standby')
                  return;
              var loading = isNetworkRequestInFlight(queryStoreValue.networkStatus);
              var lastResult = observableQuery && observableQuery.getLastResult();
              var networkStatusChanged = !!(lastResult &&
                  lastResult.networkStatus !== queryStoreValue.networkStatus);
              var shouldNotifyIfLoading = options.returnPartialData ||
                  (!newData && queryStoreValue.previousVariables) ||
                  (networkStatusChanged && options.notifyOnNetworkStatusChange) ||
                  fetchPolicy === 'cache-only' ||
                  fetchPolicy === 'cache-and-network';
              if (loading && !shouldNotifyIfLoading) {
                  return;
              }
              var hasGraphQLErrors = isNonEmptyArray(queryStoreValue.graphQLErrors);
              var errorPolicy = observableQuery
                  && observableQuery.options.errorPolicy
                  || options.errorPolicy
                  || 'none';
              if (errorPolicy === 'none' && hasGraphQLErrors || queryStoreValue.networkError) {
                  return invoke('error', new ApolloError({
                      graphQLErrors: queryStoreValue.graphQLErrors,
                      networkError: queryStoreValue.networkError,
                  }));
              }
              try {
                  var data = void 0;
                  var isMissing = void 0;
                  if (newData) {
                      if (fetchPolicy !== 'no-cache' && fetchPolicy !== 'network-only') {
                          _this.setQuery(queryId, function () { return ({ newData: null }); });
                      }
                      data = newData.result;
                      isMissing = !newData.complete;
                  }
                  else {
                      var lastError = observableQuery && observableQuery.getLastError();
                      var errorStatusChanged = errorPolicy !== 'none' &&
                          (lastError && lastError.graphQLErrors) !==
                              queryStoreValue.graphQLErrors;
                      if (lastResult && lastResult.data && !errorStatusChanged) {
                          data = lastResult.data;
                          isMissing = false;
                      }
                      else {
                          var diffResult = _this.dataStore.getCache().diff({
                              query: document,
                              variables: queryStoreValue.previousVariables ||
                                  queryStoreValue.variables,
                              returnPartialData: true,
                              optimistic: true,
                          });
                          data = diffResult.result;
                          isMissing = !diffResult.complete;
                      }
                  }
                  var stale = isMissing && !(options.returnPartialData ||
                      fetchPolicy === 'cache-only');
                  var resultFromStore = {
                      data: stale ? lastResult && lastResult.data : data,
                      loading: loading,
                      networkStatus: queryStoreValue.networkStatus,
                      stale: stale,
                  };
                  if (errorPolicy === 'all' && hasGraphQLErrors) {
                      resultFromStore.errors = queryStoreValue.graphQLErrors;
                  }
                  invoke('next', resultFromStore);
              }
              catch (networkError) {
                  invoke('error', new ApolloError({ networkError: networkError }));
              }
          };
      };
      QueryManager.prototype.transform = function (document) {
          var transformCache = this.transformCache;
          if (!transformCache.has(document)) {
              var cache = this.dataStore.getCache();
              var transformed = cache.transformDocument(document);
              var forLink = removeConnectionDirectiveFromDocument(cache.transformForLink(transformed));
              var clientQuery = this.localState.clientQuery(transformed);
              var serverQuery = this.localState.serverQuery(forLink);
              var cacheEntry_1 = {
                  document: transformed,
                  hasClientExports: hasClientExports(transformed),
                  hasForcedResolvers: this.localState.shouldForceResolvers(transformed),
                  clientQuery: clientQuery,
                  serverQuery: serverQuery,
                  defaultVars: getDefaultValues(getOperationDefinition(transformed)),
              };
              var add = function (doc) {
                  if (doc && !transformCache.has(doc)) {
                      transformCache.set(doc, cacheEntry_1);
                  }
              };
              add(document);
              add(transformed);
              add(clientQuery);
              add(serverQuery);
          }
          return transformCache.get(document);
      };
      QueryManager.prototype.getVariables = function (document, variables) {
          return __assign(__assign({}, this.transform(document).defaultVars), variables);
      };
      QueryManager.prototype.watchQuery = function (options, shouldSubscribe) {
          if (shouldSubscribe === void 0) { shouldSubscribe = true; }
          process.env.NODE_ENV === "production" ? invariant(options.fetchPolicy !== 'standby', 11) : invariant(options.fetchPolicy !== 'standby', 'client.watchQuery cannot be called with fetchPolicy set to "standby"');
          options.variables = this.getVariables(options.query, options.variables);
          if (typeof options.notifyOnNetworkStatusChange === 'undefined') {
              options.notifyOnNetworkStatusChange = false;
          }
          var transformedOptions = __assign({}, options);
          return new ObservableQuery({
              queryManager: this,
              options: transformedOptions,
              shouldSubscribe: shouldSubscribe,
          });
      };
      QueryManager.prototype.query = function (options) {
          var _this = this;
          process.env.NODE_ENV === "production" ? invariant(options.query, 12) : invariant(options.query, 'query option is required. You must specify your GraphQL document ' +
              'in the query option.');
          process.env.NODE_ENV === "production" ? invariant(options.query.kind === 'Document', 13) : invariant(options.query.kind === 'Document', 'You must wrap the query string in a "gql" tag.');
          process.env.NODE_ENV === "production" ? invariant(!options.returnPartialData, 14) : invariant(!options.returnPartialData, 'returnPartialData option only supported on watchQuery.');
          process.env.NODE_ENV === "production" ? invariant(!options.pollInterval, 15) : invariant(!options.pollInterval, 'pollInterval option only supported on watchQuery.');
          return new Promise(function (resolve, reject) {
              var watchedQuery = _this.watchQuery(options, false);
              _this.fetchQueryRejectFns.set("query:" + watchedQuery.queryId, reject);
              watchedQuery
                  .result()
                  .then(resolve, reject)
                  .then(function () {
                  return _this.fetchQueryRejectFns.delete("query:" + watchedQuery.queryId);
              });
          });
      };
      QueryManager.prototype.generateQueryId = function () {
          return String(this.idCounter++);
      };
      QueryManager.prototype.stopQueryInStore = function (queryId) {
          this.stopQueryInStoreNoBroadcast(queryId);
          this.broadcastQueries();
      };
      QueryManager.prototype.stopQueryInStoreNoBroadcast = function (queryId) {
          this.stopPollingQuery(queryId);
          this.queryStore.stopQuery(queryId);
          this.invalidate(queryId);
      };
      QueryManager.prototype.addQueryListener = function (queryId, listener) {
          this.setQuery(queryId, function (_a) {
              var listeners = _a.listeners;
              listeners.add(listener);
              return { invalidated: false };
          });
      };
      QueryManager.prototype.updateQueryWatch = function (queryId, document, options) {
          var _this = this;
          var cancel = this.getQuery(queryId).cancel;
          if (cancel)
              cancel();
          var previousResult = function () {
              var previousResult = null;
              var observableQuery = _this.getQuery(queryId).observableQuery;
              if (observableQuery) {
                  var lastResult = observableQuery.getLastResult();
                  if (lastResult) {
                      previousResult = lastResult.data;
                  }
              }
              return previousResult;
          };
          return this.dataStore.getCache().watch({
              query: document,
              variables: options.variables,
              optimistic: true,
              previousResult: previousResult,
              callback: function (newData) {
                  _this.setQuery(queryId, function () { return ({ invalidated: true, newData: newData }); });
              },
          });
      };
      QueryManager.prototype.addObservableQuery = function (queryId, observableQuery) {
          this.setQuery(queryId, function () { return ({ observableQuery: observableQuery }); });
      };
      QueryManager.prototype.removeObservableQuery = function (queryId) {
          var cancel = this.getQuery(queryId).cancel;
          this.setQuery(queryId, function () { return ({ observableQuery: null }); });
          if (cancel)
              cancel();
      };
      QueryManager.prototype.clearStore = function () {
          this.fetchQueryRejectFns.forEach(function (reject) {
              reject(process.env.NODE_ENV === "production" ? new InvariantError(16) : new InvariantError('Store reset while query was in flight (not completed in link chain)'));
          });
          var resetIds = [];
          this.queries.forEach(function (_a, queryId) {
              var observableQuery = _a.observableQuery;
              if (observableQuery)
                  resetIds.push(queryId);
          });
          this.queryStore.reset(resetIds);
          this.mutationStore.reset();
          return this.dataStore.reset();
      };
      QueryManager.prototype.resetStore = function () {
          var _this = this;
          return this.clearStore().then(function () {
              return _this.reFetchObservableQueries();
          });
      };
      QueryManager.prototype.reFetchObservableQueries = function (includeStandby) {
          var _this = this;
          if (includeStandby === void 0) { includeStandby = false; }
          var observableQueryPromises = [];
          this.queries.forEach(function (_a, queryId) {
              var observableQuery = _a.observableQuery;
              if (observableQuery) {
                  var fetchPolicy = observableQuery.options.fetchPolicy;
                  observableQuery.resetLastResults();
                  if (fetchPolicy !== 'cache-only' &&
                      (includeStandby || fetchPolicy !== 'standby')) {
                      observableQueryPromises.push(observableQuery.refetch());
                  }
                  _this.setQuery(queryId, function () { return ({ newData: null }); });
                  _this.invalidate(queryId);
              }
          });
          this.broadcastQueries();
          return Promise.all(observableQueryPromises);
      };
      QueryManager.prototype.observeQuery = function (queryId, options, observer) {
          this.addQueryListener(queryId, this.queryListenerForObserver(queryId, options, observer));
          return this.fetchQuery(queryId, options);
      };
      QueryManager.prototype.startQuery = function (queryId, options, listener) {
          process.env.NODE_ENV === "production" || invariant.warn("The QueryManager.startQuery method has been deprecated");
          this.addQueryListener(queryId, listener);
          this.fetchQuery(queryId, options)
              .catch(function () { return undefined; });
          return queryId;
      };
      QueryManager.prototype.startGraphQLSubscription = function (_a) {
          var _this = this;
          var query = _a.query, fetchPolicy = _a.fetchPolicy, variables = _a.variables;
          query = this.transform(query).document;
          variables = this.getVariables(query, variables);
          var makeObservable = function (variables) {
              return _this.getObservableFromLink(query, {}, variables, false).map(function (result) {
                  if (!fetchPolicy || fetchPolicy !== 'no-cache') {
                      _this.dataStore.markSubscriptionResult(result, query, variables);
                      _this.broadcastQueries();
                  }
                  if (graphQLResultHasError(result)) {
                      throw new ApolloError({
                          graphQLErrors: result.errors,
                      });
                  }
                  return result;
              });
          };
          if (this.transform(query).hasClientExports) {
              var observablePromise_1 = this.localState.addExportedVariables(query, variables).then(makeObservable);
              return new Observable$1(function (observer) {
                  var sub = null;
                  observablePromise_1.then(function (observable) { return sub = observable.subscribe(observer); }, observer.error);
                  return function () { return sub && sub.unsubscribe(); };
              });
          }
          return makeObservable(variables);
      };
      QueryManager.prototype.stopQuery = function (queryId) {
          this.stopQueryNoBroadcast(queryId);
          this.broadcastQueries();
      };
      QueryManager.prototype.stopQueryNoBroadcast = function (queryId) {
          this.stopQueryInStoreNoBroadcast(queryId);
          this.removeQuery(queryId);
      };
      QueryManager.prototype.removeQuery = function (queryId) {
          this.fetchQueryRejectFns.delete("query:" + queryId);
          this.fetchQueryRejectFns.delete("fetchRequest:" + queryId);
          this.getQuery(queryId).subscriptions.forEach(function (x) { return x.unsubscribe(); });
          this.queries.delete(queryId);
      };
      QueryManager.prototype.getCurrentQueryResult = function (observableQuery, optimistic) {
          if (optimistic === void 0) { optimistic = true; }
          var _a = observableQuery.options, variables = _a.variables, query = _a.query, fetchPolicy = _a.fetchPolicy, returnPartialData = _a.returnPartialData;
          var lastResult = observableQuery.getLastResult();
          var newData = this.getQuery(observableQuery.queryId).newData;
          if (newData && newData.complete) {
              return { data: newData.result, partial: false };
          }
          if (fetchPolicy === 'no-cache' || fetchPolicy === 'network-only') {
              return { data: undefined, partial: false };
          }
          var _b = this.dataStore.getCache().diff({
              query: query,
              variables: variables,
              previousResult: lastResult ? lastResult.data : undefined,
              returnPartialData: true,
              optimistic: optimistic,
          }), result = _b.result, complete = _b.complete;
          return {
              data: (complete || returnPartialData) ? result : void 0,
              partial: !complete,
          };
      };
      QueryManager.prototype.getQueryWithPreviousResult = function (queryIdOrObservable) {
          var observableQuery;
          if (typeof queryIdOrObservable === 'string') {
              var foundObserveableQuery = this.getQuery(queryIdOrObservable).observableQuery;
              process.env.NODE_ENV === "production" ? invariant(foundObserveableQuery, 17) : invariant(foundObserveableQuery, "ObservableQuery with this id doesn't exist: " + queryIdOrObservable);
              observableQuery = foundObserveableQuery;
          }
          else {
              observableQuery = queryIdOrObservable;
          }
          var _a = observableQuery.options, variables = _a.variables, query = _a.query;
          return {
              previousResult: this.getCurrentQueryResult(observableQuery, false).data,
              variables: variables,
              document: query,
          };
      };
      QueryManager.prototype.broadcastQueries = function () {
          var _this = this;
          this.onBroadcast();
          this.queries.forEach(function (info, id) {
              if (info.invalidated) {
                  info.listeners.forEach(function (listener) {
                      if (listener) {
                          listener(_this.queryStore.get(id), info.newData);
                      }
                  });
              }
          });
      };
      QueryManager.prototype.getLocalState = function () {
          return this.localState;
      };
      QueryManager.prototype.getObservableFromLink = function (query, context, variables, deduplication) {
          var _this = this;
          if (deduplication === void 0) { deduplication = this.queryDeduplication; }
          var observable;
          var serverQuery = this.transform(query).serverQuery;
          if (serverQuery) {
              var _a = this, inFlightLinkObservables_1 = _a.inFlightLinkObservables, link = _a.link;
              var operation = {
                  query: serverQuery,
                  variables: variables,
                  operationName: getOperationName(serverQuery) || void 0,
                  context: this.prepareContext(__assign(__assign({}, context), { forceFetch: !deduplication })),
              };
              context = operation.context;
              if (deduplication) {
                  var byVariables_1 = inFlightLinkObservables_1.get(serverQuery) || new Map();
                  inFlightLinkObservables_1.set(serverQuery, byVariables_1);
                  var varJson_1 = JSON.stringify(variables);
                  observable = byVariables_1.get(varJson_1);
                  if (!observable) {
                      byVariables_1.set(varJson_1, observable = multiplex(execute(link, operation)));
                      var cleanup = function () {
                          byVariables_1.delete(varJson_1);
                          if (!byVariables_1.size)
                              inFlightLinkObservables_1.delete(serverQuery);
                          cleanupSub_1.unsubscribe();
                      };
                      var cleanupSub_1 = observable.subscribe({
                          next: cleanup,
                          error: cleanup,
                          complete: cleanup,
                      });
                  }
              }
              else {
                  observable = multiplex(execute(link, operation));
              }
          }
          else {
              observable = Observable$1.of({ data: {} });
              context = this.prepareContext(context);
          }
          var clientQuery = this.transform(query).clientQuery;
          if (clientQuery) {
              observable = asyncMap(observable, function (result) {
                  return _this.localState.runResolvers({
                      document: clientQuery,
                      remoteResult: result,
                      context: context,
                      variables: variables,
                  });
              });
          }
          return observable;
      };
      QueryManager.prototype.fetchRequest = function (_a) {
          var _this = this;
          var requestId = _a.requestId, queryId = _a.queryId, document = _a.document, options = _a.options, fetchMoreForQueryId = _a.fetchMoreForQueryId;
          var variables = options.variables, _b = options.errorPolicy, errorPolicy = _b === void 0 ? 'none' : _b, fetchPolicy = options.fetchPolicy;
          var resultFromStore;
          var errorsFromStore;
          return new Promise(function (resolve, reject) {
              var observable = _this.getObservableFromLink(document, options.context, variables);
              var fqrfId = "fetchRequest:" + queryId;
              _this.fetchQueryRejectFns.set(fqrfId, reject);
              var cleanup = function () {
                  _this.fetchQueryRejectFns.delete(fqrfId);
                  _this.setQuery(queryId, function (_a) {
                      var subscriptions = _a.subscriptions;
                      subscriptions.delete(subscription);
                  });
              };
              var subscription = observable.map(function (result) {
                  if (requestId >= _this.getQuery(queryId).lastRequestId) {
                      _this.markQueryResult(queryId, result, options, fetchMoreForQueryId);
                      _this.queryStore.markQueryResult(queryId, result, fetchMoreForQueryId);
                      _this.invalidate(queryId);
                      _this.invalidate(fetchMoreForQueryId);
                      _this.broadcastQueries();
                  }
                  if (errorPolicy === 'none' && isNonEmptyArray(result.errors)) {
                      return reject(new ApolloError({
                          graphQLErrors: result.errors,
                      }));
                  }
                  if (errorPolicy === 'all') {
                      errorsFromStore = result.errors;
                  }
                  if (fetchMoreForQueryId || fetchPolicy === 'no-cache') {
                      resultFromStore = result.data;
                  }
                  else {
                      var _a = _this.dataStore.getCache().diff({
                          variables: variables,
                          query: document,
                          optimistic: false,
                          returnPartialData: true,
                      }), result_1 = _a.result, complete = _a.complete;
                      if (complete || options.returnPartialData) {
                          resultFromStore = result_1;
                      }
                  }
              }).subscribe({
                  error: function (error) {
                      cleanup();
                      reject(error);
                  },
                  complete: function () {
                      cleanup();
                      resolve({
                          data: resultFromStore,
                          errors: errorsFromStore,
                          loading: false,
                          networkStatus: NetworkStatus.ready,
                          stale: false,
                      });
                  },
              });
              _this.setQuery(queryId, function (_a) {
                  var subscriptions = _a.subscriptions;
                  subscriptions.add(subscription);
              });
          });
      };
      QueryManager.prototype.getQuery = function (queryId) {
          return (this.queries.get(queryId) || {
              listeners: new Set(),
              invalidated: false,
              document: null,
              newData: null,
              lastRequestId: 1,
              observableQuery: null,
              subscriptions: new Set(),
          });
      };
      QueryManager.prototype.setQuery = function (queryId, updater) {
          var prev = this.getQuery(queryId);
          var newInfo = __assign(__assign({}, prev), updater(prev));
          this.queries.set(queryId, newInfo);
      };
      QueryManager.prototype.invalidate = function (queryId, invalidated) {
          if (invalidated === void 0) { invalidated = true; }
          if (queryId) {
              this.setQuery(queryId, function () { return ({ invalidated: invalidated }); });
          }
      };
      QueryManager.prototype.prepareContext = function (context) {
          if (context === void 0) { context = {}; }
          var newContext = this.localState.prepareContext(context);
          return __assign(__assign({}, newContext), { clientAwareness: this.clientAwareness });
      };
      QueryManager.prototype.checkInFlight = function (queryId) {
          var query = this.queryStore.get(queryId);
          return (query &&
              query.networkStatus !== NetworkStatus.ready &&
              query.networkStatus !== NetworkStatus.error);
      };
      QueryManager.prototype.startPollingQuery = function (options, queryId, listener) {
          var _this = this;
          var pollInterval = options.pollInterval;
          process.env.NODE_ENV === "production" ? invariant(pollInterval, 18) : invariant(pollInterval, 'Attempted to start a polling query without a polling interval.');
          if (!this.ssrMode) {
              var info = this.pollingInfoByQueryId.get(queryId);
              if (!info) {
                  this.pollingInfoByQueryId.set(queryId, (info = {}));
              }
              info.interval = pollInterval;
              info.options = __assign(__assign({}, options), { fetchPolicy: 'network-only' });
              var maybeFetch_1 = function () {
                  var info = _this.pollingInfoByQueryId.get(queryId);
                  if (info) {
                      if (_this.checkInFlight(queryId)) {
                          poll_1();
                      }
                      else {
                          _this.fetchQuery(queryId, info.options, FetchType.poll).then(poll_1, poll_1);
                      }
                  }
              };
              var poll_1 = function () {
                  var info = _this.pollingInfoByQueryId.get(queryId);
                  if (info) {
                      clearTimeout(info.timeout);
                      info.timeout = setTimeout(maybeFetch_1, info.interval);
                  }
              };
              if (listener) {
                  this.addQueryListener(queryId, listener);
              }
              poll_1();
          }
          return queryId;
      };
      QueryManager.prototype.stopPollingQuery = function (queryId) {
          this.pollingInfoByQueryId.delete(queryId);
      };
      return QueryManager;
  }());
  
  var DataStore = (function () {
      function DataStore(initialCache) {
          this.cache = initialCache;
      }
      DataStore.prototype.getCache = function () {
          return this.cache;
      };
      DataStore.prototype.markQueryResult = function (result, document, variables, fetchMoreForQueryId, ignoreErrors) {
          if (ignoreErrors === void 0) { ignoreErrors = false; }
          var writeWithErrors = !graphQLResultHasError(result);
          if (ignoreErrors && graphQLResultHasError(result) && result.data) {
              writeWithErrors = true;
          }
          if (!fetchMoreForQueryId && writeWithErrors) {
              this.cache.write({
                  result: result.data,
                  dataId: 'ROOT_QUERY',
                  query: document,
                  variables: variables,
              });
          }
      };
      DataStore.prototype.markSubscriptionResult = function (result, document, variables) {
          if (!graphQLResultHasError(result)) {
              this.cache.write({
                  result: result.data,
                  dataId: 'ROOT_SUBSCRIPTION',
                  query: document,
                  variables: variables,
              });
          }
      };
      DataStore.prototype.markMutationInit = function (mutation) {
          var _this = this;
          if (mutation.optimisticResponse) {
              var optimistic_1;
              if (typeof mutation.optimisticResponse === 'function') {
                  optimistic_1 = mutation.optimisticResponse(mutation.variables);
              }
              else {
                  optimistic_1 = mutation.optimisticResponse;
              }
              this.cache.recordOptimisticTransaction(function (c) {
                  var orig = _this.cache;
                  _this.cache = c;
                  try {
                      _this.markMutationResult({
                          mutationId: mutation.mutationId,
                          result: { data: optimistic_1 },
                          document: mutation.document,
                          variables: mutation.variables,
                          updateQueries: mutation.updateQueries,
                          update: mutation.update,
                      });
                  }
                  finally {
                      _this.cache = orig;
                  }
              }, mutation.mutationId);
          }
      };
      DataStore.prototype.markMutationResult = function (mutation) {
          var _this = this;
          if (!graphQLResultHasError(mutation.result)) {
              var cacheWrites_1 = [{
                      result: mutation.result.data,
                      dataId: 'ROOT_MUTATION',
                      query: mutation.document,
                      variables: mutation.variables,
                  }];
              var updateQueries_1 = mutation.updateQueries;
              if (updateQueries_1) {
                  Object.keys(updateQueries_1).forEach(function (id) {
                      var _a = updateQueries_1[id], query = _a.query, updater = _a.updater;
                      var _b = _this.cache.diff({
                          query: query.document,
                          variables: query.variables,
                          returnPartialData: true,
                          optimistic: false,
                      }), currentQueryResult = _b.result, complete = _b.complete;
                      if (complete) {
                          var nextQueryResult = tryFunctionOrLogError(function () {
                              return updater(currentQueryResult, {
                                  mutationResult: mutation.result,
                                  queryName: getOperationName(query.document) || undefined,
                                  queryVariables: query.variables,
                              });
                          });
                          if (nextQueryResult) {
                              cacheWrites_1.push({
                                  result: nextQueryResult,
                                  dataId: 'ROOT_QUERY',
                                  query: query.document,
                                  variables: query.variables,
                              });
                          }
                      }
                  });
              }
              this.cache.performTransaction(function (c) {
                  cacheWrites_1.forEach(function (write) { return c.write(write); });
                  var update = mutation.update;
                  if (update) {
                      tryFunctionOrLogError(function () { return update(c, mutation.result); });
                  }
              });
          }
      };
      DataStore.prototype.markMutationComplete = function (_a) {
          var mutationId = _a.mutationId, optimisticResponse = _a.optimisticResponse;
          if (optimisticResponse) {
              this.cache.removeOptimistic(mutationId);
          }
      };
      DataStore.prototype.markUpdateQueryResult = function (document, variables, newResult) {
          this.cache.write({
              result: newResult,
              dataId: 'ROOT_QUERY',
              variables: variables,
              query: document,
          });
      };
      DataStore.prototype.reset = function () {
          return this.cache.reset();
      };
      return DataStore;
  }());
  
  var version = "2.6.10";
  
  var hasSuggestedDevtools = false;
  var ApolloClient = (function () {
      function ApolloClient(options) {
          var _this = this;
          this.defaultOptions = {};
          this.resetStoreCallbacks = [];
          this.clearStoreCallbacks = [];
          var cache = options.cache, _a = options.ssrMode, ssrMode = _a === void 0 ? false : _a, _b = options.ssrForceFetchDelay, ssrForceFetchDelay = _b === void 0 ? 0 : _b, connectToDevTools = options.connectToDevTools, _c = options.queryDeduplication, queryDeduplication = _c === void 0 ? true : _c, defaultOptions = options.defaultOptions, _d = options.assumeImmutableResults, assumeImmutableResults = _d === void 0 ? false : _d, resolvers = options.resolvers, typeDefs = options.typeDefs, fragmentMatcher = options.fragmentMatcher, clientAwarenessName = options.name, clientAwarenessVersion = options.version;
          var link = options.link;
          if (!link && resolvers) {
              link = ApolloLink.empty();
          }
          if (!link || !cache) {
              throw process.env.NODE_ENV === "production" ? new InvariantError(4) : new InvariantError("In order to initialize Apollo Client, you must specify 'link' and 'cache' properties in the options object.\n" +
                  "These options are part of the upgrade requirements when migrating from Apollo Client 1.x to Apollo Client 2.x.\n" +
                  "For more information, please visit: https://www.apollographql.com/docs/tutorial/client.html#apollo-client-setup");
          }
          this.link = link;
          this.cache = cache;
          this.store = new DataStore(cache);
          this.disableNetworkFetches = ssrMode || ssrForceFetchDelay > 0;
          this.queryDeduplication = queryDeduplication;
          this.defaultOptions = defaultOptions || {};
          this.typeDefs = typeDefs;
          if (ssrForceFetchDelay) {
              setTimeout(function () { return (_this.disableNetworkFetches = false); }, ssrForceFetchDelay);
          }
          this.watchQuery = this.watchQuery.bind(this);
          this.query = this.query.bind(this);
          this.mutate = this.mutate.bind(this);
          this.resetStore = this.resetStore.bind(this);
          this.reFetchObservableQueries = this.reFetchObservableQueries.bind(this);
          var defaultConnectToDevTools = process.env.NODE_ENV !== 'production' &&
              typeof window !== 'undefined' &&
              !window.__APOLLO_CLIENT__;
          if (typeof connectToDevTools === 'undefined'
              ? defaultConnectToDevTools
              : connectToDevTools && typeof window !== 'undefined') {
              window.__APOLLO_CLIENT__ = this;
          }
          if (!hasSuggestedDevtools && process.env.NODE_ENV !== 'production') {
              hasSuggestedDevtools = true;
              if (typeof window !== 'undefined' &&
                  window.document &&
                  window.top === window.self) {
                  if (typeof window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
                      if (window.navigator &&
                          window.navigator.userAgent &&
                          window.navigator.userAgent.indexOf('Chrome') > -1) {
                          console.debug('Download the Apollo DevTools ' +
                              'for a better development experience: ' +
                              'https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm');
                      }
                  }
              }
          }
          this.version = version;
          this.localState = new LocalState({
              cache: cache,
              client: this,
              resolvers: resolvers,
              fragmentMatcher: fragmentMatcher,
          });
          this.queryManager = new QueryManager({
              link: this.link,
              store: this.store,
              queryDeduplication: queryDeduplication,
              ssrMode: ssrMode,
              clientAwareness: {
                  name: clientAwarenessName,
                  version: clientAwarenessVersion,
              },
              localState: this.localState,
              assumeImmutableResults: assumeImmutableResults,
              onBroadcast: function () {
                  if (_this.devToolsHookCb) {
                      _this.devToolsHookCb({
                          action: {},
                          state: {
                              queries: _this.queryManager.queryStore.getStore(),
                              mutations: _this.queryManager.mutationStore.getStore(),
                          },
                          dataWithOptimisticResults: _this.cache.extract(true),
                      });
                  }
              },
          });
      }
      ApolloClient.prototype.stop = function () {
          this.queryManager.stop();
      };
      ApolloClient.prototype.watchQuery = function (options) {
          if (this.defaultOptions.watchQuery) {
              options = __assign(__assign({}, this.defaultOptions.watchQuery), options);
          }
          if (this.disableNetworkFetches &&
              (options.fetchPolicy === 'network-only' ||
                  options.fetchPolicy === 'cache-and-network')) {
              options = __assign(__assign({}, options), { fetchPolicy: 'cache-first' });
          }
          return this.queryManager.watchQuery(options);
      };
      ApolloClient.prototype.query = function (options) {
          if (this.defaultOptions.query) {
              options = __assign(__assign({}, this.defaultOptions.query), options);
          }
          process.env.NODE_ENV === "production" ? invariant(options.fetchPolicy !== 'cache-and-network', 5) : invariant(options.fetchPolicy !== 'cache-and-network', 'The cache-and-network fetchPolicy does not work with client.query, because ' +
              'client.query can only return a single result. Please use client.watchQuery ' +
              'to receive multiple results from the cache and the network, or consider ' +
              'using a different fetchPolicy, such as cache-first or network-only.');
          if (this.disableNetworkFetches && options.fetchPolicy === 'network-only') {
              options = __assign(__assign({}, options), { fetchPolicy: 'cache-first' });
          }
          return this.queryManager.query(options);
      };
      ApolloClient.prototype.mutate = function (options) {
          if (this.defaultOptions.mutate) {
              options = __assign(__assign({}, this.defaultOptions.mutate), options);
          }
          return this.queryManager.mutate(options);
      };
      ApolloClient.prototype.subscribe = function (options) {
          return this.queryManager.startGraphQLSubscription(options);
      };
      ApolloClient.prototype.readQuery = function (options, optimistic) {
          if (optimistic === void 0) { optimistic = false; }
          return this.cache.readQuery(options, optimistic);
      };
      ApolloClient.prototype.readFragment = function (options, optimistic) {
          if (optimistic === void 0) { optimistic = false; }
          return this.cache.readFragment(options, optimistic);
      };
      ApolloClient.prototype.writeQuery = function (options) {
          var result = this.cache.writeQuery(options);
          this.queryManager.broadcastQueries();
          return result;
      };
      ApolloClient.prototype.writeFragment = function (options) {
          var result = this.cache.writeFragment(options);
          this.queryManager.broadcastQueries();
          return result;
      };
      ApolloClient.prototype.writeData = function (options) {
          var result = this.cache.writeData(options);
          this.queryManager.broadcastQueries();
          return result;
      };
      ApolloClient.prototype.__actionHookForDevTools = function (cb) {
          this.devToolsHookCb = cb;
      };
      ApolloClient.prototype.__requestRaw = function (payload) {
          return execute(this.link, payload);
      };
      ApolloClient.prototype.initQueryManager = function () {
          process.env.NODE_ENV === "production" || invariant.warn('Calling the initQueryManager method is no longer necessary, ' +
              'and it will be removed from ApolloClient in version 3.0.');
          return this.queryManager;
      };
      ApolloClient.prototype.resetStore = function () {
          var _this = this;
          return Promise.resolve()
              .then(function () { return _this.queryManager.clearStore(); })
              .then(function () { return Promise.all(_this.resetStoreCallbacks.map(function (fn) { return fn(); })); })
              .then(function () { return _this.reFetchObservableQueries(); });
      };
      ApolloClient.prototype.clearStore = function () {
          var _this = this;
          return Promise.resolve()
              .then(function () { return _this.queryManager.clearStore(); })
              .then(function () { return Promise.all(_this.clearStoreCallbacks.map(function (fn) { return fn(); })); });
      };
      ApolloClient.prototype.onResetStore = function (cb) {
          var _this = this;
          this.resetStoreCallbacks.push(cb);
          return function () {
              _this.resetStoreCallbacks = _this.resetStoreCallbacks.filter(function (c) { return c !== cb; });
          };
      };
      ApolloClient.prototype.onClearStore = function (cb) {
          var _this = this;
          this.clearStoreCallbacks.push(cb);
          return function () {
              _this.clearStoreCallbacks = _this.clearStoreCallbacks.filter(function (c) { return c !== cb; });
          };
      };
      ApolloClient.prototype.reFetchObservableQueries = function (includeStandby) {
          return this.queryManager.reFetchObservableQueries(includeStandby);
      };
      ApolloClient.prototype.extract = function (optimistic) {
          return this.cache.extract(optimistic);
      };
      ApolloClient.prototype.restore = function (serializedState) {
          return this.cache.restore(serializedState);
      };
      ApolloClient.prototype.addResolvers = function (resolvers) {
          this.localState.addResolvers(resolvers);
      };
      ApolloClient.prototype.setResolvers = function (resolvers) {
          this.localState.setResolvers(resolvers);
      };
      ApolloClient.prototype.getResolvers = function () {
          return this.localState.getResolvers();
      };
      ApolloClient.prototype.setLocalStateFragmentMatcher = function (fragmentMatcher) {
          this.localState.setFragmentMatcher(fragmentMatcher);
      };
      return ApolloClient;
  }());
  
  function queryFromPojo(obj) {
      var op = {
          kind: 'OperationDefinition',
          operation: 'query',
          name: {
              kind: 'Name',
              value: 'GeneratedClientQuery',
          },
          selectionSet: selectionSetFromObj(obj),
      };
      var out = {
          kind: 'Document',
          definitions: [op],
      };
      return out;
  }
  function fragmentFromPojo(obj, typename) {
      var frag = {
          kind: 'FragmentDefinition',
          typeCondition: {
              kind: 'NamedType',
              name: {
                  kind: 'Name',
                  value: typename || '__FakeType',
              },
          },
          name: {
              kind: 'Name',
              value: 'GeneratedClientQuery',
          },
          selectionSet: selectionSetFromObj(obj),
      };
      var out = {
          kind: 'Document',
          definitions: [frag],
      };
      return out;
  }
  function selectionSetFromObj(obj) {
      if (typeof obj === 'number' ||
          typeof obj === 'boolean' ||
          typeof obj === 'string' ||
          typeof obj === 'undefined' ||
          obj === null) {
          return null;
      }
      if (Array.isArray(obj)) {
          return selectionSetFromObj(obj[0]);
      }
      var selections = [];
      Object.keys(obj).forEach(function (key) {
          var nestedSelSet = selectionSetFromObj(obj[key]);
          var field = {
              kind: 'Field',
              name: {
                  kind: 'Name',
                  value: key,
              },
              selectionSet: nestedSelSet || undefined,
          };
          selections.push(field);
      });
      var selectionSet = {
          kind: 'SelectionSet',
          selections: selections,
      };
      return selectionSet;
  }
  var justTypenameQuery = {
      kind: 'Document',
      definitions: [
          {
              kind: 'OperationDefinition',
              operation: 'query',
              name: null,
              variableDefinitions: null,
              directives: [],
              selectionSet: {
                  kind: 'SelectionSet',
                  selections: [
                      {
                          kind: 'Field',
                          alias: null,
                          name: {
                              kind: 'Name',
                              value: '__typename',
                          },
                          arguments: [],
                          directives: [],
                          selectionSet: null,
                      },
                  ],
              },
          },
      ],
  };
  
  var ApolloCache = (function () {
      function ApolloCache() {
      }
      ApolloCache.prototype.transformDocument = function (document) {
          return document;
      };
      ApolloCache.prototype.transformForLink = function (document) {
          return document;
      };
      ApolloCache.prototype.readQuery = function (options, optimistic) {
          if (optimistic === void 0) { optimistic = false; }
          return this.read({
              query: options.query,
              variables: options.variables,
              optimistic: optimistic,
          });
      };
      ApolloCache.prototype.readFragment = function (options, optimistic) {
          if (optimistic === void 0) { optimistic = false; }
          return this.read({
              query: getFragmentQueryDocument(options.fragment, options.fragmentName),
              variables: options.variables,
              rootId: options.id,
              optimistic: optimistic,
          });
      };
      ApolloCache.prototype.writeQuery = function (options) {
          this.write({
              dataId: 'ROOT_QUERY',
              result: options.data,
              query: options.query,
              variables: options.variables,
          });
      };
      ApolloCache.prototype.writeFragment = function (options) {
          this.write({
              dataId: options.id,
              result: options.data,
              variables: options.variables,
              query: getFragmentQueryDocument(options.fragment, options.fragmentName),
          });
      };
      ApolloCache.prototype.writeData = function (_a) {
          var id = _a.id, data = _a.data;
          if (typeof id !== 'undefined') {
              var typenameResult = null;
              try {
                  typenameResult = this.read({
                      rootId: id,
                      optimistic: false,
                      query: justTypenameQuery,
                  });
              }
              catch (e) {
              }
              var __typename = (typenameResult && typenameResult.__typename) || '__ClientData';
              var dataToWrite = Object.assign({ __typename: __typename }, data);
              this.writeFragment({
                  id: id,
                  fragment: fragmentFromPojo(dataToWrite, __typename),
                  data: dataToWrite,
              });
          }
          else {
              this.writeQuery({ query: queryFromPojo(data), data: data });
          }
      };
      return ApolloCache;
  }());
  
  // This currentContext variable will only be used if the makeSlotClass
  // function is called, which happens only if this is the first copy of the
  // @wry/context package to be imported.
  var currentContext = null;
  // This unique internal object is used to denote the absence of a value
  // for a given Slot, and is never exposed to outside code.
  var MISSING_VALUE = {};
  var idCounter = 1;
  // Although we can't do anything about the cost of duplicated code from
  // accidentally bundling multiple copies of the @wry/context package, we can
  // avoid creating the Slot class more than once using makeSlotClass.
  var makeSlotClass = function () { return /** @class */ (function () {
      function Slot() {
          // If you have a Slot object, you can find out its slot.id, but you cannot
          // guess the slot.id of a Slot you don't have access to, thanks to the
          // randomized suffix.
          this.id = [
              "slot",
              idCounter++,
              Date.now(),
              Math.random().toString(36).slice(2),
          ].join(":");
      }
      Slot.prototype.hasValue = function () {
          for (var context_1 = currentContext; context_1; context_1 = context_1.parent) {
              // We use the Slot object iself as a key to its value, which means the
              // value cannot be obtained without a reference to the Slot object.
              if (this.id in context_1.slots) {
                  var value = context_1.slots[this.id];
                  if (value === MISSING_VALUE)
                      break;
                  if (context_1 !== currentContext) {
                      // Cache the value in currentContext.slots so the next lookup will
                      // be faster. This caching is safe because the tree of contexts and
                      // the values of the slots are logically immutable.
                      currentContext.slots[this.id] = value;
                  }
                  return true;
              }
          }
          if (currentContext) {
              // If a value was not found for this Slot, it's never going to be found
              // no matter how many times we look it up, so we might as well cache
              // the absence of the value, too.
              currentContext.slots[this.id] = MISSING_VALUE;
          }
          return false;
      };
      Slot.prototype.getValue = function () {
          if (this.hasValue()) {
              return currentContext.slots[this.id];
          }
      };
      Slot.prototype.withValue = function (value, callback, 
      // Given the prevalence of arrow functions, specifying arguments is likely
      // to be much more common than specifying `this`, hence this ordering:
      args, thisArg) {
          var _a;
          var slots = (_a = {
                  __proto__: null
              },
              _a[this.id] = value,
              _a);
          var parent = currentContext;
          currentContext = { parent: parent, slots: slots };
          try {
              // Function.prototype.apply allows the arguments array argument to be
              // omitted or undefined, so args! is fine here.
              return callback.apply(thisArg, args);
          }
          finally {
              currentContext = parent;
          }
      };
      // Capture the current context and wrap a callback function so that it
      // reestablishes the captured context when called.
      Slot.bind = function (callback) {
          var context = currentContext;
          return function () {
              var saved = currentContext;
              try {
                  currentContext = context;
                  return callback.apply(this, arguments);
              }
              finally {
                  currentContext = saved;
              }
          };
      };
      // Immediately run a callback function without any captured context.
      Slot.noContext = function (callback, 
      // Given the prevalence of arrow functions, specifying arguments is likely
      // to be much more common than specifying `this`, hence this ordering:
      args, thisArg) {
          if (currentContext) {
              var saved = currentContext;
              try {
                  currentContext = null;
                  // Function.prototype.apply allows the arguments array argument to be
                  // omitted or undefined, so args! is fine here.
                  return callback.apply(thisArg, args);
              }
              finally {
                  currentContext = saved;
              }
          }
          else {
              return callback.apply(thisArg, args);
          }
      };
      return Slot;
  }()); };
  // We store a single global implementation of the Slot class as a permanent
  // non-enumerable symbol property of the Array constructor. This obfuscation
  // does nothing to prevent access to the Slot class, but at least it ensures
  // the implementation (i.e. currentContext) cannot be tampered with, and all
  // copies of the @wry/context package (hopefully just one) will share the
  // same Slot implementation. Since the first copy of the @wry/context package
  // to be imported wins, this technique imposes a very high cost for any
  // future breaking changes to the Slot class.
  var globalKey = "@wry/context:Slot";
  var host = Array;
  var Slot = host[globalKey] || function () {
      var Slot = makeSlotClass();
      try {
          Object.defineProperty(host, globalKey, {
              value: host[globalKey] = Slot,
              enumerable: false,
              writable: false,
              configurable: false,
          });
      }
      finally {
          return Slot;
      }
  }();
  
  Slot.bind; Slot.noContext;
  
  function defaultDispose() { }
  var Cache = /** @class */ (function () {
      function Cache(max, dispose) {
          if (max === void 0) { max = Infinity; }
          if (dispose === void 0) { dispose = defaultDispose; }
          this.max = max;
          this.dispose = dispose;
          this.map = new Map();
          this.newest = null;
          this.oldest = null;
      }
      Cache.prototype.has = function (key) {
          return this.map.has(key);
      };
      Cache.prototype.get = function (key) {
          var entry = this.getEntry(key);
          return entry && entry.value;
      };
      Cache.prototype.getEntry = function (key) {
          var entry = this.map.get(key);
          if (entry && entry !== this.newest) {
              var older = entry.older, newer = entry.newer;
              if (newer) {
                  newer.older = older;
              }
              if (older) {
                  older.newer = newer;
              }
              entry.older = this.newest;
              entry.older.newer = entry;
              entry.newer = null;
              this.newest = entry;
              if (entry === this.oldest) {
                  this.oldest = newer;
              }
          }
          return entry;
      };
      Cache.prototype.set = function (key, value) {
          var entry = this.getEntry(key);
          if (entry) {
              return entry.value = value;
          }
          entry = {
              key: key,
              value: value,
              newer: null,
              older: this.newest
          };
          if (this.newest) {
              this.newest.newer = entry;
          }
          this.newest = entry;
          this.oldest = this.oldest || entry;
          this.map.set(key, entry);
          return entry.value;
      };
      Cache.prototype.clean = function () {
          while (this.oldest && this.map.size > this.max) {
              this.delete(this.oldest.key);
          }
      };
      Cache.prototype.delete = function (key) {
          var entry = this.map.get(key);
          if (entry) {
              if (entry === this.newest) {
                  this.newest = entry.older;
              }
              if (entry === this.oldest) {
                  this.oldest = entry.newer;
              }
              if (entry.newer) {
                  entry.newer.older = entry.older;
              }
              if (entry.older) {
                  entry.older.newer = entry.newer;
              }
              this.map.delete(key);
              this.dispose(entry.value, key);
              return true;
          }
          return false;
      };
      return Cache;
  }());
  
  var parentEntrySlot = new Slot();
  
  var reusableEmptyArray = [];
  var emptySetPool = [];
  var POOL_TARGET_SIZE = 100;
  // Since this package might be used browsers, we should avoid using the
  // Node built-in assert module.
  function assert(condition, optionalMessage) {
      if (!condition) {
          throw new Error(optionalMessage || "assertion failure");
      }
  }
  function valueIs(a, b) {
      var len = a.length;
      return (
      // Unknown values are not equal to each other.
      len > 0 &&
          // Both values must be ordinary (or both exceptional) to be equal.
          len === b.length &&
          // The underlying value or exception must be the same.
          a[len - 1] === b[len - 1]);
  }
  function valueGet(value) {
      switch (value.length) {
          case 0: throw new Error("unknown value");
          case 1: return value[0];
          case 2: throw value[1];
      }
  }
  function valueCopy(value) {
      return value.slice(0);
  }
  var Entry = /** @class */ (function () {
      function Entry(fn, args) {
          this.fn = fn;
          this.args = args;
          this.parents = new Set();
          this.childValues = new Map();
          // When this Entry has children that are dirty, this property becomes
          // a Set containing other Entry objects, borrowed from emptySetPool.
          // When the set becomes empty, it gets recycled back to emptySetPool.
          this.dirtyChildren = null;
          this.dirty = true;
          this.recomputing = false;
          this.value = [];
          ++Entry.count;
      }
      // This is the most important method of the Entry API, because it
      // determines whether the cached this.value can be returned immediately,
      // or must be recomputed. The overall performance of the caching system
      // depends on the truth of the following observations: (1) this.dirty is
      // usually false, (2) this.dirtyChildren is usually null/empty, and thus
      // (3) valueGet(this.value) is usually returned without recomputation.
      Entry.prototype.recompute = function () {
          assert(!this.recomputing, "already recomputing");
          if (!rememberParent(this) && maybeReportOrphan(this)) {
              // The recipient of the entry.reportOrphan callback decided to dispose
              // of this orphan entry by calling entry.dispose(), so we don't need to
              // (and should not) proceed with the recomputation.
              return void 0;
          }
          return mightBeDirty(this)
              ? reallyRecompute(this)
              : valueGet(this.value);
      };
      Entry.prototype.setDirty = function () {
          if (this.dirty)
              return;
          this.dirty = true;
          this.value.length = 0;
          reportDirty(this);
          // We can go ahead and unsubscribe here, since any further dirty
          // notifications we receive will be redundant, and unsubscribing may
          // free up some resources, e.g. file watchers.
          maybeUnsubscribe(this);
      };
      Entry.prototype.dispose = function () {
          var _this = this;
          forgetChildren(this).forEach(maybeReportOrphan);
          maybeUnsubscribe(this);
          // Because this entry has been kicked out of the cache (in index.js),
          // we've lost the ability to find out if/when this entry becomes dirty,
          // whether that happens through a subscription, because of a direct call
          // to entry.setDirty(), or because one of its children becomes dirty.
          // Because of this loss of future information, we have to assume the
          // worst (that this entry might have become dirty very soon), so we must
          // immediately mark this entry's parents as dirty. Normally we could
          // just call entry.setDirty() rather than calling parent.setDirty() for
          // each parent, but that would leave this entry in parent.childValues
          // and parent.dirtyChildren, which would prevent the child from being
          // truly forgotten.
          this.parents.forEach(function (parent) {
              parent.setDirty();
              forgetChild(parent, _this);
          });
      };
      Entry.count = 0;
      return Entry;
  }());
  function rememberParent(child) {
      var parent = parentEntrySlot.getValue();
      if (parent) {
          child.parents.add(parent);
          if (!parent.childValues.has(child)) {
              parent.childValues.set(child, []);
          }
          if (mightBeDirty(child)) {
              reportDirtyChild(parent, child);
          }
          else {
              reportCleanChild(parent, child);
          }
          return parent;
      }
  }
  function reallyRecompute(entry) {
      // Since this recomputation is likely to re-remember some of this
      // entry's children, we forget our children here but do not call
      // maybeReportOrphan until after the recomputation finishes.
      var originalChildren = forgetChildren(entry);
      // Set entry as the parent entry while calling recomputeNewValue(entry).
      parentEntrySlot.withValue(entry, recomputeNewValue, [entry]);
      if (maybeSubscribe(entry)) {
          // If we successfully recomputed entry.value and did not fail to
          // (re)subscribe, then this Entry is no longer explicitly dirty.
          setClean(entry);
      }
      // Now that we've had a chance to re-remember any children that were
      // involved in the recomputation, we can safely report any orphan
      // children that remain.
      originalChildren.forEach(maybeReportOrphan);
      return valueGet(entry.value);
  }
  function recomputeNewValue(entry) {
      entry.recomputing = true;
      // Set entry.value as unknown.
      entry.value.length = 0;
      try {
          // If entry.fn succeeds, entry.value will become a normal Value.
          entry.value[0] = entry.fn.apply(null, entry.args);
      }
      catch (e) {
          // If entry.fn throws, entry.value will become exceptional.
          entry.value[1] = e;
      }
      // Either way, this line is always reached.
      entry.recomputing = false;
  }
  function mightBeDirty(entry) {
      return entry.dirty || !!(entry.dirtyChildren && entry.dirtyChildren.size);
  }
  function setClean(entry) {
      entry.dirty = false;
      if (mightBeDirty(entry)) {
          // This Entry may still have dirty children, in which case we can't
          // let our parents know we're clean just yet.
          return;
      }
      reportClean(entry);
  }
  function reportDirty(child) {
      child.parents.forEach(function (parent) { return reportDirtyChild(parent, child); });
  }
  function reportClean(child) {
      child.parents.forEach(function (parent) { return reportCleanChild(parent, child); });
  }
  // Let a parent Entry know that one of its children may be dirty.
  function reportDirtyChild(parent, child) {
      // Must have called rememberParent(child) before calling
      // reportDirtyChild(parent, child).
      assert(parent.childValues.has(child));
      assert(mightBeDirty(child));
      if (!parent.dirtyChildren) {
          parent.dirtyChildren = emptySetPool.pop() || new Set;
      }
      else if (parent.dirtyChildren.has(child)) {
          // If we already know this child is dirty, then we must have already
          // informed our own parents that we are dirty, so we can terminate
          // the recursion early.
          return;
      }
      parent.dirtyChildren.add(child);
      reportDirty(parent);
  }
  // Let a parent Entry know that one of its children is no longer dirty.
  function reportCleanChild(parent, child) {
      // Must have called rememberChild(child) before calling
      // reportCleanChild(parent, child).
      assert(parent.childValues.has(child));
      assert(!mightBeDirty(child));
      var childValue = parent.childValues.get(child);
      if (childValue.length === 0) {
          parent.childValues.set(child, valueCopy(child.value));
      }
      else if (!valueIs(childValue, child.value)) {
          parent.setDirty();
      }
      removeDirtyChild(parent, child);
      if (mightBeDirty(parent)) {
          return;
      }
      reportClean(parent);
  }
  function removeDirtyChild(parent, child) {
      var dc = parent.dirtyChildren;
      if (dc) {
          dc.delete(child);
          if (dc.size === 0) {
              if (emptySetPool.length < POOL_TARGET_SIZE) {
                  emptySetPool.push(dc);
              }
              parent.dirtyChildren = null;
          }
      }
  }
  // If the given entry has a reportOrphan method, and no remaining parents,
  // call entry.reportOrphan and return true iff it returns true. The
  // reportOrphan function should return true to indicate entry.dispose()
  // has been called, and the entry has been removed from any other caches
  // (see index.js for the only current example).
  function maybeReportOrphan(entry) {
      return entry.parents.size === 0 &&
          typeof entry.reportOrphan === "function" &&
          entry.reportOrphan() === true;
  }
  // Removes all children from this entry and returns an array of the
  // removed children.
  function forgetChildren(parent) {
      var children = reusableEmptyArray;
      if (parent.childValues.size > 0) {
          children = [];
          parent.childValues.forEach(function (_value, child) {
              forgetChild(parent, child);
              children.push(child);
          });
      }
      // After we forget all our children, this.dirtyChildren must be empty
      // and therefore must have been reset to null.
      assert(parent.dirtyChildren === null);
      return children;
  }
  function forgetChild(parent, child) {
      child.parents.delete(parent);
      parent.childValues.delete(child);
      removeDirtyChild(parent, child);
  }
  function maybeSubscribe(entry) {
      if (typeof entry.subscribe === "function") {
          try {
              maybeUnsubscribe(entry); // Prevent double subscriptions.
              entry.unsubscribe = entry.subscribe.apply(null, entry.args);
          }
          catch (e) {
              // If this Entry has a subscribe function and it threw an exception
              // (or an unsubscribe function it previously returned now throws),
              // return false to indicate that we were not able to subscribe (or
              // unsubscribe), and this Entry should remain dirty.
              entry.setDirty();
              return false;
          }
      }
      // Returning true indicates either that there was no entry.subscribe
      // function or that it succeeded.
      return true;
  }
  function maybeUnsubscribe(entry) {
      var unsubscribe = entry.unsubscribe;
      if (typeof unsubscribe === "function") {
          entry.unsubscribe = void 0;
          unsubscribe();
      }
  }
  
  // A trie data structure that holds object keys weakly, yet can also hold
  // non-object keys, unlike the native `WeakMap`.
  var KeyTrie = /** @class */ (function () {
      function KeyTrie(weakness) {
          this.weakness = weakness;
      }
      KeyTrie.prototype.lookup = function () {
          var array = [];
          for (var _i = 0; _i < arguments.length; _i++) {
              array[_i] = arguments[_i];
          }
          return this.lookupArray(array);
      };
      KeyTrie.prototype.lookupArray = function (array) {
          var node = this;
          array.forEach(function (key) { return node = node.getChildTrie(key); });
          return node.data || (node.data = Object.create(null));
      };
      KeyTrie.prototype.getChildTrie = function (key) {
          var map = this.weakness && isObjRef(key)
              ? this.weak || (this.weak = new WeakMap())
              : this.strong || (this.strong = new Map());
          var child = map.get(key);
          if (!child)
              map.set(key, child = new KeyTrie(this.weakness));
          return child;
      };
      return KeyTrie;
  }());
  function isObjRef(value) {
      switch (typeof value) {
          case "object":
              if (value === null)
                  break;
          // Fall through to return true...
          case "function":
              return true;
      }
      return false;
  }
  
  // The defaultMakeCacheKey function is remarkably powerful, because it gives
  // a unique object for any shallow-identical list of arguments. If you need
  // to implement a custom makeCacheKey function, you may find it helpful to
  // delegate the final work to defaultMakeCacheKey, which is why we export it
  // here. However, you may want to avoid defaultMakeCacheKey if your runtime
  // does not support WeakMap, or you have the ability to return a string key.
  // In those cases, just write your own custom makeCacheKey functions.
  var keyTrie = new KeyTrie(typeof WeakMap === "function");
  function defaultMakeCacheKey() {
      var args = [];
      for (var _i = 0; _i < arguments.length; _i++) {
          args[_i] = arguments[_i];
      }
      return keyTrie.lookupArray(args);
  }
  var caches = new Set();
  function wrap$1(originalFunction, options) {
      if (options === void 0) { options = Object.create(null); }
      var cache = new Cache(options.max || Math.pow(2, 16), function (entry) { return entry.dispose(); });
      var disposable = !!options.disposable;
      var makeCacheKey = options.makeCacheKey || defaultMakeCacheKey;
      function optimistic() {
          if (disposable && !parentEntrySlot.hasValue()) {
              // If there's no current parent computation, and this wrapped
              // function is disposable (meaning we don't care about entry.value,
              // just dependency tracking), then we can short-cut everything else
              // in this function, because entry.recompute() is going to recycle
              // the entry object without recomputing anything, anyway.
              return void 0;
          }
          var key = makeCacheKey.apply(null, arguments);
          if (key === void 0) {
              return originalFunction.apply(null, arguments);
          }
          var args = Array.prototype.slice.call(arguments);
          var entry = cache.get(key);
          if (entry) {
              entry.args = args;
          }
          else {
              entry = new Entry(originalFunction, args);
              cache.set(key, entry);
              entry.subscribe = options.subscribe;
              if (disposable) {
                  entry.reportOrphan = function () { return cache.delete(key); };
              }
          }
          var value = entry.recompute();
          // Move this entry to the front of the least-recently used queue,
          // since we just finished computing its value.
          cache.set(key, entry);
          caches.add(cache);
          // Clean up any excess entries in the cache, but only if there is no
          // active parent entry, meaning we're not in the middle of a larger
          // computation that might be flummoxed by the cleaning.
          if (!parentEntrySlot.hasValue()) {
              caches.forEach(function (cache) { return cache.clean(); });
              caches.clear();
          }
          // If options.disposable is truthy, the caller of wrap is telling us
          // they don't care about the result of entry.recompute(), so we should
          // avoid returning the value, so it won't be accidentally used.
          return disposable ? void 0 : value;
      }
      optimistic.dirty = function () {
          var key = makeCacheKey.apply(null, arguments);
          var child = key !== void 0 && cache.get(key);
          if (child) {
              child.setDirty();
          }
      };
      return optimistic;
  }
  
  var haveWarned = false;
  function shouldWarn() {
      var answer = !haveWarned;
      if (!isTest()) {
          haveWarned = true;
      }
      return answer;
  }
  var HeuristicFragmentMatcher = (function () {
      function HeuristicFragmentMatcher() {
      }
      HeuristicFragmentMatcher.prototype.ensureReady = function () {
          return Promise.resolve();
      };
      HeuristicFragmentMatcher.prototype.canBypassInit = function () {
          return true;
      };
      HeuristicFragmentMatcher.prototype.match = function (idValue, typeCondition, context) {
          var obj = context.store.get(idValue.id);
          var isRootQuery = idValue.id === 'ROOT_QUERY';
          if (!obj) {
              return isRootQuery;
          }
          var _a = obj.__typename, __typename = _a === void 0 ? isRootQuery && 'Query' : _a;
          if (!__typename) {
              if (shouldWarn()) {
                  process.env.NODE_ENV === "production" || invariant.warn("You're using fragments in your queries, but either don't have the addTypename:\n  true option set in Apollo Client, or you are trying to write a fragment to the store without the __typename.\n   Please turn on the addTypename option and include __typename when writing fragments so that Apollo Client\n   can accurately match fragments.");
                  process.env.NODE_ENV === "production" || invariant.warn('Could not find __typename on Fragment ', typeCondition, obj);
                  process.env.NODE_ENV === "production" || invariant.warn("DEPRECATION WARNING: using fragments without __typename is unsupported behavior " +
                      "and will be removed in future versions of Apollo client. You should fix this and set addTypename to true now.");
              }
              return 'heuristic';
          }
          if (__typename === typeCondition) {
              return true;
          }
          if (shouldWarn()) {
              process.env.NODE_ENV === "production" || invariant.error('You are using the simple (heuristic) fragment matcher, but your ' +
                  'queries contain union or interface types. Apollo Client will not be ' +
                  'able to accurately map fragments. To make this error go away, use ' +
                  'the `IntrospectionFragmentMatcher` as described in the docs: ' +
                  'https://www.apollographql.com/docs/react/advanced/fragments.html#fragment-matcher');
          }
          return 'heuristic';
      };
      return HeuristicFragmentMatcher;
  }());
  
  var hasOwn = Object.prototype.hasOwnProperty;
  var DepTrackingCache = (function () {
      function DepTrackingCache(data) {
          var _this = this;
          if (data === void 0) { data = Object.create(null); }
          this.data = data;
          this.depend = wrap$1(function (dataId) { return _this.data[dataId]; }, {
              disposable: true,
              makeCacheKey: function (dataId) {
                  return dataId;
              },
          });
      }
      DepTrackingCache.prototype.toObject = function () {
          return this.data;
      };
      DepTrackingCache.prototype.get = function (dataId) {
          this.depend(dataId);
          return this.data[dataId];
      };
      DepTrackingCache.prototype.set = function (dataId, value) {
          var oldValue = this.data[dataId];
          if (value !== oldValue) {
              this.data[dataId] = value;
              this.depend.dirty(dataId);
          }
      };
      DepTrackingCache.prototype.delete = function (dataId) {
          if (hasOwn.call(this.data, dataId)) {
              delete this.data[dataId];
              this.depend.dirty(dataId);
          }
      };
      DepTrackingCache.prototype.clear = function () {
          this.replace(null);
      };
      DepTrackingCache.prototype.replace = function (newData) {
          var _this = this;
          if (newData) {
              Object.keys(newData).forEach(function (dataId) {
                  _this.set(dataId, newData[dataId]);
              });
              Object.keys(this.data).forEach(function (dataId) {
                  if (!hasOwn.call(newData, dataId)) {
                      _this.delete(dataId);
                  }
              });
          }
          else {
              Object.keys(this.data).forEach(function (dataId) {
                  _this.delete(dataId);
              });
          }
      };
      return DepTrackingCache;
  }());
  function defaultNormalizedCacheFactory(seed) {
      return new DepTrackingCache(seed);
  }
  
  var StoreReader = (function () {
      function StoreReader(_a) {
          var _this = this;
          var _b = _a === void 0 ? {} : _a, _c = _b.cacheKeyRoot, cacheKeyRoot = _c === void 0 ? new KeyTrie(canUseWeakMap) : _c, _d = _b.freezeResults, freezeResults = _d === void 0 ? false : _d;
          var _e = this, executeStoreQuery = _e.executeStoreQuery, executeSelectionSet = _e.executeSelectionSet, executeSubSelectedArray = _e.executeSubSelectedArray;
          this.freezeResults = freezeResults;
          this.executeStoreQuery = wrap$1(function (options) {
              return executeStoreQuery.call(_this, options);
          }, {
              makeCacheKey: function (_a) {
                  var query = _a.query, rootValue = _a.rootValue, contextValue = _a.contextValue, variableValues = _a.variableValues, fragmentMatcher = _a.fragmentMatcher;
                  if (contextValue.store instanceof DepTrackingCache) {
                      return cacheKeyRoot.lookup(contextValue.store, query, fragmentMatcher, JSON.stringify(variableValues), rootValue.id);
                  }
              }
          });
          this.executeSelectionSet = wrap$1(function (options) {
              return executeSelectionSet.call(_this, options);
          }, {
              makeCacheKey: function (_a) {
                  var selectionSet = _a.selectionSet, rootValue = _a.rootValue, execContext = _a.execContext;
                  if (execContext.contextValue.store instanceof DepTrackingCache) {
                      return cacheKeyRoot.lookup(execContext.contextValue.store, selectionSet, execContext.fragmentMatcher, JSON.stringify(execContext.variableValues), rootValue.id);
                  }
              }
          });
          this.executeSubSelectedArray = wrap$1(function (options) {
              return executeSubSelectedArray.call(_this, options);
          }, {
              makeCacheKey: function (_a) {
                  var field = _a.field, array = _a.array, execContext = _a.execContext;
                  if (execContext.contextValue.store instanceof DepTrackingCache) {
                      return cacheKeyRoot.lookup(execContext.contextValue.store, field, array, JSON.stringify(execContext.variableValues));
                  }
              }
          });
      }
      StoreReader.prototype.readQueryFromStore = function (options) {
          return this.diffQueryAgainstStore(__assign(__assign({}, options), { returnPartialData: false })).result;
      };
      StoreReader.prototype.diffQueryAgainstStore = function (_a) {
          var store = _a.store, query = _a.query, variables = _a.variables, previousResult = _a.previousResult, _b = _a.returnPartialData, returnPartialData = _b === void 0 ? true : _b, _c = _a.rootId, rootId = _c === void 0 ? 'ROOT_QUERY' : _c, fragmentMatcherFunction = _a.fragmentMatcherFunction, config = _a.config;
          var queryDefinition = getQueryDefinition(query);
          variables = assign({}, getDefaultValues(queryDefinition), variables);
          var context = {
              store: store,
              dataIdFromObject: config && config.dataIdFromObject,
              cacheRedirects: (config && config.cacheRedirects) || {},
          };
          var execResult = this.executeStoreQuery({
              query: query,
              rootValue: {
                  type: 'id',
                  id: rootId,
                  generated: true,
                  typename: 'Query',
              },
              contextValue: context,
              variableValues: variables,
              fragmentMatcher: fragmentMatcherFunction,
          });
          var hasMissingFields = execResult.missing && execResult.missing.length > 0;
          if (hasMissingFields && !returnPartialData) {
              execResult.missing.forEach(function (info) {
                  if (info.tolerable)
                      return;
                  throw process.env.NODE_ENV === "production" ? new InvariantError(8) : new InvariantError("Can't find field " + info.fieldName + " on object " + JSON.stringify(info.object, null, 2) + ".");
              });
          }
          if (previousResult) {
              if (equal(previousResult, execResult.result)) {
                  execResult.result = previousResult;
              }
          }
          return {
              result: execResult.result,
              complete: !hasMissingFields,
          };
      };
      StoreReader.prototype.executeStoreQuery = function (_a) {
          var query = _a.query, rootValue = _a.rootValue, contextValue = _a.contextValue, variableValues = _a.variableValues, _b = _a.fragmentMatcher, fragmentMatcher = _b === void 0 ? defaultFragmentMatcher : _b;
          var mainDefinition = getMainDefinition(query);
          var fragments = getFragmentDefinitions(query);
          var fragmentMap = createFragmentMap(fragments);
          var execContext = {
              query: query,
              fragmentMap: fragmentMap,
              contextValue: contextValue,
              variableValues: variableValues,
              fragmentMatcher: fragmentMatcher,
          };
          return this.executeSelectionSet({
              selectionSet: mainDefinition.selectionSet,
              rootValue: rootValue,
              execContext: execContext,
          });
      };
      StoreReader.prototype.executeSelectionSet = function (_a) {
          var _this = this;
          var selectionSet = _a.selectionSet, rootValue = _a.rootValue, execContext = _a.execContext;
          var fragmentMap = execContext.fragmentMap, contextValue = execContext.contextValue, variables = execContext.variableValues;
          var finalResult = { result: null };
          var objectsToMerge = [];
          var object = contextValue.store.get(rootValue.id);
          var typename = (object && object.__typename) ||
              (rootValue.id === 'ROOT_QUERY' && 'Query') ||
              void 0;
          function handleMissing(result) {
              var _a;
              if (result.missing) {
                  finalResult.missing = finalResult.missing || [];
                  (_a = finalResult.missing).push.apply(_a, result.missing);
              }
              return result.result;
          }
          selectionSet.selections.forEach(function (selection) {
              var _a;
              if (!shouldInclude(selection, variables)) {
                  return;
              }
              if (isField(selection)) {
                  var fieldResult = handleMissing(_this.executeField(object, typename, selection, execContext));
                  if (typeof fieldResult !== 'undefined') {
                      objectsToMerge.push((_a = {},
                          _a[resultKeyNameFromField(selection)] = fieldResult,
                          _a));
                  }
              }
              else {
                  var fragment = void 0;
                  if (isInlineFragment(selection)) {
                      fragment = selection;
                  }
                  else {
                      fragment = fragmentMap[selection.name.value];
                      if (!fragment) {
                          throw process.env.NODE_ENV === "production" ? new InvariantError(9) : new InvariantError("No fragment named " + selection.name.value);
                      }
                  }
                  var typeCondition = fragment.typeCondition && fragment.typeCondition.name.value;
                  var match = !typeCondition ||
                      execContext.fragmentMatcher(rootValue, typeCondition, contextValue);
                  if (match) {
                      var fragmentExecResult = _this.executeSelectionSet({
                          selectionSet: fragment.selectionSet,
                          rootValue: rootValue,
                          execContext: execContext,
                      });
                      if (match === 'heuristic' && fragmentExecResult.missing) {
                          fragmentExecResult = __assign(__assign({}, fragmentExecResult), { missing: fragmentExecResult.missing.map(function (info) {
                                  return __assign(__assign({}, info), { tolerable: true });
                              }) });
                      }
                      objectsToMerge.push(handleMissing(fragmentExecResult));
                  }
              }
          });
          finalResult.result = mergeDeepArray(objectsToMerge);
          if (this.freezeResults && process.env.NODE_ENV !== 'production') {
              Object.freeze(finalResult.result);
          }
          return finalResult;
      };
      StoreReader.prototype.executeField = function (object, typename, field, execContext) {
          var variables = execContext.variableValues, contextValue = execContext.contextValue;
          var fieldName = field.name.value;
          var args = argumentsObjectFromField(field, variables);
          var info = {
              resultKey: resultKeyNameFromField(field),
              directives: getDirectiveInfoFromField(field, variables),
          };
          var readStoreResult = readStoreResolver(object, typename, fieldName, args, contextValue, info);
          if (Array.isArray(readStoreResult.result)) {
              return this.combineExecResults(readStoreResult, this.executeSubSelectedArray({
                  field: field,
                  array: readStoreResult.result,
                  execContext: execContext,
              }));
          }
          if (!field.selectionSet) {
              assertSelectionSetForIdValue(field, readStoreResult.result);
              if (this.freezeResults && process.env.NODE_ENV !== 'production') {
                  maybeDeepFreeze(readStoreResult);
              }
              return readStoreResult;
          }
          if (readStoreResult.result == null) {
              return readStoreResult;
          }
          return this.combineExecResults(readStoreResult, this.executeSelectionSet({
              selectionSet: field.selectionSet,
              rootValue: readStoreResult.result,
              execContext: execContext,
          }));
      };
      StoreReader.prototype.combineExecResults = function () {
          var execResults = [];
          for (var _i = 0; _i < arguments.length; _i++) {
              execResults[_i] = arguments[_i];
          }
          var missing;
          execResults.forEach(function (execResult) {
              if (execResult.missing) {
                  missing = missing || [];
                  missing.push.apply(missing, execResult.missing);
              }
          });
          return {
              result: execResults.pop().result,
              missing: missing,
          };
      };
      StoreReader.prototype.executeSubSelectedArray = function (_a) {
          var _this = this;
          var field = _a.field, array = _a.array, execContext = _a.execContext;
          var missing;
          function handleMissing(childResult) {
              if (childResult.missing) {
                  missing = missing || [];
                  missing.push.apply(missing, childResult.missing);
              }
              return childResult.result;
          }
          array = array.map(function (item) {
              if (item === null) {
                  return null;
              }
              if (Array.isArray(item)) {
                  return handleMissing(_this.executeSubSelectedArray({
                      field: field,
                      array: item,
                      execContext: execContext,
                  }));
              }
              if (field.selectionSet) {
                  return handleMissing(_this.executeSelectionSet({
                      selectionSet: field.selectionSet,
                      rootValue: item,
                      execContext: execContext,
                  }));
              }
              assertSelectionSetForIdValue(field, item);
              return item;
          });
          if (this.freezeResults && process.env.NODE_ENV !== 'production') {
              Object.freeze(array);
          }
          return { result: array, missing: missing };
      };
      return StoreReader;
  }());
  function assertSelectionSetForIdValue(field, value) {
      if (!field.selectionSet && isIdValue(value)) {
          throw process.env.NODE_ENV === "production" ? new InvariantError(10) : new InvariantError("Missing selection set for object of type " + value.typename + " returned for query field " + field.name.value);
      }
  }
  function defaultFragmentMatcher() {
      return true;
  }
  function readStoreResolver(object, typename, fieldName, args, context, _a) {
      _a.resultKey; var directives = _a.directives;
      var storeKeyName = fieldName;
      if (args || directives) {
          storeKeyName = getStoreKeyName(storeKeyName, args, directives);
      }
      var fieldValue = void 0;
      if (object) {
          fieldValue = object[storeKeyName];
          if (typeof fieldValue === 'undefined' &&
              context.cacheRedirects &&
              typeof typename === 'string') {
              var type = context.cacheRedirects[typename];
              if (type) {
                  var resolver = type[fieldName];
                  if (resolver) {
                      fieldValue = resolver(object, args, {
                          getCacheKey: function (storeObj) {
                              var id = context.dataIdFromObject(storeObj);
                              return id && toIdValue({
                                  id: id,
                                  typename: storeObj.__typename,
                              });
                          },
                      });
                  }
              }
          }
      }
      if (typeof fieldValue === 'undefined') {
          return {
              result: fieldValue,
              missing: [{
                      object: object,
                      fieldName: storeKeyName,
                      tolerable: false,
                  }],
          };
      }
      if (isJsonValue(fieldValue)) {
          fieldValue = fieldValue.json;
      }
      return {
          result: fieldValue,
      };
  }
  
  var ObjectCache = (function () {
      function ObjectCache(data) {
          if (data === void 0) { data = Object.create(null); }
          this.data = data;
      }
      ObjectCache.prototype.toObject = function () {
          return this.data;
      };
      ObjectCache.prototype.get = function (dataId) {
          return this.data[dataId];
      };
      ObjectCache.prototype.set = function (dataId, value) {
          this.data[dataId] = value;
      };
      ObjectCache.prototype.delete = function (dataId) {
          this.data[dataId] = void 0;
      };
      ObjectCache.prototype.clear = function () {
          this.data = Object.create(null);
      };
      ObjectCache.prototype.replace = function (newData) {
          this.data = newData || Object.create(null);
      };
      return ObjectCache;
  }());
  
  var WriteError = (function (_super) {
      __extends(WriteError, _super);
      function WriteError() {
          var _this = _super !== null && _super.apply(this, arguments) || this;
          _this.type = 'WriteError';
          return _this;
      }
      return WriteError;
  }(Error));
  function enhanceErrorWithDocument(error, document) {
      var enhancedError = new WriteError("Error writing result to store for query:\n " + JSON.stringify(document));
      enhancedError.message += '\n' + error.message;
      enhancedError.stack = error.stack;
      return enhancedError;
  }
  var StoreWriter = (function () {
      function StoreWriter() {
      }
      StoreWriter.prototype.writeQueryToStore = function (_a) {
          var query = _a.query, result = _a.result, _b = _a.store, store = _b === void 0 ? defaultNormalizedCacheFactory() : _b, variables = _a.variables, dataIdFromObject = _a.dataIdFromObject, fragmentMatcherFunction = _a.fragmentMatcherFunction;
          return this.writeResultToStore({
              dataId: 'ROOT_QUERY',
              result: result,
              document: query,
              store: store,
              variables: variables,
              dataIdFromObject: dataIdFromObject,
              fragmentMatcherFunction: fragmentMatcherFunction,
          });
      };
      StoreWriter.prototype.writeResultToStore = function (_a) {
          var dataId = _a.dataId, result = _a.result, document = _a.document, _b = _a.store, store = _b === void 0 ? defaultNormalizedCacheFactory() : _b, variables = _a.variables, dataIdFromObject = _a.dataIdFromObject, fragmentMatcherFunction = _a.fragmentMatcherFunction;
          var operationDefinition = getOperationDefinition(document);
          try {
              return this.writeSelectionSetToStore({
                  result: result,
                  dataId: dataId,
                  selectionSet: operationDefinition.selectionSet,
                  context: {
                      store: store,
                      processedData: {},
                      variables: assign({}, getDefaultValues(operationDefinition), variables),
                      dataIdFromObject: dataIdFromObject,
                      fragmentMap: createFragmentMap(getFragmentDefinitions(document)),
                      fragmentMatcherFunction: fragmentMatcherFunction,
                  },
              });
          }
          catch (e) {
              throw enhanceErrorWithDocument(e, document);
          }
      };
      StoreWriter.prototype.writeSelectionSetToStore = function (_a) {
          var _this = this;
          var result = _a.result, dataId = _a.dataId, selectionSet = _a.selectionSet, context = _a.context;
          var variables = context.variables, store = context.store, fragmentMap = context.fragmentMap;
          selectionSet.selections.forEach(function (selection) {
              var _a;
              if (!shouldInclude(selection, variables)) {
                  return;
              }
              if (isField(selection)) {
                  var resultFieldKey = resultKeyNameFromField(selection);
                  var value = result[resultFieldKey];
                  if (typeof value !== 'undefined') {
                      _this.writeFieldToStore({
                          dataId: dataId,
                          value: value,
                          field: selection,
                          context: context,
                      });
                  }
                  else {
                      var isDefered = false;
                      var isClient = false;
                      if (selection.directives && selection.directives.length) {
                          isDefered = selection.directives.some(function (directive) { return directive.name && directive.name.value === 'defer'; });
                          isClient = selection.directives.some(function (directive) { return directive.name && directive.name.value === 'client'; });
                      }
                      if (!isDefered && !isClient && context.fragmentMatcherFunction) {
                          process.env.NODE_ENV === "production" || invariant.warn("Missing field " + resultFieldKey + " in " + JSON.stringify(result, null, 2).substring(0, 100));
                      }
                  }
              }
              else {
                  var fragment = void 0;
                  if (isInlineFragment(selection)) {
                      fragment = selection;
                  }
                  else {
                      fragment = (fragmentMap || {})[selection.name.value];
                      process.env.NODE_ENV === "production" ? invariant(fragment, 3) : invariant(fragment, "No fragment named " + selection.name.value + ".");
                  }
                  var matches = true;
                  if (context.fragmentMatcherFunction && fragment.typeCondition) {
                      var id = dataId || 'self';
                      var idValue = toIdValue({ id: id, typename: undefined });
                      var fakeContext = {
                          store: new ObjectCache((_a = {}, _a[id] = result, _a)),
                          cacheRedirects: {},
                      };
                      var match = context.fragmentMatcherFunction(idValue, fragment.typeCondition.name.value, fakeContext);
                      if (!isProduction() && match === 'heuristic') {
                          process.env.NODE_ENV === "production" || invariant.error('WARNING: heuristic fragment matching going on!');
                      }
                      matches = !!match;
                  }
                  if (matches) {
                      _this.writeSelectionSetToStore({
                          result: result,
                          selectionSet: fragment.selectionSet,
                          dataId: dataId,
                          context: context,
                      });
                  }
              }
          });
          return store;
      };
      StoreWriter.prototype.writeFieldToStore = function (_a) {
          var _b;
          var field = _a.field, value = _a.value, dataId = _a.dataId, context = _a.context;
          var variables = context.variables, dataIdFromObject = context.dataIdFromObject, store = context.store;
          var storeValue;
          var storeObject;
          var storeFieldName = storeKeyNameFromField(field, variables);
          if (!field.selectionSet || value === null) {
              storeValue =
                  value != null && typeof value === 'object'
                      ?
                          { type: 'json', json: value }
                      :
                          value;
          }
          else if (Array.isArray(value)) {
              var generatedId = dataId + "." + storeFieldName;
              storeValue = this.processArrayValue(value, generatedId, field.selectionSet, context);
          }
          else {
              var valueDataId = dataId + "." + storeFieldName;
              var generated = true;
              if (!isGeneratedId(valueDataId)) {
                  valueDataId = '$' + valueDataId;
              }
              if (dataIdFromObject) {
                  var semanticId = dataIdFromObject(value);
                  process.env.NODE_ENV === "production" ? invariant(!semanticId || !isGeneratedId(semanticId), 4) : invariant(!semanticId || !isGeneratedId(semanticId), 'IDs returned by dataIdFromObject cannot begin with the "$" character.');
                  if (semanticId ||
                      (typeof semanticId === 'number' && semanticId === 0)) {
                      valueDataId = semanticId;
                      generated = false;
                  }
              }
              if (!isDataProcessed(valueDataId, field, context.processedData)) {
                  this.writeSelectionSetToStore({
                      dataId: valueDataId,
                      result: value,
                      selectionSet: field.selectionSet,
                      context: context,
                  });
              }
              var typename = value.__typename;
              storeValue = toIdValue({ id: valueDataId, typename: typename }, generated);
              storeObject = store.get(dataId);
              var escapedId = storeObject && storeObject[storeFieldName];
              if (escapedId !== storeValue && isIdValue(escapedId)) {
                  var hadTypename = escapedId.typename !== undefined;
                  var hasTypename = typename !== undefined;
                  var typenameChanged = hadTypename && hasTypename && escapedId.typename !== typename;
                  process.env.NODE_ENV === "production" ? invariant(!generated || escapedId.generated || typenameChanged, 5) : invariant(!generated || escapedId.generated || typenameChanged, "Store error: the application attempted to write an object with no provided id but the store already contains an id of " + escapedId.id + " for this object. The selectionSet that was trying to be written is:\n" + JSON.stringify(field));
                  process.env.NODE_ENV === "production" ? invariant(!hadTypename || hasTypename, 6) : invariant(!hadTypename || hasTypename, "Store error: the application attempted to write an object with no provided typename but the store already contains an object with typename of " + escapedId.typename + " for the object of id " + escapedId.id + ". The selectionSet that was trying to be written is:\n" + JSON.stringify(field));
                  if (escapedId.generated) {
                      if (typenameChanged) {
                          if (!generated) {
                              store.delete(escapedId.id);
                          }
                      }
                      else {
                          mergeWithGenerated(escapedId.id, storeValue.id, store);
                      }
                  }
              }
          }
          storeObject = store.get(dataId);
          if (!storeObject || !equal(storeValue, storeObject[storeFieldName])) {
              store.set(dataId, __assign(__assign({}, storeObject), (_b = {}, _b[storeFieldName] = storeValue, _b)));
          }
      };
      StoreWriter.prototype.processArrayValue = function (value, generatedId, selectionSet, context) {
          var _this = this;
          return value.map(function (item, index) {
              if (item === null) {
                  return null;
              }
              var itemDataId = generatedId + "." + index;
              if (Array.isArray(item)) {
                  return _this.processArrayValue(item, itemDataId, selectionSet, context);
              }
              var generated = true;
              if (context.dataIdFromObject) {
                  var semanticId = context.dataIdFromObject(item);
                  if (semanticId) {
                      itemDataId = semanticId;
                      generated = false;
                  }
              }
              if (!isDataProcessed(itemDataId, selectionSet, context.processedData)) {
                  _this.writeSelectionSetToStore({
                      dataId: itemDataId,
                      result: item,
                      selectionSet: selectionSet,
                      context: context,
                  });
              }
              return toIdValue({ id: itemDataId, typename: item.__typename }, generated);
          });
      };
      return StoreWriter;
  }());
  function isGeneratedId(id) {
      return id[0] === '$';
  }
  function mergeWithGenerated(generatedKey, realKey, cache) {
      if (generatedKey === realKey) {
          return false;
      }
      var generated = cache.get(generatedKey);
      var real = cache.get(realKey);
      var madeChanges = false;
      Object.keys(generated).forEach(function (key) {
          var value = generated[key];
          var realValue = real[key];
          if (isIdValue(value) &&
              isGeneratedId(value.id) &&
              isIdValue(realValue) &&
              !equal(value, realValue) &&
              mergeWithGenerated(value.id, realValue.id, cache)) {
              madeChanges = true;
          }
      });
      cache.delete(generatedKey);
      var newRealValue = __assign(__assign({}, generated), real);
      if (equal(newRealValue, real)) {
          return madeChanges;
      }
      cache.set(realKey, newRealValue);
      return true;
  }
  function isDataProcessed(dataId, field, processedData) {
      if (!processedData) {
          return false;
      }
      if (processedData[dataId]) {
          if (processedData[dataId].indexOf(field) >= 0) {
              return true;
          }
          else {
              processedData[dataId].push(field);
          }
      }
      else {
          processedData[dataId] = [field];
      }
      return false;
  }
  
  var defaultConfig = {
      fragmentMatcher: new HeuristicFragmentMatcher(),
      dataIdFromObject: defaultDataIdFromObject,
      addTypename: true,
      resultCaching: true,
      freezeResults: false,
  };
  function defaultDataIdFromObject(result) {
      if (result.__typename) {
          if (result.id !== undefined) {
              return result.__typename + ":" + result.id;
          }
          if (result._id !== undefined) {
              return result.__typename + ":" + result._id;
          }
      }
      return null;
  }
  var hasOwn$1 = Object.prototype.hasOwnProperty;
  var OptimisticCacheLayer = (function (_super) {
      __extends(OptimisticCacheLayer, _super);
      function OptimisticCacheLayer(optimisticId, parent, transaction) {
          var _this = _super.call(this, Object.create(null)) || this;
          _this.optimisticId = optimisticId;
          _this.parent = parent;
          _this.transaction = transaction;
          return _this;
      }
      OptimisticCacheLayer.prototype.toObject = function () {
          return __assign(__assign({}, this.parent.toObject()), this.data);
      };
      OptimisticCacheLayer.prototype.get = function (dataId) {
          return hasOwn$1.call(this.data, dataId)
              ? this.data[dataId]
              : this.parent.get(dataId);
      };
      return OptimisticCacheLayer;
  }(ObjectCache));
  var InMemoryCache = (function (_super) {
      __extends(InMemoryCache, _super);
      function InMemoryCache(config) {
          if (config === void 0) { config = {}; }
          var _this = _super.call(this) || this;
          _this.watches = new Set();
          _this.typenameDocumentCache = new Map();
          _this.cacheKeyRoot = new KeyTrie(canUseWeakMap);
          _this.silenceBroadcast = false;
          _this.config = __assign(__assign({}, defaultConfig), config);
          if (_this.config.customResolvers) {
              process.env.NODE_ENV === "production" || invariant.warn('customResolvers have been renamed to cacheRedirects. Please update your config as we will be deprecating customResolvers in the next major version.');
              _this.config.cacheRedirects = _this.config.customResolvers;
          }
          if (_this.config.cacheResolvers) {
              process.env.NODE_ENV === "production" || invariant.warn('cacheResolvers have been renamed to cacheRedirects. Please update your config as we will be deprecating cacheResolvers in the next major version.');
              _this.config.cacheRedirects = _this.config.cacheResolvers;
          }
          _this.addTypename = !!_this.config.addTypename;
          _this.data = _this.config.resultCaching
              ? new DepTrackingCache()
              : new ObjectCache();
          _this.optimisticData = _this.data;
          _this.storeWriter = new StoreWriter();
          _this.storeReader = new StoreReader({
              cacheKeyRoot: _this.cacheKeyRoot,
              freezeResults: config.freezeResults,
          });
          var cache = _this;
          var maybeBroadcastWatch = cache.maybeBroadcastWatch;
          _this.maybeBroadcastWatch = wrap$1(function (c) {
              return maybeBroadcastWatch.call(_this, c);
          }, {
              makeCacheKey: function (c) {
                  if (c.optimistic) {
                      return;
                  }
                  if (c.previousResult) {
                      return;
                  }
                  if (cache.data instanceof DepTrackingCache) {
                      return cache.cacheKeyRoot.lookup(c.query, JSON.stringify(c.variables));
                  }
              }
          });
          return _this;
      }
      InMemoryCache.prototype.restore = function (data) {
          if (data)
              this.data.replace(data);
          return this;
      };
      InMemoryCache.prototype.extract = function (optimistic) {
          if (optimistic === void 0) { optimistic = false; }
          return (optimistic ? this.optimisticData : this.data).toObject();
      };
      InMemoryCache.prototype.read = function (options) {
          if (typeof options.rootId === 'string' &&
              typeof this.data.get(options.rootId) === 'undefined') {
              return null;
          }
          var fragmentMatcher = this.config.fragmentMatcher;
          var fragmentMatcherFunction = fragmentMatcher && fragmentMatcher.match;
          return this.storeReader.readQueryFromStore({
              store: options.optimistic ? this.optimisticData : this.data,
              query: this.transformDocument(options.query),
              variables: options.variables,
              rootId: options.rootId,
              fragmentMatcherFunction: fragmentMatcherFunction,
              previousResult: options.previousResult,
              config: this.config,
          }) || null;
      };
      InMemoryCache.prototype.write = function (write) {
          var fragmentMatcher = this.config.fragmentMatcher;
          var fragmentMatcherFunction = fragmentMatcher && fragmentMatcher.match;
          this.storeWriter.writeResultToStore({
              dataId: write.dataId,
              result: write.result,
              variables: write.variables,
              document: this.transformDocument(write.query),
              store: this.data,
              dataIdFromObject: this.config.dataIdFromObject,
              fragmentMatcherFunction: fragmentMatcherFunction,
          });
          this.broadcastWatches();
      };
      InMemoryCache.prototype.diff = function (query) {
          var fragmentMatcher = this.config.fragmentMatcher;
          var fragmentMatcherFunction = fragmentMatcher && fragmentMatcher.match;
          return this.storeReader.diffQueryAgainstStore({
              store: query.optimistic ? this.optimisticData : this.data,
              query: this.transformDocument(query.query),
              variables: query.variables,
              returnPartialData: query.returnPartialData,
              previousResult: query.previousResult,
              fragmentMatcherFunction: fragmentMatcherFunction,
              config: this.config,
          });
      };
      InMemoryCache.prototype.watch = function (watch) {
          var _this = this;
          this.watches.add(watch);
          return function () {
              _this.watches.delete(watch);
          };
      };
      InMemoryCache.prototype.evict = function (query) {
          throw process.env.NODE_ENV === "production" ? new InvariantError(7) : new InvariantError("eviction is not implemented on InMemory Cache");
      };
      InMemoryCache.prototype.reset = function () {
          this.data.clear();
          this.broadcastWatches();
          return Promise.resolve();
      };
      InMemoryCache.prototype.removeOptimistic = function (idToRemove) {
          var toReapply = [];
          var removedCount = 0;
          var layer = this.optimisticData;
          while (layer instanceof OptimisticCacheLayer) {
              if (layer.optimisticId === idToRemove) {
                  ++removedCount;
              }
              else {
                  toReapply.push(layer);
              }
              layer = layer.parent;
          }
          if (removedCount > 0) {
              this.optimisticData = layer;
              while (toReapply.length > 0) {
                  var layer_1 = toReapply.pop();
                  this.performTransaction(layer_1.transaction, layer_1.optimisticId);
              }
              this.broadcastWatches();
          }
      };
      InMemoryCache.prototype.performTransaction = function (transaction, optimisticId) {
          var _a = this, data = _a.data, silenceBroadcast = _a.silenceBroadcast;
          this.silenceBroadcast = true;
          if (typeof optimisticId === 'string') {
              this.data = this.optimisticData = new OptimisticCacheLayer(optimisticId, this.optimisticData, transaction);
          }
          try {
              transaction(this);
          }
          finally {
              this.silenceBroadcast = silenceBroadcast;
              this.data = data;
          }
          this.broadcastWatches();
      };
      InMemoryCache.prototype.recordOptimisticTransaction = function (transaction, id) {
          return this.performTransaction(transaction, id);
      };
      InMemoryCache.prototype.transformDocument = function (document) {
          if (this.addTypename) {
              var result = this.typenameDocumentCache.get(document);
              if (!result) {
                  result = addTypenameToDocument(document);
                  this.typenameDocumentCache.set(document, result);
                  this.typenameDocumentCache.set(result, result);
              }
              return result;
          }
          return document;
      };
      InMemoryCache.prototype.broadcastWatches = function () {
          var _this = this;
          if (!this.silenceBroadcast) {
              this.watches.forEach(function (c) { return _this.maybeBroadcastWatch(c); });
          }
      };
      InMemoryCache.prototype.maybeBroadcastWatch = function (c) {
          c.callback(this.diff({
              query: c.query,
              variables: c.variables,
              previousResult: c.previousResult && c.previousResult(),
              optimistic: c.optimistic,
          }));
      };
      return InMemoryCache;
  }(ApolloCache));
  
  var defaultHttpOptions = {
      includeQuery: true,
      includeExtensions: false,
  };
  var defaultHeaders = {
      accept: '*/*',
      'content-type': 'application/json',
  };
  var defaultOptions = {
      method: 'POST',
  };
  var fallbackHttpConfig = {
      http: defaultHttpOptions,
      headers: defaultHeaders,
      options: defaultOptions,
  };
  var throwServerError = function (response, result, message) {
      var error = new Error(message);
      error.name = 'ServerError';
      error.response = response;
      error.statusCode = response.status;
      error.result = result;
      throw error;
  };
  var parseAndCheckHttpResponse = function (operations) { return function (response) {
      return (response
          .text()
          .then(function (bodyText) {
          try {
              return JSON.parse(bodyText);
          }
          catch (err) {
              var parseError = err;
              parseError.name = 'ServerParseError';
              parseError.response = response;
              parseError.statusCode = response.status;
              parseError.bodyText = bodyText;
              return Promise.reject(parseError);
          }
      })
          .then(function (result) {
          if (response.status >= 300) {
              throwServerError(response, result, "Response not successful: Received status code " + response.status);
          }
          if (!Array.isArray(result) &&
              !result.hasOwnProperty('data') &&
              !result.hasOwnProperty('errors')) {
              throwServerError(response, result, "Server response was missing for query '" + (Array.isArray(operations)
                  ? operations.map(function (op) { return op.operationName; })
                  : operations.operationName) + "'.");
          }
          return result;
      }));
  }; };
  var checkFetcher = function (fetcher) {
      if (!fetcher && typeof fetch === 'undefined') {
          var library = 'unfetch';
          if (typeof window === 'undefined')
              library = 'node-fetch';
          throw process.env.NODE_ENV === "production" ? new InvariantError(1) : new InvariantError("\nfetch is not found globally and no fetcher passed, to fix pass a fetch for\nyour environment like https://www.npmjs.com/package/" + library + ".\n\nFor example:\nimport fetch from '" + library + "';\nimport { createHttpLink } from 'apollo-link-http';\n\nconst link = createHttpLink({ uri: '/graphql', fetch: fetch });");
      }
  };
  var createSignalIfSupported = function () {
      if (typeof AbortController === 'undefined')
          return { controller: false, signal: false };
      var controller = new AbortController();
      var signal = controller.signal;
      return { controller: controller, signal: signal };
  };
  var selectHttpOptionsAndBody = function (operation, fallbackConfig) {
      var configs = [];
      for (var _i = 2; _i < arguments.length; _i++) {
          configs[_i - 2] = arguments[_i];
      }
      var options = __assign({}, fallbackConfig.options, { headers: fallbackConfig.headers, credentials: fallbackConfig.credentials });
      var http = fallbackConfig.http;
      configs.forEach(function (config) {
          options = __assign({}, options, config.options, { headers: __assign({}, options.headers, config.headers) });
          if (config.credentials)
              options.credentials = config.credentials;
          http = __assign({}, http, config.http);
      });
      var operationName = operation.operationName, extensions = operation.extensions, variables = operation.variables, query = operation.query;
      var body = { operationName: operationName, variables: variables };
      if (http.includeExtensions)
          body.extensions = extensions;
      if (http.includeQuery)
          body.query = print(query);
      return {
          options: options,
          body: body,
      };
  };
  var serializeFetchParameter = function (p, label) {
      var serialized;
      try {
          serialized = JSON.stringify(p);
      }
      catch (e) {
          var parseError = process.env.NODE_ENV === "production" ? new InvariantError(2) : new InvariantError("Network request failed. " + label + " is not serializable: " + e.message);
          parseError.parseError = e;
          throw parseError;
      }
      return serialized;
  };
  var selectURI = function (operation, fallbackURI) {
      var context = operation.getContext();
      var contextURI = context.uri;
      if (contextURI) {
          return contextURI;
      }
      else if (typeof fallbackURI === 'function') {
          return fallbackURI(operation);
      }
      else {
          return fallbackURI || '/graphql';
      }
  };
  
  var createHttpLink = function (linkOptions) {
      if (linkOptions === void 0) { linkOptions = {}; }
      var _a = linkOptions.uri, uri = _a === void 0 ? '/graphql' : _a, fetcher = linkOptions.fetch, includeExtensions = linkOptions.includeExtensions, useGETForQueries = linkOptions.useGETForQueries, requestOptions = __rest(linkOptions, ["uri", "fetch", "includeExtensions", "useGETForQueries"]);
      checkFetcher(fetcher);
      if (!fetcher) {
          fetcher = fetch;
      }
      var linkConfig = {
          http: { includeExtensions: includeExtensions },
          options: requestOptions.fetchOptions,
          credentials: requestOptions.credentials,
          headers: requestOptions.headers,
      };
      return new ApolloLink(function (operation) {
          var chosenURI = selectURI(operation, uri);
          var context = operation.getContext();
          var clientAwarenessHeaders = {};
          if (context.clientAwareness) {
              var _a = context.clientAwareness, name_1 = _a.name, version = _a.version;
              if (name_1) {
                  clientAwarenessHeaders['apollographql-client-name'] = name_1;
              }
              if (version) {
                  clientAwarenessHeaders['apollographql-client-version'] = version;
              }
          }
          var contextHeaders = __assign({}, clientAwarenessHeaders, context.headers);
          var contextConfig = {
              http: context.http,
              options: context.fetchOptions,
              credentials: context.credentials,
              headers: contextHeaders,
          };
          var _b = selectHttpOptionsAndBody(operation, fallbackHttpConfig, linkConfig, contextConfig), options = _b.options, body = _b.body;
          var controller;
          if (!options.signal) {
              var _c = createSignalIfSupported(), _controller = _c.controller, signal = _c.signal;
              controller = _controller;
              if (controller)
                  options.signal = signal;
          }
          var definitionIsMutation = function (d) {
              return d.kind === 'OperationDefinition' && d.operation === 'mutation';
          };
          if (useGETForQueries &&
              !operation.query.definitions.some(definitionIsMutation)) {
              options.method = 'GET';
          }
          if (options.method === 'GET') {
              var _d = rewriteURIForGET(chosenURI, body), newURI = _d.newURI, parseError = _d.parseError;
              if (parseError) {
                  return fromError(parseError);
              }
              chosenURI = newURI;
          }
          else {
              try {
                  options.body = serializeFetchParameter(body, 'Payload');
              }
              catch (parseError) {
                  return fromError(parseError);
              }
          }
          return new Observable(function (observer) {
              fetcher(chosenURI, options)
                  .then(function (response) {
                  operation.setContext({ response: response });
                  return response;
              })
                  .then(parseAndCheckHttpResponse(operation))
                  .then(function (result) {
                  observer.next(result);
                  observer.complete();
                  return result;
              })
                  .catch(function (err) {
                  if (err.name === 'AbortError')
                      return;
                  if (err.result && err.result.errors && err.result.data) {
                      observer.next(err.result);
                  }
                  observer.error(err);
              });
              return function () {
                  if (controller)
                      controller.abort();
              };
          });
      });
  };
  function rewriteURIForGET(chosenURI, body) {
      var queryParams = [];
      var addQueryParam = function (key, value) {
          queryParams.push(key + "=" + encodeURIComponent(value));
      };
      if ('query' in body) {
          addQueryParam('query', body.query);
      }
      if (body.operationName) {
          addQueryParam('operationName', body.operationName);
      }
      if (body.variables) {
          var serializedVariables = void 0;
          try {
              serializedVariables = serializeFetchParameter(body.variables, 'Variables map');
          }
          catch (parseError) {
              return { parseError: parseError };
          }
          addQueryParam('variables', serializedVariables);
      }
      if (body.extensions) {
          var serializedExtensions = void 0;
          try {
              serializedExtensions = serializeFetchParameter(body.extensions, 'Extensions map');
          }
          catch (parseError) {
              return { parseError: parseError };
          }
          addQueryParam('extensions', serializedExtensions);
      }
      var fragment = '', preFragment = chosenURI;
      var fragmentStart = chosenURI.indexOf('#');
      if (fragmentStart !== -1) {
          fragment = chosenURI.substr(fragmentStart);
          preFragment = chosenURI.substr(0, fragmentStart);
      }
      var queryParamsPrefix = preFragment.indexOf('?') === -1 ? '?' : '&';
      var newURI = preFragment + queryParamsPrefix + queryParams.join('&') + fragment;
      return { newURI: newURI };
  }
  var HttpLink = (function (_super) {
      __extends(HttpLink, _super);
      function HttpLink(opts) {
          return _super.call(this, createHttpLink(opts).request) || this;
      }
      return HttpLink;
  }(ApolloLink));
  
  (function (ConnectionMode) {
      ConnectionMode[ConnectionMode["AUTO"] = 0] = "AUTO";
      ConnectionMode[ConnectionMode["PLAIN"] = 1] = "PLAIN";
      ConnectionMode[ConnectionMode["NODES"] = 2] = "NODES";
      ConnectionMode[ConnectionMode["EDGES"] = 3] = "EDGES";
      ConnectionMode[ConnectionMode["ITEMS"] = 4] = "ITEMS";
  })(exports.ConnectionMode || (exports.ConnectionMode = {}));
  (function (ArgumentMode) {
      ArgumentMode[ArgumentMode["TYPE"] = 0] = "TYPE";
      ArgumentMode[ArgumentMode["LIST"] = 1] = "LIST";
  })(exports.ArgumentMode || (exports.ArgumentMode = {}));
  
  /**
   * This class provides methods to transform incoming data from GraphQL in to a format Vuex-ORM understands and
   * vice versa.
   */
  var Transformer = /** @class */ (function () {
      function Transformer() {
      }
      /**
       * Transforms outgoing data. Use for variables param.
       *
       * @param {Model} model Base model of the mutation/query
       * @param {Data} data Data to transform
       * @param {boolean} read Tells if this is a write or a read action. read is fetch, write is push and persist.
       * @param {Array<String>} whitelist of fields
       * @param {Map<string, Array<string>>} outgoingRecords List of record IDs that are already added to the
       *                                                     outgoing data in order to detect recursion.
       * @param {boolean} recursiveCall Tells if it's a recursive call.
       * @returns {Data}
       */
      Transformer.transformOutgoingData = function (model, data, read, whitelist, outgoingRecords, recursiveCall) {
          var _this = this;
          var context = Context.getInstance();
          var relations = model.getRelations();
          var returnValue = {};
          if (outgoingRecords === undefined)
              outgoingRecords = new Map();
          if (recursiveCall === undefined)
              recursiveCall = false;
          Object.keys(data).forEach(function (key) {
              var value = data[key];
              var isRelation = model.getRelations().has(key);
              var isRecursion = false;
              if (value instanceof Array) {
                  isRecursion = isRelation && _this.isRecursion(outgoingRecords, value[0]);
              }
              else {
                  isRecursion = isRelation && _this.isRecursion(outgoingRecords, value);
              }
              // shouldIncludeOutgoingField and the read param is tricky. In the initial call of this method
              // we want to include any relation, so we have to make sure it's false. In the recursive calls
              // it should be true when we transform the outgoing data for fetch (and false for the others)
              if (!isRecursion &&
                  _this.shouldIncludeOutgoingField(recursiveCall && read, key, value, model, whitelist)) {
                  var relatedModel = Model.getRelatedModel(relations.get(key));
                  if (value instanceof Array) {
                      // Either this is a hasMany field or a .attr() field which contains an array.
                      var arrayModel_1 = context.getModel(singularize(key), true);
                      if (arrayModel_1) {
                          _this.addRecordForRecursionDetection(outgoingRecords, value[0]);
                          returnValue[key] = value.map(function (v) {
                              return _this.transformOutgoingData(arrayModel_1 || model, v, read, undefined, outgoingRecords, true);
                          });
                      }
                      else {
                          // Simple field, not a relation
                          returnValue[key] = value;
                      }
                  }
                  else if (typeof value === "object" && value.$id !== undefined) {
                      if (!relatedModel) {
                          relatedModel = context.getModel(value.$self().entity);
                      }
                      _this.addRecordForRecursionDetection(outgoingRecords, value);
                      // Value is a record, transform that too
                      returnValue[key] = _this.transformOutgoingData(relatedModel, value, read, undefined, outgoingRecords, true);
                  }
                  else {
                      // In any other case just let the value be what ever it is
                      returnValue[key] = value;
                  }
              }
          });
          return returnValue;
      };
      /**
       * Transforms a set of incoming data to the format vuex-orm requires.
       *
       * @param {Data | Array<Data>} data
       * @param model
       * @param mutation required to transform something like `disableUserAddress` to the actual model name.
       * @param {boolean} recursiveCall
       * @returns {Data}
       */
      Transformer.transformIncomingData = function (data, model, mutation, recursiveCall) {
          var _this = this;
          if (mutation === void 0) { mutation = false; }
          if (recursiveCall === void 0) { recursiveCall = false; }
          var result = {};
          var context = Context.getInstance();
          if (!recursiveCall) {
              context.logger.group("Transforming incoming data");
              context.logger.log("Raw data:", data);
          }
          if (Array.isArray(data)) {
              result = data.map(function (d) { return _this.transformIncomingData(d, model, mutation, true); });
          }
          else {
              Object.keys(data).forEach(function (key) {
                  if (data[key] !== undefined && data[key] !== null && key in data) {
                      if (isPlainObject(data[key])) {
                          var localModel = context.getModel(key, true) || model;
                          if (data[key].nodes && context.connectionMode === exports.ConnectionMode.NODES) {
                              result[pluralize$1(key)] = _this.transformIncomingData(data[key].nodes, localModel, mutation, true);
                          }
                          else if (data[key].edges && context.connectionMode === exports.ConnectionMode.EDGES) {
                              result[pluralize$1(key)] = _this.transformIncomingData(data[key].edges, localModel, mutation, true);
                          }
                          else if (data["node"] && context.connectionMode === exports.ConnectionMode.EDGES) {
                              result = _this.transformIncomingData(data["node"], localModel, mutation, true);
                          }
                          else if (data[key].items && context.connectionMode === exports.ConnectionMode.ITEMS) {
                              result[pluralize$1(key)] = _this.transformIncomingData(data[key].items, localModel, mutation, true);
                          }
                          else {
                              var newKey = key;
                              if (mutation && !recursiveCall) {
                                  newKey = data[key].nodes ? localModel.pluralName : localModel.singularName;
                                  newKey = downcaseFirstLetter(newKey);
                              }
                              result[newKey] = _this.transformIncomingData(data[key], localModel, mutation, true);
                          }
                      }
                      else if (Model.isFieldNumber(model.fields.get(key))) {
                          result[key] = parseFloat(data[key]);
                      }
                      else if (key.endsWith("Type") && model.isTypeFieldOfPolymorphicRelation(key)) {
                          result[key] = pluralize$1(downcaseFirstLetter(data[key]));
                      }
                      else {
                          result[key] = data[key];
                      }
                  }
              });
          }
          if (!recursiveCall) {
              context.logger.log("Transformed data:", result);
              context.logger.groupEnd();
          }
          else {
              result["$isPersisted"] = true;
          }
          // Make sure this is really a plain JS object. We had some issues in testing here.
          return clone(result);
      };
      /**
       * Tells if a field should be included in the outgoing data.
       * @param {boolean} forFilter Tells whether a filter is constructed or not.
       * @param {string} fieldName Name of the field to check.
       * @param {any} value Value of the field.
       * @param {Model} model Model class which contains the field.
       * @param {Array<String>|undefined} whitelist Contains a list of fields which should always be included.
       * @returns {boolean}
       */
      Transformer.shouldIncludeOutgoingField = function (forFilter, fieldName, value, model, whitelist) {
          // Always add fields on the whitelist.
          if (whitelist && whitelist.includes(fieldName))
              return true;
          // Ignore internal fields
          if (fieldName.startsWith("$"))
              return false;
          // Ignore pivot objects
          if (fieldName === "pivot")
              return false;
          // Ignore empty fields
          if (value === null || value === undefined)
              return false;
          // Ignore fields that don't exist in the input type
          if (!this.inputTypeContainsField(model, fieldName))
              return false;
          // Include all eager save connections
          if (model.getRelations().has(fieldName)) {
              // We never add relations to filters.
              if (forFilter)
                  return false;
              var relation = model.getRelations().get(fieldName);
              var related = Model.getRelatedModel(relation);
              if (related && model.shouldEagerSaveRelation(fieldName, relation, related))
                  return true;
              // All other relations are skipped
              return false;
          }
          // Everything else is ok
          return true;
      };
      /**
       * Tells whether a field is in the input type.
       * @param {Model} model
       * @param {string} fieldName
       */
      Transformer.inputTypeContainsField = function (model, fieldName) {
          var inputTypeName = Context.getInstance().adapter.getInputTypeName(model) || model.singularName + "Input";
          var inputType = Context.getInstance().schema.getType(inputTypeName, false);
          if (inputType === null)
              throw new Error("Type " + inputType + " doesn't exist.");
          return inputType.inputFields.find(function (f) { return f.name === fieldName; }) !== undefined;
      };
      /**
       * Registers a record for recursion detection.
       * @param {Map<string, Array<string>>} records Map of IDs.
       * @param {ORMModel} record The record to register.
       */
      Transformer.addRecordForRecursionDetection = function (records, record) {
          var context = Context.getInstance();
          if (!record) {
              context.logger.warn("Trying to add invalid record", record, "to recursion detection");
              return;
          }
          if (!record.$self) {
              context.logger.warn("Seems like you're using non-model classes with plugin graphql. You shouldn't do that.");
              return;
          }
          var model = context.getModel(record.$self().entity);
          var ids = records.get(model.singularName) || [];
          ids.push(record.$id);
          records.set(model.singularName, ids);
      };
      /**
       * Detects recursions.
       * @param {Map<string, Array<string>>} records Map of IDs.
       * @param {ORMModel} record The record to check.
       * @return {boolean} true when the record is already included in the records.
       */
      Transformer.isRecursion = function (records, record) {
          if (!record)
              return false;
          if (!record.$self) {
              Context.getInstance().logger.warn("Seems like you're using non-model classes with plugin graphql. You shouldn't do that.");
              return false;
          }
          var model = Context.getInstance().getModel(record.$self().entity);
          var ids = records.get(model.singularName) || [];
          return ids.includes(record.$id);
      };
      return Transformer;
  }());
  
  var parser$1 = getCjsExportFromNamespace(parser);
  
  var parse$1 = parser$1.parse;
  
  // Strip insignificant whitespace
  // Note that this could do a lot more, such as reorder fields etc.
  function normalize(string) {
    return string.replace(/[\s,]+/g, ' ').trim();
  }
  
  // A map docString -> graphql document
  var docCache = {};
  
  // A map fragmentName -> [normalized source]
  var fragmentSourceMap = {};
  
  function cacheKeyFromLoc(loc) {
    return normalize(loc.source.body.substring(loc.start, loc.end));
  }
  
  // For testing.
  function resetCaches() {
    docCache = {};
    fragmentSourceMap = {};
  }
  
  // Take a unstripped parsed document (query/mutation or even fragment), and
  // check all fragment definitions, checking for name->source uniqueness.
  // We also want to make sure only unique fragments exist in the document.
  var printFragmentWarnings = true;
  function processFragments(ast) {
    var astFragmentMap = {};
    var definitions = [];
  
    for (var i = 0; i < ast.definitions.length; i++) {
      var fragmentDefinition = ast.definitions[i];
  
      if (fragmentDefinition.kind === 'FragmentDefinition') {
        var fragmentName = fragmentDefinition.name.value;
        var sourceKey = cacheKeyFromLoc(fragmentDefinition.loc);
  
        // We know something about this fragment
        if (fragmentSourceMap.hasOwnProperty(fragmentName) && !fragmentSourceMap[fragmentName][sourceKey]) {
  
          // this is a problem because the app developer is trying to register another fragment with
          // the same name as one previously registered. So, we tell them about it.
          if (printFragmentWarnings) {
            console.warn("Warning: fragment with name " + fragmentName + " already exists.\n"
              + "graphql-tag enforces all fragment names across your application to be unique; read more about\n"
              + "this in the docs: http://dev.apollodata.com/core/fragments.html#unique-names");
          }
  
          fragmentSourceMap[fragmentName][sourceKey] = true;
  
        } else if (!fragmentSourceMap.hasOwnProperty(fragmentName)) {
          fragmentSourceMap[fragmentName] = {};
          fragmentSourceMap[fragmentName][sourceKey] = true;
        }
  
        if (!astFragmentMap[sourceKey]) {
          astFragmentMap[sourceKey] = true;
          definitions.push(fragmentDefinition);
        }
      } else {
        definitions.push(fragmentDefinition);
      }
    }
  
    ast.definitions = definitions;
    return ast;
  }
  
  function disableFragmentWarnings() {
    printFragmentWarnings = false;
  }
  
  function stripLoc(doc, removeLocAtThisLevel) {
    var docType = Object.prototype.toString.call(doc);
  
    if (docType === '[object Array]') {
      return doc.map(function (d) {
        return stripLoc(d, removeLocAtThisLevel);
      });
    }
  
    if (docType !== '[object Object]') {
      throw new Error('Unexpected input.');
    }
  
    // We don't want to remove the root loc field so we can use it
    // for fragment substitution (see below)
    if (removeLocAtThisLevel && doc.loc) {
      delete doc.loc;
    }
  
    // https://github.com/apollographql/graphql-tag/issues/40
    if (doc.loc) {
      delete doc.loc.startToken;
      delete doc.loc.endToken;
    }
  
    var keys = Object.keys(doc);
    var key;
    var value;
    var valueType;
  
    for (key in keys) {
      if (keys.hasOwnProperty(key)) {
        value = doc[keys[key]];
        valueType = Object.prototype.toString.call(value);
  
        if (valueType === '[object Object]' || valueType === '[object Array]') {
          doc[keys[key]] = stripLoc(value, true);
        }
      }
    }
  
    return doc;
  }
  
  var experimentalFragmentVariables = false;
  function parseDocument(doc) {
    var cacheKey = normalize(doc);
  
    if (docCache[cacheKey]) {
      return docCache[cacheKey];
    }
  
    var parsed = parse$1(doc, { experimentalFragmentVariables: experimentalFragmentVariables });
    if (!parsed || parsed.kind !== 'Document') {
      throw new Error('Not a valid GraphQL document.');
    }
  
    // check that all "new" fragments inside the documents are consistent with
    // existing fragments of the same name
    parsed = processFragments(parsed);
    parsed = stripLoc(parsed, false);
    docCache[cacheKey] = parsed;
  
    return parsed;
  }
  
  function enableExperimentalFragmentVariables() {
    experimentalFragmentVariables = true;
  }
  
  function disableExperimentalFragmentVariables() {
    experimentalFragmentVariables = false;
  }
  
  // XXX This should eventually disallow arbitrary string interpolation, like Relay does
  function gql(/* arguments */) {
    var args = Array.prototype.slice.call(arguments);
  
    var literals = args[0];
  
    // We always get literals[0] and then matching post literals for each arg given
    var result = (typeof(literals) === "string") ? literals : literals[0];
  
    for (var i = 1; i < args.length; i++) {
      if (args[i] && args[i].kind && args[i].kind === 'Document') {
        result += args[i].loc.source.body;
      } else {
        result += args[i];
      }
  
      result += literals[i];
    }
  
    return parseDocument(result);
  }
  
  // Support typescript, which isn't as nice as Babel about default exports
  gql.default = gql;
  gql.resetCaches = resetCaches;
  gql.disableFragmentWarnings = disableFragmentWarnings;
  gql.enableExperimentalFragmentVariables = enableExperimentalFragmentVariables;
  gql.disableExperimentalFragmentVariables = disableExperimentalFragmentVariables;
  
  var src = gql;
  
  /**
   * This class takes care of the communication with the graphql endpoint by leveraging the awesome apollo-client lib.
   */
  var Apollo = /** @class */ (function () {
      /**
       * @constructor
       */
      function Apollo() {
          var context = Context.getInstance();
          // This allows the test suite to pass a custom link
          if (!context.options.apolloClient && context.options.link) {
              this.httpLink = context.options.link;
          }
          else {
              /* istanbul ignore next */
              this.httpLink = new HttpLink({
                  uri: context.options.url ? context.options.url : "/graphql",
                  credentials: context.options.credentials ? context.options.credentials : "same-origin",
                  useGETForQueries: Boolean(context.options.useGETForQueries)
              });
          }
          if (context.options.apolloClient) {
              this.apolloClient = (function (context) {
                  return context.options.apolloClient;
              })(context);
          }
          else {
              this.apolloClient = new ApolloClient({
                  link: this.httpLink,
                  cache: new InMemoryCache(),
                  connectToDevTools: context.debugMode
              });
          }
      }
      /**
       * Sends a request to the GraphQL API via apollo
       * @param model
       * @param {any} query The query to send (result from gql())
       * @param {Arguments} variables Optional. The variables to send with the query
       * @param {boolean} mutation Optional. If this is a mutation (true) or a query (false, default)
       * @param {boolean} bypassCache If true the query will be send to the server without using the cache. For queries only
       * @returns {Promise<Data>} The new records
       */
      Apollo.prototype.request = function (model, query, variables, mutation, bypassCache) {
          if (mutation === void 0) { mutation = false; }
          if (bypassCache === void 0) { bypassCache = false; }
          return __awaiter(this, void 0, void 0, function () {
              var fetchPolicy, context, response;
              return __generator(this, function (_a) {
                  switch (_a.label) {
                      case 0:
                          fetchPolicy = bypassCache ? "network-only" : "cache-first";
                          Context.getInstance().logger.logQuery(query, variables, fetchPolicy);
                          context = { headers: Apollo.getHeaders() };
                          if (!mutation) return [3 /*break*/, 2];
                          return [4 /*yield*/, this.apolloClient.mutate({ mutation: query, variables: variables, context: context })];
                      case 1:
                          response = _a.sent();
                          return [3 /*break*/, 4];
                      case 2: return [4 /*yield*/, this.apolloClient.query({ query: query, variables: variables, fetchPolicy: fetchPolicy, context: context })];
                      case 3:
                          response = _a.sent();
                          _a.label = 4;
                      case 4: 
                      // Transform incoming data into something useful
                      return [2 /*return*/, Transformer.transformIncomingData(response.data, model, mutation)];
                  }
              });
          });
      };
      Apollo.prototype.simpleQuery = function (query, variables, bypassCache, context) {
          if (bypassCache === void 0) { bypassCache = false; }
          return __awaiter(this, void 0, void 0, function () {
              var fetchPolicy;
              return __generator(this, function (_a) {
                  fetchPolicy = bypassCache ? "network-only" : "cache-first";
                  return [2 /*return*/, this.apolloClient.query({
                          query: src(query),
                          variables: variables,
                          fetchPolicy: fetchPolicy,
                          context: { headers: Apollo.getHeaders() }
                      })];
              });
          });
      };
      Apollo.prototype.simpleMutation = function (query, variables, context) {
          return __awaiter(this, void 0, void 0, function () {
              return __generator(this, function (_a) {
                  return [2 /*return*/, this.apolloClient.mutate({
                          mutation: src(query),
                          variables: variables,
                          context: { headers: Apollo.getHeaders() }
                      })];
              });
          });
      };
      Apollo.getHeaders = function () {
          var context = Context.getInstance();
          var headers = context.options.headers ? context.options.headers : {};
          if (typeof headers === "function") {
              headers = headers(context);
          }
          return headers;
      };
      return Apollo;
  }());
  
  var Schema = /** @class */ (function () {
      function Schema(schema) {
          var _this = this;
          var context = Context.getInstance();
          this.schema = schema;
          this.types = new Map();
          this.mutations = new Map();
          this.queries = new Map();
          this.schema.types.forEach(function (t) { return _this.types.set(t.name, t); });
          this.getType(context.adapter.getRootQueryName()).fields.forEach(function (f) {
              return _this.queries.set(f.name, f);
          });
          this.getType(context.adapter.getRootMutationName()).fields.forEach(function (f) {
              return _this.mutations.set(f.name, f);
          });
      }
      Schema.prototype.determineQueryMode = function () {
          var _this = this;
          var connection = null;
          this.queries.forEach(function (query) {
              var typeName = Schema.getTypeNameOfField(query);
              if (typeName.endsWith("Connection")) {
                  connection = _this.getType(typeName);
                  return false; // break
              }
              return true;
          });
          /* istanbul ignore next */
          if (!connection) {
              throw new Error("Can't determine the connection mode due to the fact that here are no connection types in the schema. Please set the connectionMode via Vuex-ORM-GraphQL options!");
          }
          if (connection.fields.find(function (f) { return f.name === "nodes"; })) {
              return exports.ConnectionMode.NODES;
          }
          else if (connection.fields.find(function (f) { return f.name === "edges"; })) {
              return exports.ConnectionMode.EDGES;
          }
          else if (connection.fields.find(function (f) { return f.name === "items"; })) {
              return exports.ConnectionMode.ITEMS;
          }
          else {
              return exports.ConnectionMode.PLAIN;
          }
      };
      Schema.prototype.getType = function (name, allowNull) {
          if (allowNull === void 0) { allowNull = false; }
          name = Context.getInstance().adapter.prepareSchemaTypeName(name);
          var type = this.types.get(name);
          if (!allowNull && !type) {
              throw new Error("Couldn't find Type of name " + name + " in the GraphQL Schema.");
          }
          return type || null;
      };
      Schema.prototype.getMutation = function (name, allowNull) {
          if (allowNull === void 0) { allowNull = false; }
          var mutation = this.mutations.get(name);
          /* istanbul ignore next */
          if (!allowNull && !mutation) {
              throw new Error("Couldn't find Mutation of name " + name + " in the GraphQL Schema.");
          }
          return mutation || null;
      };
      Schema.prototype.getQuery = function (name, allowNull) {
          if (allowNull === void 0) { allowNull = false; }
          var query = this.queries.get(name);
          /* istanbul ignore next */
          if (!allowNull && !query) {
              throw new Error("Couldn't find Query of name " + name + " in the GraphQL Schema.");
          }
          return query || null;
      };
      Schema.returnsConnection = function (field) {
          return Schema.getTypeNameOfField(field).endsWith("Connection");
      };
      Schema.getRealType = function (type) {
          if (type.kind === "NON_NULL") {
              return this.getRealType(type.ofType);
          }
          else {
              return type;
          }
      };
      Schema.getTypeNameOfField = function (field) {
          var type = this.getRealType(field.type);
          if (type.kind === "LIST") {
              while (!type.name)
                  type = type.ofType;
              return "[" + type.name + "]";
          }
          else {
              while (!type.name)
                  type = type.ofType;
              /* istanbul ignore next */
              if (!type.name)
                  throw new Error("Can't find type name for field " + field.name);
              return type.name;
          }
      };
      return Schema;
  }());
  
  var DefaultAdapter = /** @class */ (function () {
      function DefaultAdapter() {
      }
      DefaultAdapter.prototype.getRootMutationName = function () {
          return "Mutation";
      };
      DefaultAdapter.prototype.getRootQueryName = function () {
          return "Query";
      };
      DefaultAdapter.prototype.getConnectionMode = function () {
          return exports.ConnectionMode.NODES;
      };
      DefaultAdapter.prototype.getArgumentMode = function () {
          return exports.ArgumentMode.TYPE;
      };
      DefaultAdapter.prototype.getFilterTypeName = function (model) {
          return upcaseFirstLetter(model.singularName) + "Filter";
      };
      DefaultAdapter.prototype.getInputTypeName = function (model, action) {
          return upcaseFirstLetter(model.singularName) + "Input";
      };
      DefaultAdapter.prototype.getNameForDestroy = function (model) {
          return "delete" + upcaseFirstLetter(model.singularName);
      };
      DefaultAdapter.prototype.getNameForFetch = function (model, plural) {
          return plural ? model.pluralName : model.singularName;
      };
      DefaultAdapter.prototype.getNameForPersist = function (model) {
          return "create" + upcaseFirstLetter(model.singularName);
      };
      DefaultAdapter.prototype.getNameForPush = function (model) {
          return "update" + upcaseFirstLetter(model.singularName);
      };
      DefaultAdapter.prototype.prepareSchemaTypeName = function (name) {
          return upcaseFirstLetter(name);
      };
      return DefaultAdapter;
  }());
  
  var introspectionQuery = "\nquery Introspection {\n  __schema {\n    types {\n      name\n      description\n      fields(includeDeprecated: true) {\n        name\n        description\n        args {\n          name\n          description\n          type {\n            name\n            kind\n\n            ofType {\n              kind\n\n              name\n              ofType {\n                kind\n                name\n\n                ofType {\n                  kind\n                  name\n                }\n              }\n            }\n          }\n        }\n\n        type {\n          name\n          kind\n\n          ofType {\n            kind\n\n            name\n            ofType {\n              kind\n              name\n\n              ofType {\n                kind\n                name\n              }\n            }\n          }\n        }\n      }\n\n      inputFields {\n        name\n        description\n        type {\n          name\n          kind\n\n          ofType {\n            kind\n\n            name\n            ofType {\n              kind\n              name\n\n              ofType {\n                kind\n                name\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n}\n";
  
  /**
   * Internal context of the plugin. This class contains all information, the models, database, logger and so on.
   *
   * It's a singleton class, so just call Context.getInstance() anywhere you need the context.
   */
  var Context = /** @class */ (function () {
      /**
       * Private constructor, called by the setup method
       *
       * @constructor
       * @param {PluginComponents} components The Vuex-ORM Components collection
       * @param {Options} options The options passed to VuexORM.install
       */
      function Context(components, options) {
          /**
           * Collection of all Vuex-ORM models wrapped in a Model instance.
           * @type {Map<any, any>}
           */
          this.models = new Map();
          /**
           * When true, the logging is enabled.
           * @type {boolean}
           */
          this.debugMode = false;
          /**
           * Defines how to query connections. 'auto' | 'nodes' | 'edges' | 'plain' | 'items'
           */
          this.connectionMode = exports.ConnectionMode.AUTO;
          /**
           * Container for the global mocks.
           * @type {Object}
           */
          this.globalMocks = {};
          this.components = components;
          this.options = options;
          this.database = options.database;
          this.debugMode = Boolean(options.debug);
          this.logger = new Logger(this.debugMode);
          this.adapter = options.adapter || new DefaultAdapter();
          /* istanbul ignore next */
          if (!options.database) {
              throw new Error("database param is required to initialize vuex-orm-graphql!");
          }
      }
      /**
       * Get the singleton instance of the context.
       * @returns {Context}
       */
      Context.getInstance = function () {
          return this.instance;
      };
      /**
       * This is called only once and creates a new instance of the Context.
       * @param {PluginComponents} components The Vuex-ORM Components collection
       * @param {Options} options The options passed to VuexORM.install
       * @returns {Context}
       */
      Context.setup = function (components, options) {
          this.instance = new Context(components, options);
          this.instance.apollo = new Apollo();
          this.instance.collectModels();
          this.instance.logger.group("Context setup");
          this.instance.logger.log("components", this.instance.components);
          this.instance.logger.log("options", this.instance.options);
          this.instance.logger.log("database", this.instance.database);
          this.instance.logger.log("models", this.instance.models);
          this.instance.logger.groupEnd();
          return this.instance;
      };
      Context.prototype.loadSchema = function () {
          return __awaiter(this, void 0, void 0, function () {
              var _this = this;
              return __generator(this, function (_a) {
                  if (!this.schemaWillBeLoaded) {
                      this.schemaWillBeLoaded = new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () {
                          var context, result;
                          return __generator(this, function (_a) {
                              switch (_a.label) {
                                  case 0:
                                      this.logger.log("Fetching GraphQL Schema initially ...");
                                      this.connectionMode = this.adapter.getConnectionMode();
                                      context = {
                                          headers: { "X-GraphQL-Introspection-Query": "true" }
                                      };
                                      return [4 /*yield*/, this.apollo.simpleQuery(introspectionQuery, {}, true, context)];
                                  case 1:
                                      result = _a.sent();
                                      this.schema = new Schema(result.data.__schema);
                                      this.logger.log("GraphQL Schema successful fetched", result);
                                      this.logger.log("Starting to process the schema ...");
                                      this.processSchema();
                                      this.logger.log("Schema procession done!");
                                      resolve(this.schema);
                                      return [2 /*return*/];
                              }
                          });
                      }); });
                  }
                  return [2 /*return*/, this.schemaWillBeLoaded];
              });
          });
      };
      Context.prototype.processSchema = function () {
          var _this = this;
          this.models.forEach(function (model) {
              var type;
              try {
                  type = _this.schema.getType(model.singularName);
              }
              catch (error) {
                  _this.logger.warn("Ignoring entity " + model.singularName + " because it's not in the schema.");
                  return;
              }
              model.fields.forEach(function (field, fieldName) {
                  if (!type.fields.find(function (f) { return f.name === fieldName; })) {
                      _this.logger.warn("Ignoring field " + model.singularName + "." + fieldName + " because it's not in the schema.");
                      // TODO: Move skipFields to the model
                      model.baseModel.skipFields = model.baseModel.skipFields ? model.baseModel.skipFields : [];
                      if (!model.baseModel.skipFields.includes(fieldName)) {
                          model.baseModel.skipFields.push(fieldName);
                      }
                  }
              });
          });
          if (this.connectionMode === exports.ConnectionMode.AUTO) {
              this.connectionMode = this.schema.determineQueryMode();
              this.logger.log("Connection Query Mode is " + this.connectionMode + " by automatic detection");
          }
          else {
              this.logger.log("Connection Query Mode is " + this.connectionMode + " by config");
          }
      };
      /**
       * Returns a model from the model collection by it's name
       *
       * @param {Model|string} model A Model instance, a singular or plural name of the model
       * @param {boolean} allowNull When true this method returns null instead of throwing an exception when no model was
       *                            found. Default is false
       * @returns {Model}
       */
      Context.prototype.getModel = function (model, allowNull) {
          if (allowNull === void 0) { allowNull = false; }
          if (typeof model === "string") {
              var name_1 = singularize(downcaseFirstLetter(model));
              model = this.models.get(name_1);
              if (!allowNull && !model)
                  throw new Error("No such model " + name_1 + "!");
          }
          return model;
      };
      /**
       * Will add a mock for simple mutations or queries. These are model unrelated and have to be
       * handled  globally.
       *
       * @param {Mock} mock - Mock config.
       */
      Context.prototype.addGlobalMock = function (mock) {
          if (this.findGlobalMock(mock.action, mock.options))
              return false;
          if (!this.globalMocks[mock.action])
              this.globalMocks[mock.action] = [];
          this.globalMocks[mock.action].push(mock);
          return true;
      };
      /**
       * Finds a global mock for the given action and options.
       *
       * @param {string} action - Name of the action like 'simpleQuery' or 'simpleMutation'.
       * @param {MockOptions} options - MockOptions like { name: 'example' }.
       * @returns {Mock | null} null when no mock was found.
       */
      Context.prototype.findGlobalMock = function (action, options) {
          if (this.globalMocks[action]) {
              return (this.globalMocks[action].find(function (m) {
                  if (!m.options || !options)
                      return true;
                  var relevantOptions = pick(options, Object.keys(m.options));
                  return isEqual(relevantOptions, m.options || {});
              }) || null);
          }
          return null;
      };
      /**
       * Hook to be called by simpleMutation and simpleQuery actions in order to get the global mock
       * returnValue.
       *
       * @param {string} action - Name of the action like 'simpleQuery' or 'simpleMutation'.
       * @param {MockOptions} options - MockOptions.
       * @returns {any} null when no mock was found.
       */
      Context.prototype.globalMockHook = function (action, options) {
          var returnValue = null;
          var mock = this.findGlobalMock(action, options);
          if (mock) {
              if (mock.returnValue instanceof Function) {
                  returnValue = mock.returnValue();
              }
              else {
                  returnValue = mock.returnValue || null;
              }
          }
          return returnValue;
      };
      /**
       * Wraps all Vuex-ORM entities in a Model object and saves them into this.models
       */
      Context.prototype.collectModels = function () {
          var _this = this;
          this.database.entities.forEach(function (entity) {
              var model = new Model(entity.model);
              _this.models.set(model.singularName, model);
              Model.augment(model);
          });
      };
      return Context;
  }());
  
  /**
   * Contains all logic to build GraphQL queries/mutations.
   */
  var QueryBuilder = /** @class */ (function () {
      function QueryBuilder() {
      }
      /**
       * Builds a field for the GraphQL query and a specific model
       *
       * @param {Model|string} model The model to use
       * @param {boolean} multiple Determines whether plural/nodes syntax or singular syntax is used.
       * @param {Arguments} args The args that will be passed to the query field ( user(role: $role) )
       * @param {Array<Model>} path The relations in this list are ignored (while traversing relations).
       *                                    Mainly for recursion
       * @param {string} name Optional name of the field. If not provided, this will be the model name
       * @param filter
       * @param {boolean} allowIdFields Optional. Determines if id fields will be ignored for the argument generation.
       *                                See buildArguments
       * @returns {string}
       *
       * @todo Do we need the allowIdFields param?
       */
      QueryBuilder.buildField = function (model, multiple, args, path, name, filter, allowIdFields) {
          if (multiple === void 0) { multiple = true; }
          if (path === void 0) { path = []; }
          if (filter === void 0) { filter = false; }
          if (allowIdFields === void 0) { allowIdFields = false; }
          var context = Context.getInstance();
          model = context.getModel(model);
          name = name ? name : model.pluralName;
          var field = context.schema.getMutation(name, true) || context.schema.getQuery(name, true);
          var params = this.buildArguments(model, args, false, filter, allowIdFields, field);
          path = path.length === 0 ? [model.singularName] : path;
          var fields = "\n      " + model.getQueryFields().join(" ") + "\n      " + this.buildRelationsQuery(model, path) + "\n    ";
          if (multiple) {
              var header = "" + name + params;
              if (context.connectionMode === exports.ConnectionMode.NODES) {
                  return "\n          " + header + " {\n            nodes {\n              " + fields + "\n            }\n          }\n        ";
              }
              else if (context.connectionMode === exports.ConnectionMode.EDGES) {
                  return "\n          " + header + " {\n            edges {\n              node {\n                " + fields + "\n              }\n            }\n          }\n        ";
              }
              else if (context.connectionMode === exports.ConnectionMode.ITEMS) {
                  return "\n          " + header + " {\n            items {\n              " + fields + "\n            }\n          }\n        ";
              }
              else {
                  return "\n          " + header + " {\n            " + fields + "\n          }\n        ";
              }
          }
          else {
              return "\n        " + (name ? name : model.singularName) + params + " {\n          " + fields + "\n        }\n      ";
          }
      };
      /**
       * Generates a query.
       * Currently only one root field for the query is possible.
       * @param {string} type 'mutation' or 'query'
       * @param {Model | string} model The model this query or mutation affects. This mainly determines the query fields.
       * @param {string} name Optional name of the query/mutation. Will overwrite the name from the model.
       * @param {Arguments} args Arguments for the query
       * @param {boolean} multiple Determines if the root query field is a connection or not (will be passed to buildField)
       * @param {boolean} filter When true the query arguments are passed via a filter object.
       * @returns {any} Whatever gql() returns
       */
      QueryBuilder.buildQuery = function (type, model, name, args, multiple, filter) {
          var context = Context.getInstance();
          // model
          model = context.getModel(model);
          // arguments
          args = this.prepareArguments(args);
          // multiple
          multiple = multiple === undefined ? !args["id"] : multiple;
          // name
          if (!name)
              name = multiple ? model.pluralName : model.singularName;
          // field
          var field = context.schema.getMutation(name, true) || context.schema.getQuery(name, true);
          // build query
          var query = type + " " + upcaseFirstLetter(name) + this.buildArguments(model, args, true, filter, true, field) + " {\n" +
              ("  " + this.buildField(model, multiple, args, [], name, filter, true) + "\n") +
              "}";
          return src(query);
      };
      /**
       * Generates the arguments string for a graphql query based on a given map.
       *
       * There are three types of arguments:
       *
       * 1) Signatures with primitive types (signature = true)
       *      => 'mutation createUser($name: String!)'
       *
       * 2) Signatures with object types (signature = true, args = { user: { __type: 'User' }})
       *      => 'mutation createUser($user: UserInput!)'
       *
       * 3) Fields with variables (signature = false)
       *      => 'user(id: $id)'
       *
       * 4) Filter fields with variables (signature = false, filter = true)
       *      => 'users(filter: { active: $active })'
       *
       * @param model
       * @param {Arguments | undefined} args
       * @param {boolean} signature When true, then this method generates a query signature instead of key/value pairs
       * @param filter
       * @param {boolean} allowIdFields If true, ID fields will be included in the arguments list
       * @param {GraphQLField} field Optional. The GraphQL mutation or query field
       * @returns {String}
       */
      QueryBuilder.buildArguments = function (model, args, signature, filter, allowIdFields, field) {
          var _this = this;
          if (signature === void 0) { signature = false; }
          if (filter === void 0) { filter = false; }
          if (allowIdFields === void 0) { allowIdFields = true; }
          if (field === void 0) { field = null; }
          var context = Context.getInstance();
          if (args === undefined)
              return "";
          var returnValue = "";
          var first = true;
          if (args) {
              Object.keys(args).forEach(function (key) {
                  var value = args[key];
                  var isForeignKey = model.skipField(key);
                  var skipFieldDueId = (key === "id" || isForeignKey) && !allowIdFields;
                  var schemaField = _this.findSchemaFieldForArgument(key, field, model, filter);
                  var isConnectionField = schemaField && Schema.getTypeNameOfField(schemaField).endsWith("Connection");
                  // Ignore null fields, ids and connections
                  if (value && !skipFieldDueId && !isConnectionField) {
                      var typeOrValue = "";
                      if (signature) {
                          if (isPlainObject(value) && value.__type) {
                              // Case 2 (User!)
                              typeOrValue = context.adapter.getInputTypeName(context.getModel(value.__type)) + "!";
                          }
                          else if (value instanceof Array && field) {
                              var arg = QueryBuilder.findSchemaFieldForArgument(key, field, model, filter);
                              /* istanbul ignore next */
                              if (!arg) {
                                  throw new Error("The argument " + key + " is of type array but it's not possible to determine the type, because it's not in the field " + field.name);
                              }
                              typeOrValue = Schema.getTypeNameOfField(arg) + "!";
                          }
                          else if (schemaField && Schema.getTypeNameOfField(schemaField)) {
                              // Case 1, 3 and 4
                              typeOrValue = Schema.getTypeNameOfField(schemaField) + "!";
                          }
                          else if (key === "id" || isForeignKey) {
                              // Case 1 (ID!)
                              typeOrValue = "ID!";
                          }
                          else {
                              // Case 1 (String!)
                              typeOrValue = _this.determineAttributeType(model, key, value, field || undefined);
                              typeOrValue = typeOrValue + "!";
                          }
                      }
                      else {
                          // Case 3 or 4
                          typeOrValue = "$" + key;
                      }
                      returnValue = "" + returnValue + (first ? "" : ", ") + ((signature ? "$" : "") +
                          key) + ": " + typeOrValue;
                      first = false;
                  }
              });
              if (!first) {
                  if (!signature &&
                      filter &&
                      Context.getInstance().adapter.getArgumentMode() === exports.ArgumentMode.TYPE) {
                      returnValue = "filter: { " + returnValue + " }";
                  }
                  returnValue = "(" + returnValue + ")";
              }
          }
          return returnValue;
      };
      /**
       * Determines the GraphQL primitive type of a field in the variables hash by the field type or (when
       * the field type is generic attribute) by the variable type.
       * @param {Model} model
       * @param {string} key
       * @param {string} value
       * @param {GraphQLField} query Pass when we have to detect the type of an argument
       * @returns {string}
       */
      QueryBuilder.determineAttributeType = function (model, key, value, query) {
          var context = Context.getInstance();
          var field = model.fields.get(key);
          var schemaField;
          if (query) {
              schemaField = query.args.find(function (f) { return f.name === key; });
              if (!schemaField) {
                  var filterField = query.args.find(function (f) { return f.name === "filter"; });
                  if (filterField) {
                      schemaField = this.findSchemaFieldForArgument(key, null, model, true);
                  }
              }
          }
          else {
              schemaField = context.schema.getType(model.singularName).fields.find(function (f) { return f.name === key; });
          }
          if (schemaField && Schema.getTypeNameOfField(schemaField)) {
              return Schema.getTypeNameOfField(schemaField);
          }
          else {
              if (field instanceof context.components.String) {
                  return "String";
              }
              else if (field && field instanceof context.components.Number) {
                  return "Int";
              }
              else if (field && field instanceof context.components.Boolean) {
                  return "Boolean";
              }
              else {
                  if (typeof value === "number")
                      return "Int";
                  if (typeof value === "string")
                      return "String";
                  if (typeof value === "boolean")
                      return "Boolean";
                  throw new Error("Can't find suitable graphql type for field '" + model.singularName + "." + key + "'.");
              }
          }
      };
      QueryBuilder.findSchemaFieldForArgument = function (name, field, model, isFilter) {
          var context = Context.getInstance();
          var schema = context.schema;
          var schemaField;
          if (field) {
              schemaField = field.args.find(function (f) { return f.name === name; });
              if (schemaField)
                  return schemaField;
          }
          // We try to find the FilterType or at least the Type this query belongs to.
          var type = schema.getType(isFilter ? context.adapter.getFilterTypeName(model) : model.singularName, true);
          // Next we try to find the field from the type
          schemaField = type
              ? (isFilter ? type.inputFields : type.fields).find(function (f) { return f.name === name; })
              : undefined;
          // Warn before we return null
          if (!schemaField) {
              Context.getInstance().logger.warn("Couldn't find the argument with name " + name + " for the mutation/query " + (field ? field.name : "(?)"));
          }
          return schemaField;
      };
      /**
       * Generates the fields for all related models.
       *
       * @param {Model} model
       * @param {Array<Model>} path
       * @returns {string}
       */
      QueryBuilder.buildRelationsQuery = function (model, path) {
          var _this = this;
          if (path === void 0) { path = []; }
          if (model === null)
              return "";
          Context.getInstance();
          var relationQueries = [];
          model.getRelations().forEach(function (field, name) {
              var relatedModel = Model.getRelatedModel(field);
              // We will ignore the field, when it's already in the path. Means: When it's already queried. However there are
              // cases where the model will have a relationship to itself. For example a nested category strucure where the
              // category model has a parent: belongsTo(Category). So we also check if the model references itself. If this is
              // the case, we allow the nesting up to 5 times.
              var referencesItSelf = takeWhile(path.slice(0).reverse(), function (p) { return p === relatedModel.singularName; }).length;
              var ignore = referencesItSelf
                  ? referencesItSelf > 5
                  : path.includes(relatedModel.singularName);
              // console.log(`-----> Will ${ignore ? '' : 'not'} ignore ${model.singularName}.${name}, path: ${path.join('.')}`);
              if (model.shouldEagerLoadRelation(name, field, relatedModel) && !ignore) {
                  var newPath = path.slice(0);
                  newPath.push(relatedModel.singularName);
                  relationQueries.push(_this.buildField(relatedModel, Model.isConnection(field), undefined, newPath, name, false));
              }
          });
          return relationQueries.join("\n");
      };
      QueryBuilder.prepareArguments = function (args) {
          args = (args ? clone(args) : {});
          Object.keys(args).forEach(function (key) {
              var value = args[key];
              if (value && isPlainObject(value)) {
                  if (Context.getInstance().adapter.getArgumentMode() === exports.ArgumentMode.LIST) {
                      Object.keys(value).forEach(function (k) {
                          args[k] = value[k];
                      });
                      delete args[key];
                  }
                  else {
                      args[key] = { __type: upcaseFirstLetter(key) };
                  }
              }
          });
          return args;
      };
      return QueryBuilder;
  }());
  
  /**
   * Provides some helper methods to interact with the Vuex-ORM store
   */
  var Store = /** @class */ (function () {
      function Store() {
      }
      /**
       * Inserts incoming data into the store. Existing data will be updated.
       *
       * @param {Data} data New data to insert/update
       * @param {Function} dispatch Vuex Dispatch method for the model
       * @return {Promise<Data>} Inserted data as hash
       */
      Store.insertData = function (data, dispatch) {
          return __awaiter(this, void 0, void 0, function () {
              var insertedData;
              var _this = this;
              return __generator(this, function (_a) {
                  switch (_a.label) {
                      case 0:
                          insertedData = {};
                          return [4 /*yield*/, Promise.all(Object.keys(data).map(function (key) { return __awaiter(_this, void 0, void 0, function () {
                                  var value, newData;
                                  return __generator(this, function (_a) {
                                      switch (_a.label) {
                                          case 0:
                                              value = data[key];
                                              Context.getInstance().logger.log("Inserting records", value);
                                              return [4 /*yield*/, dispatch("insertOrUpdate", { data: value })];
                                          case 1:
                                              newData = _a.sent();
                                              Object.keys(newData).forEach(function (dataKey) {
                                                  if (!insertedData[dataKey])
                                                      insertedData[dataKey] = [];
                                                  insertedData[dataKey] = insertedData[dataKey].concat(newData[dataKey]);
                                              });
                                              return [2 /*return*/];
                                      }
                                  });
                              }); }))];
                      case 1:
                          _a.sent();
                          return [2 /*return*/, insertedData];
                  }
              });
          });
      };
      return Store;
  }());
  
  /**
   * Base class for all Vuex actions. Contains some utility and convenience methods.
   */
  var Action = /** @class */ (function () {
      function Action() {
      }
      /**
       * Sends a mutation.
       *
       * @param {string} name Name of the mutation like 'createUser'
       * @param {Data | undefined} variables Variables to send with the mutation
       * @param {Function} dispatch Vuex Dispatch method for the model
       * @param {Model} model The model this mutation affects.
       * @param {boolean} multiple Tells if we're requesting a single record or multiple.
       * @returns {Promise<any>}
       */
      Action.mutation = function (name, variables, dispatch, model) {
          return __awaiter(this, void 0, void 0, function () {
              var context, schema, multiple, query, newData, insertedData, records, newRecord;
              var _a;
              return __generator(this, function (_b) {
                  switch (_b.label) {
                      case 0:
                          if (!variables) return [3 /*break*/, 5];
                          context = Context.getInstance();
                          return [4 /*yield*/, context.loadSchema()];
                      case 1:
                          schema = _b.sent();
                          multiple = Schema.returnsConnection(schema.getMutation(name));
                          query = QueryBuilder.buildQuery("mutation", model, name, variables, multiple);
                          return [4 /*yield*/, context.apollo.request(model, query, variables, true)];
                      case 2:
                          newData = _b.sent();
                          if (!(name !== context.adapter.getNameForDestroy(model))) return [3 /*break*/, 4];
                          newData = newData[Object.keys(newData)[0]];
                          // IDs as String cause terrible issues, so we convert them to integers.
                          newData.id = toPrimaryKey(newData.id);
                          return [4 /*yield*/, Store.insertData((_a = {}, _a[model.pluralName] = newData, _a), dispatch)];
                      case 3:
                          insertedData = _b.sent();
                          records = insertedData[model.pluralName];
                          newRecord = records[records.length - 1];
                          if (newRecord) {
                              return [2 /*return*/, newRecord];
                          }
                          else {
                              Context.getInstance().logger.log("Couldn't find the record of type '", model.pluralName, "' within", insertedData, ". Falling back to find()");
                              return [2 /*return*/, model.baseModel.query().last()];
                          }
                      case 4: return [2 /*return*/, true];
                      case 5: return [2 /*return*/];
                  }
              });
          });
      };
      /**
       * Convenience method to get the model from the state.
       * @param {RootState} state Vuex state
       * @returns {Model}
       */
      Action.getModelFromState = function (state) {
          return Context.getInstance().getModel(state.$name);
      };
      /**
       * Makes sure args is a hash.
       *
       * @param {Arguments|undefined} args
       * @param {any} id When not undefined, it's added to the args
       * @returns {Arguments}
       */
      Action.prepareArgs = function (args, id) {
          args = args || {};
          if (id)
              args["id"] = id;
          return args;
      };
      /**
       * Adds the record itself to the args and sends it through transformOutgoingData. Key is named by the singular name
       * of the model.
       *
       * @param {Arguments} args
       * @param {Model} model
       * @param {Data} data
       * @returns {Arguments}
       */
      Action.addRecordToArgs = function (args, model, data) {
          args[model.singularName] = Transformer.transformOutgoingData(model, data, false);
          return args;
      };
      /**
       * Transforms each field of the args which contains a model.
       * @param {Arguments} args
       * @returns {Arguments}
       */
      Action.transformArgs = function (args) {
          var context = Context.getInstance();
          Object.keys(args).forEach(function (key) {
              var value = args[key];
              if (value instanceof context.components.Model) {
                  var model = context.getModel(singularize(value.$self().entity));
                  var transformedValue = Transformer.transformOutgoingData(model, value, false);
                  context.logger.log("A", key, "model was found within the variables and will be transformed from", value, "to", transformedValue);
                  args[key] = transformedValue;
              }
          });
          return args;
      };
      return Action;
  }());
  
  /**
   * Destroy action for sending a delete mutation. Will be used for record.$destroy().
   */
  var Destroy = /** @class */ (function (_super) {
      __extends(Destroy, _super);
      function Destroy() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      /**
       * Registers the record.$destroy() and record.$deleteAndDestroy() methods and
       * the destroy Vuex Action.
       */
      Destroy.setup = function () {
          var context = Context.getInstance();
          var record = context.components.Model.prototype;
          context.components.Actions.destroy = Destroy.call.bind(Destroy);
          record.$destroy = function () {
              return __awaiter(this, void 0, void 0, function () {
                  return __generator(this, function (_a) {
                      return [2 /*return*/, this.$dispatch("destroy", { id: toPrimaryKey(this.$id) })];
                  });
              });
          };
          record.$deleteAndDestroy = function () {
              return __awaiter(this, void 0, void 0, function () {
                  return __generator(this, function (_a) {
                      switch (_a.label) {
                          case 0: return [4 /*yield*/, this.$delete()];
                          case 1:
                              _a.sent();
                              return [2 /*return*/, this.$destroy()];
                      }
                  });
              });
          };
      };
      /**
       * @param {State} state The Vuex state
       * @param {DispatchFunction} dispatch Vuex Dispatch method for the model
       * @param {number} id ID of the record to delete
       * @returns {Promise<any>} true
       */
      Destroy.call = function (_a, _b) {
          var state = _a.state, dispatch = _a.dispatch;
          var id = _b.id, args = _b.args;
          return __awaiter(this, void 0, void 0, function () {
              var model, mutationName, mockReturnValue;
              return __generator(this, function (_c) {
                  switch (_c.label) {
                      case 0:
                          if (!id) return [3 /*break*/, 4];
                          model = this.getModelFromState(state);
                          mutationName = Context.getInstance().adapter.getNameForDestroy(model);
                          mockReturnValue = model.$mockHook("destroy", { id: id });
                          if (!mockReturnValue) return [3 /*break*/, 2];
                          return [4 /*yield*/, Store.insertData(mockReturnValue, dispatch)];
                      case 1:
                          _c.sent();
                          return [2 /*return*/, true];
                      case 2:
                          args = this.prepareArgs(args, id);
                          return [4 /*yield*/, Action.mutation(mutationName, args, dispatch, model)];
                      case 3:
                          _c.sent();
                          return [2 /*return*/, true];
                      case 4: 
                      /* istanbul ignore next */
                      throw new Error("The destroy action requires the 'id' to be set");
                  }
              });
          });
      };
      return Destroy;
  }(Action));
  
  /**
   * Fetch action for sending a query. Will be used for Model.fetch().
   */
  var Fetch = /** @class */ (function (_super) {
      __extends(Fetch, _super);
      function Fetch() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      /**
       * Registers the Model.fetch() method and the fetch Vuex Action.
       */
      Fetch.setup = function () {
          var context = Context.getInstance();
          var model = context.components.Model;
          context.components.Actions.fetch = Fetch.call.bind(Fetch);
          model.fetch = function (filter, bypassCache) {
              if (bypassCache === void 0) { bypassCache = false; }
              return __awaiter(this, void 0, void 0, function () {
                  var filterObj;
                  return __generator(this, function (_a) {
                      filterObj = filter;
                      if (!isPlainObject(filterObj))
                          filterObj = { id: filter };
                      return [2 /*return*/, this.dispatch("fetch", { filter: filterObj, bypassCache: bypassCache })];
                  });
              });
          };
      };
      /**
       * @param {any} state The Vuex state
       * @param {DispatchFunction} dispatch Vuex Dispatch method for the model
       * @param {ActionParams} params Optional params to send with the query
       * @returns {Promise<Data>} The fetched records as hash
       */
      Fetch.call = function (_a, params) {
          var state = _a.state, dispatch = _a.dispatch;
          return __awaiter(this, void 0, void 0, function () {
              var context, model, mockReturnValue, filter, bypassCache, multiple, name, query, data;
              return __generator(this, function (_b) {
                  switch (_b.label) {
                      case 0:
                          context = Context.getInstance();
                          model = this.getModelFromState(state);
                          mockReturnValue = model.$mockHook("fetch", {
                              filter: params ? params.filter || {} : {}
                          });
                          if (mockReturnValue) {
                              return [2 /*return*/, Store.insertData(mockReturnValue, dispatch)];
                          }
                          return [4 /*yield*/, context.loadSchema()];
                      case 1:
                          _b.sent();
                          filter = {};
                          if (params && params.filter) {
                              filter = Transformer.transformOutgoingData(model, params.filter, true, Object.keys(params.filter));
                          }
                          bypassCache = params && params.bypassCache;
                          multiple = !filter["id"];
                          name = context.adapter.getNameForFetch(model, multiple);
                          query = QueryBuilder.buildQuery("query", model, name, filter, multiple, multiple);
                          return [4 /*yield*/, context.apollo.request(model, query, filter, false, bypassCache)];
                      case 2:
                          data = _b.sent();
                          // Insert incoming data into the store
                          return [2 /*return*/, Store.insertData(data, dispatch)];
                  }
              });
          });
      };
      return Fetch;
  }(Action));
  
  /**
   * Mutate action for sending a custom mutation. Will be used for Model.mutate() and record.$mutate().
   */
  var Mutate = /** @class */ (function (_super) {
      __extends(Mutate, _super);
      function Mutate() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      /**
       * Registers the Model.mutate() and the record.$mutate() methods and the mutate Vuex Action.
       */
      Mutate.setup = function () {
          var context = Context.getInstance();
          var model = context.components.Model;
          var record = context.components.Model.prototype;
          context.components.Actions.mutate = Mutate.call.bind(Mutate);
          model.mutate = function (params) {
              return __awaiter(this, void 0, void 0, function () {
                  return __generator(this, function (_a) {
                      return [2 /*return*/, this.dispatch("mutate", params)];
                  });
              });
          };
          record.$mutate = function (_a) {
              var name = _a.name, args = _a.args, multiple = _a.multiple;
              return __awaiter(this, void 0, void 0, function () {
                  return __generator(this, function (_b) {
                      args = args || {};
                      if (!args["id"])
                          args["id"] = toPrimaryKey(this.$id);
                      return [2 /*return*/, this.$dispatch("mutate", { name: name, args: args, multiple: multiple })];
                  });
              });
          };
      };
      /**
       * @param {any} state The Vuex state
       * @param {DispatchFunction} dispatch Vuex Dispatch method for the model
       * @param {string} name Name of the query
       * @param {boolean} multiple Fetch one or multiple?
       * @param {Arguments} args Arguments for the mutation. Must contain a 'mutation' field.
       * @returns {Promise<Data>} The new record if any
       */
      Mutate.call = function (_a, _b) {
          var state = _a.state, dispatch = _a.dispatch;
          var args = _b.args, name = _b.name;
          return __awaiter(this, void 0, void 0, function () {
              var context, model, mockReturnValue;
              return __generator(this, function (_c) {
                  switch (_c.label) {
                      case 0:
                          if (!name) return [3 /*break*/, 2];
                          context = Context.getInstance();
                          model = this.getModelFromState(state);
                          mockReturnValue = model.$mockHook("mutate", {
                              name: name,
                              args: args || {}
                          });
                          if (mockReturnValue) {
                              return [2 /*return*/, Store.insertData(mockReturnValue, dispatch)];
                          }
                          return [4 /*yield*/, context.loadSchema()];
                      case 1:
                          _c.sent();
                          args = this.prepareArgs(args);
                          // There could be anything in the args, but we have to be sure that all records are gone through
                          // transformOutgoingData()
                          this.transformArgs(args);
                          // Send the mutation
                          return [2 /*return*/, Action.mutation(name, args, dispatch, model)];
                      case 2: 
                      /* istanbul ignore next */
                      throw new Error("The mutate action requires the mutation name ('mutation') to be set");
                  }
              });
          });
      };
      return Mutate;
  }(Action));
  
  /**
   * Persist action for sending a create mutation. Will be used for record.$persist().
   */
  var Persist = /** @class */ (function (_super) {
      __extends(Persist, _super);
      function Persist() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      /**
       * Registers the record.$persist() method and the persist Vuex Action.
       */
      Persist.setup = function () {
          var context = Context.getInstance();
          var record = context.components.Model.prototype;
          context.components.Actions.persist = Persist.call.bind(Persist);
          record.$persist = function (args) {
              return __awaiter(this, void 0, void 0, function () {
                  return __generator(this, function (_a) {
                      return [2 /*return*/, this.$dispatch("persist", { id: this.$id, args: args })];
                  });
              });
          };
      };
      /**
       * @param {any} state The Vuex state
       * @param {DispatchFunction} dispatch Vuex Dispatch method for the model
       * @param {number|string} id ID of the record to persist
       * @returns {Promise<Data>} The saved record
       */
      Persist.call = function (_a, _b) {
          var state = _a.state, dispatch = _a.dispatch;
          var id = _b.id, args = _b.args;
          return __awaiter(this, void 0, void 0, function () {
              var model, mutationName, oldRecord, mockReturnValue, newRecord_1, newRecord;
              return __generator(this, function (_c) {
                  switch (_c.label) {
                      case 0:
                          if (!id) return [3 /*break*/, 7];
                          model = this.getModelFromState(state);
                          mutationName = Context.getInstance().adapter.getNameForPersist(model);
                          oldRecord = model.getRecordWithId(id);
                          mockReturnValue = model.$mockHook("persist", {
                              id: toPrimaryKey(id),
                              args: args || {}
                          });
                          if (!mockReturnValue) return [3 /*break*/, 3];
                          return [4 /*yield*/, Store.insertData(mockReturnValue, dispatch)];
                      case 1:
                          newRecord_1 = _c.sent();
                          return [4 /*yield*/, this.deleteObsoleteRecord(model, newRecord_1, oldRecord)];
                      case 2:
                          _c.sent();
                          return [2 /*return*/, newRecord_1];
                      case 3: 
                      // Arguments
                      return [4 /*yield*/, Context.getInstance().loadSchema()];
                      case 4:
                          // Arguments
                          _c.sent();
                          args = this.prepareArgs(args);
                          this.addRecordToArgs(args, model, oldRecord);
                          return [4 /*yield*/, Action.mutation(mutationName, args, dispatch, model)];
                      case 5:
                          newRecord = _c.sent();
                          // Delete the old record if necessary
                          return [4 /*yield*/, this.deleteObsoleteRecord(model, newRecord, oldRecord)];
                      case 6:
                          // Delete the old record if necessary
                          _c.sent();
                          return [2 /*return*/, newRecord];
                      case 7: 
                      /* istanbul ignore next */
                      throw new Error("The persist action requires the 'id' to be set");
                  }
              });
          });
      };
      /**
       * It's very likely that the server generated different ID for this record.
       * In this case Action.mutation has inserted a new record instead of updating the existing one.
       *
       * @param {Model} model
       * @param {Data} record
       * @returns {Promise<void>}
       */
      Persist.deleteObsoleteRecord = function (model, newRecord, oldRecord) {
          return __awaiter(this, void 0, void 0, function () {
              return __generator(this, function (_a) {
                  if (newRecord && oldRecord && newRecord.id !== oldRecord.id) {
                      Context.getInstance().logger.log("Dropping deprecated record", oldRecord);
                      return [2 /*return*/, oldRecord.$delete()];
                  }
                  return [2 /*return*/, null];
              });
          });
      };
      return Persist;
  }(Action));
  
  /**
   * Push action for sending a update mutation. Will be used for record.$push().
   */
  var Push = /** @class */ (function (_super) {
      __extends(Push, _super);
      function Push() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      /**
       * Registers the record.$push() method and the push Vuex Action.
       */
      Push.setup = function () {
          var context = Context.getInstance();
          var model = context.components.Model.prototype;
          context.components.Actions.push = Push.call.bind(Push);
          model.$push = function (args) {
              return __awaiter(this, void 0, void 0, function () {
                  return __generator(this, function (_a) {
                      return [2 /*return*/, this.$dispatch("push", { data: this, args: args })];
                  });
              });
          };
      };
      /**
       * @param {any} state The Vuex state
       * @param {DispatchFunction} dispatch Vuex Dispatch method for the model
       * @param {Arguments} data New data to save
       * @param {Arguments} args Additional arguments
       * @returns {Promise<Data>} The updated record
       */
      Push.call = function (_a, _b) {
          var state = _a.state, dispatch = _a.dispatch;
          var data = _b.data, args = _b.args;
          return __awaiter(this, void 0, void 0, function () {
              var model, mutationName, mockReturnValue;
              return __generator(this, function (_c) {
                  switch (_c.label) {
                      case 0:
                          if (!data) return [3 /*break*/, 2];
                          model = this.getModelFromState(state);
                          mutationName = Context.getInstance().adapter.getNameForPush(model);
                          mockReturnValue = model.$mockHook("push", {
                              data: data,
                              args: args || {}
                          });
                          if (mockReturnValue) {
                              return [2 /*return*/, Store.insertData(mockReturnValue, dispatch)];
                          }
                          // Arguments
                          return [4 /*yield*/, Context.getInstance().loadSchema()];
                      case 1:
                          // Arguments
                          _c.sent();
                          args = this.prepareArgs(args, data.id);
                          this.addRecordToArgs(args, model, data);
                          // Send the mutation
                          return [2 /*return*/, Action.mutation(mutationName, args, dispatch, model)];
                      case 2: 
                      /* istanbul ignore next */
                      throw new Error("The persist action requires the 'data' to be set");
                  }
              });
          });
      };
      return Push;
  }(Action));
  
  /**
   * Query action for sending a custom query. Will be used for Model.customQuery() and record.$customQuery.
   */
  var Query = /** @class */ (function (_super) {
      __extends(Query, _super);
      function Query() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      /**
       * Registers the Model.customQuery and the record.$customQuery() methods and the
       * query Vuex Action.
       */
      Query.setup = function () {
          var context = Context.getInstance();
          var model = context.components.Model;
          var record = context.components.Model.prototype;
          context.components.Actions.query = Query.call.bind(Query);
          model.customQuery = function (_a) {
              var name = _a.name, filter = _a.filter, multiple = _a.multiple, bypassCache = _a.bypassCache;
              return __awaiter(this, void 0, void 0, function () {
                  return __generator(this, function (_b) {
                      return [2 /*return*/, this.dispatch("query", { name: name, filter: filter, multiple: multiple, bypassCache: bypassCache })];
                  });
              });
          };
          record.$customQuery = function (_a) {
              var name = _a.name, filter = _a.filter, multiple = _a.multiple, bypassCache = _a.bypassCache;
              return __awaiter(this, void 0, void 0, function () {
                  return __generator(this, function (_b) {
                      filter = filter || {};
                      if (!filter["id"])
                          filter["id"] = toPrimaryKey(this.$id);
                      return [2 /*return*/, this.$dispatch("query", { name: name, filter: filter, multiple: multiple, bypassCache: bypassCache })];
                  });
              });
          };
      };
      /**
       * @param {any} state The Vuex state
       * @param {DispatchFunction} dispatch Vuex Dispatch method for the model
       * @param {string} name Name of the query
       * @param {boolean} multiple Fetch one or multiple?
       * @param {object} filter Filter object (arguments)
       * @param {boolean} bypassCache Whether to bypass the cache
       * @returns {Promise<Data>} The fetched records as hash
       */
      Query.call = function (_a, _b) {
          var state = _a.state, dispatch = _a.dispatch;
          var name = _b.name, filter = _b.filter, bypassCache = _b.bypassCache;
          return __awaiter(this, void 0, void 0, function () {
              var context, model, mockReturnValue, schema, multiple, query, data;
              return __generator(this, function (_c) {
                  switch (_c.label) {
                      case 0:
                          if (!name) return [3 /*break*/, 3];
                          context = Context.getInstance();
                          model = this.getModelFromState(state);
                          mockReturnValue = model.$mockHook("query", {
                              name: name,
                              filter: filter || {}
                          });
                          if (mockReturnValue) {
                              return [2 /*return*/, Store.insertData(mockReturnValue, dispatch)];
                          }
                          return [4 /*yield*/, context.loadSchema()];
                      case 1:
                          schema = _c.sent();
                          // Filter
                          filter = filter ? Transformer.transformOutgoingData(model, filter, true) : {};
                          multiple = Schema.returnsConnection(schema.getQuery(name));
                          query = QueryBuilder.buildQuery("query", model, name, filter, multiple, false);
                          return [4 /*yield*/, context.apollo.request(model, query, filter, false, bypassCache)];
                      case 2:
                          data = _c.sent();
                          // Insert incoming data into the store
                          return [2 /*return*/, Store.insertData(data, dispatch)];
                      case 3: 
                      /* istanbul ignore next */
                      throw new Error("The customQuery action requires the query name ('name') to be set");
                  }
              });
          });
      };
      return Query;
  }(Action));
  
  /**
   * SimpleQuery action for sending a model unrelated simple query.
   */
  var SimpleQuery = /** @class */ (function (_super) {
      __extends(SimpleQuery, _super);
      function SimpleQuery() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      /**
       * Registers the Model.simpleQuery() Vuex Root Action.
       */
      SimpleQuery.setup = function () {
          var context = Context.getInstance();
          context.components.RootActions.simpleQuery = SimpleQuery.call.bind(SimpleQuery);
      };
      /**
       * @param {DispatchFunction} dispatch Vuex Dispatch method for the model
       * @param {string} query The query to send
       * @param {Arguments} variables
       * @param {boolean} bypassCache Whether to bypass the cache
       * @returns {Promise<any>} The result
       */
      SimpleQuery.call = function (_a, _b) {
          _a.dispatch;
          var query = _b.query, bypassCache = _b.bypassCache, variables = _b.variables;
          return __awaiter(this, void 0, void 0, function () {
              var context, parsedQuery, mockReturnValue, result;
              return __generator(this, function (_c) {
                  switch (_c.label) {
                      case 0:
                          context = Context.getInstance();
                          if (!query) return [3 /*break*/, 2];
                          parsedQuery = parseQuery(query);
                          mockReturnValue = context.globalMockHook("simpleQuery", {
                              name: parsedQuery.definitions[0]["name"].value,
                              variables: variables
                          });
                          if (mockReturnValue) {
                              return [2 /*return*/, mockReturnValue];
                          }
                          variables = this.prepareArgs(variables);
                          return [4 /*yield*/, context.apollo.simpleQuery(graphQlDocumentToString(parsedQuery), variables, bypassCache)];
                      case 1:
                          result = _c.sent();
                          // remove the symbols
                          return [2 /*return*/, removeSymbols(clone(result.data))];
                      case 2: 
                      /* istanbul ignore next */
                      throw new Error("The simpleQuery action requires the 'query' to be set");
                  }
              });
          });
      };
      return SimpleQuery;
  }(Action));
  
  /**
   * SimpleMutation action for sending a model unrelated simple mutation.
   */
  var SimpleMutation = /** @class */ (function (_super) {
      __extends(SimpleMutation, _super);
      function SimpleMutation() {
          return _super !== null && _super.apply(this, arguments) || this;
      }
      /**
       * Registers the Model.simpleMutation() Vuex Root Action.
       */
      SimpleMutation.setup = function () {
          var context = Context.getInstance();
          context.components.RootActions.simpleMutation = SimpleMutation.call.bind(SimpleMutation);
      };
      /**
       * @param {DispatchFunction} dispatch Vuex Dispatch method for the model
       * @param {string} query The query to send
       * @param {Arguments} variables
       * @returns {Promise<any>} The result
       */
      SimpleMutation.call = function (_a, _b) {
          _a.dispatch;
          var query = _b.query, variables = _b.variables;
          return __awaiter(this, void 0, void 0, function () {
              var context, parsedQuery, mockReturnValue, result;
              return __generator(this, function (_c) {
                  switch (_c.label) {
                      case 0:
                          context = Context.getInstance();
                          if (!query) return [3 /*break*/, 2];
                          parsedQuery = parseQuery(query);
                          mockReturnValue = context.globalMockHook("simpleMutation", {
                              name: parsedQuery.definitions[0]["name"].value,
                              variables: variables
                          });
                          if (mockReturnValue) {
                              return [2 /*return*/, mockReturnValue];
                          }
                          variables = this.prepareArgs(variables);
                          return [4 /*yield*/, context.apollo.simpleMutation(graphQlDocumentToString(parsedQuery), variables)];
                      case 1:
                          result = _c.sent();
                          // remove the symbols
                          return [2 /*return*/, clone(result.data)];
                      case 2: 
                      /* istanbul ignore next */
                      throw new Error("The simpleMutation action requires the 'query' to be set");
                  }
              });
          });
      };
      return SimpleMutation;
  }(Action));
  
  /**
   * Main class of the plugin. Setups the internal context, Vuex actions and model methods
   */
  var VuexORMGraphQL = /** @class */ (function () {
      /**
       * @constructor
       * @param {PluginComponents} components The Vuex-ORM Components collection
       * @param {Options} options The options passed to VuexORM.install
       */
      function VuexORMGraphQL(components, options) {
          Context.setup(components, options);
          VuexORMGraphQL.setupActions();
      }
      /**
       * Allow everything to read the context.
       */
      VuexORMGraphQL.prototype.getContext = function () {
          return Context.getInstance();
      };
      /**
       * This method will setup:
       *   - Vuex actions: fetch, persist, push, destroy, mutate
       *   - Model methods: fetch(), mutate(), customQuery()
       *   - Record method: $mutate(), $persist(), $push(), $destroy(), $deleteAndDestroy(), $customQuery()
       */
      VuexORMGraphQL.setupActions = function () {
          Fetch.setup();
          Persist.setup();
          Push.setup();
          Destroy.setup();
          Mutate.setup();
          Query.setup();
          SimpleQuery.setup();
          SimpleMutation.setup();
      };
      return VuexORMGraphQL;
  }());
  
  /**
   * Plugin class. This just provides a static install method for Vuex-ORM and stores the instance of the model
   * within this.instance.
   */
  var VuexORMGraphQLPlugin = /** @class */ (function () {
      function VuexORMGraphQLPlugin() {
      }
      /**
       * This is called, when VuexORM.install(VuexOrmGraphQL, options) is called.
       *
       * @param {PluginComponents} components The Vuex-ORM Components collection
       * @param {Options} options The options passed to VuexORM.install
       * @returns {VuexORMGraphQL}
       */
      VuexORMGraphQLPlugin.install = function (components, options) {
          VuexORMGraphQLPlugin.instance = new VuexORMGraphQL(components, options);
          return VuexORMGraphQLPlugin.instance;
      };
      return VuexORMGraphQLPlugin;
  }());
  
  var context = null;
  function setupTestUtils(plugin) {
      /* istanbul ignore next */
      if (!plugin.instance) {
          throw new Error("Please call this function after setting up the store!");
      }
      context = plugin.instance.getContext();
  }
  var Mock = /** @class */ (function () {
      function Mock(action, options) {
          this.action = action;
          this.options = options;
      }
      Mock.prototype.for = function (modelClass) {
          this.modelClass = modelClass;
          return this;
      };
      Mock.prototype.andReturn = function (returnValue) {
          this.returnValue = returnValue;
          this.installMock();
          return this;
      };
      Mock.prototype.installMock = function () {
          if (this.action === "simpleQuery" || this.action === "simpleMutation") {
              context.addGlobalMock(this);
          }
          else {
              var model = context.getModel(this.modelClass.entity);
              model.$addMock(this);
          }
      };
      return Mock;
  }());
  function clearORMStore() {
      return __awaiter(this, void 0, void 0, function () {
          return __generator(this, function (_a) {
              switch (_a.label) {
                  case 0:
                      /* istanbul ignore next */
                      if (!context) {
                          throw new Error("Please call setupTestUtils() before!");
                      }
                      return [4 /*yield*/, context.database.store.dispatch("entities/deleteAll")];
                  case 1:
                      _a.sent();
                      return [2 /*return*/];
              }
          });
      });
  }
  function mock(action, options) {
      /* istanbul ignore next */
      if (!context) {
          throw new Error("Please call setupTestUtils() before!");
      }
      return new Mock(action, options);
  }
  
  exports.DefaultAdapter = DefaultAdapter;
  exports.Mock = Mock;
  exports.Model = Model;
  exports.clearORMStore = clearORMStore;
  exports.default = VuexORMGraphQLPlugin;
  exports.mock = mock;
  exports.setupTestUtils = setupTestUtils;
  