import React, { useMemo as useMemo$1 } from 'react';

function _typeof(obj) {
  "@babel/helpers - typeof";

  if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
    _typeof = function (obj) {
      return typeof obj;
    };
  } else {
    _typeof = function (obj) {
      return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
    };
  }

  return _typeof(obj);
}

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

function _defineProperty(obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj[key] = value;
  }

  return obj;
}

function ownKeys(object, enumerableOnly) {
  var keys = Object.keys(object);

  if (Object.getOwnPropertySymbols) {
    var symbols = Object.getOwnPropertySymbols(object);
    if (enumerableOnly) symbols = symbols.filter(function (sym) {
      return Object.getOwnPropertyDescriptor(object, sym).enumerable;
    });
    keys.push.apply(keys, symbols);
  }

  return keys;
}

function _objectSpread2(target) {
  for (var i = 1; i < arguments.length; i++) {
    var source = arguments[i] != null ? arguments[i] : {};

    if (i % 2) {
      ownKeys(Object(source), true).forEach(function (key) {
        _defineProperty(target, key, source[key]);
      });
    } else if (Object.getOwnPropertyDescriptors) {
      Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
    } else {
      ownKeys(Object(source)).forEach(function (key) {
        Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
      });
    }
  }

  return target;
}

function _objectWithoutPropertiesLoose(source, excluded) {
  if (source == null) return {};
  var target = {};
  var sourceKeys = Object.keys(source);
  var key, i;

  for (i = 0; i < sourceKeys.length; i++) {
    key = sourceKeys[i];
    if (excluded.indexOf(key) >= 0) continue;
    target[key] = source[key];
  }

  return target;
}

function _objectWithoutProperties(source, excluded) {
  if (source == null) return {};

  var target = _objectWithoutPropertiesLoose(source, excluded);

  var key, i;

  if (Object.getOwnPropertySymbols) {
    var sourceSymbolKeys = Object.getOwnPropertySymbols(source);

    for (i = 0; i < sourceSymbolKeys.length; i++) {
      key = sourceSymbolKeys[i];
      if (excluded.indexOf(key) >= 0) continue;
      if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
      target[key] = source[key];
    }
  }

  return target;
}

function _slicedToArray(arr, i) {
  return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();
}

function _toConsumableArray(arr) {
  return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
}

function _arrayWithoutHoles(arr) {
  if (Array.isArray(arr)) return _arrayLikeToArray(arr);
}

function _arrayWithHoles(arr) {
  if (Array.isArray(arr)) return arr;
}

function _iterableToArray(iter) {
  if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
}

function _iterableToArrayLimit(arr, i) {
  if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return;
  var _arr = [];
  var _n = true;
  var _d = false;
  var _e = undefined;

  try {
    for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
      _arr.push(_s.value);

      if (i && _arr.length === i) break;
    }
  } catch (err) {
    _d = true;
    _e = err;
  } finally {
    try {
      if (!_n && _i["return"] != null) _i["return"]();
    } finally {
      if (_d) throw _e;
    }
  }

  return _arr;
}

function _unsupportedIterableToArray(o, minLen) {
  if (!o) return;
  if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  var n = Object.prototype.toString.call(o).slice(8, -1);
  if (n === "Object" && o.constructor) n = o.constructor.name;
  if (n === "Map" || n === "Set") return Array.from(o);
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}

function _arrayLikeToArray(arr, len) {
  if (len == null || len > arr.length) len = arr.length;

  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];

  return arr2;
}

function _nonIterableSpread() {
  throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}

function _nonIterableRest() {
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}

function _createForOfIteratorHelper(o) {
  if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) {
    if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) {
      var i = 0;

      var F = function () {};

      return {
        s: F,
        n: function () {
          if (i >= o.length) return {
            done: true
          };
          return {
            done: false,
            value: o[i++]
          };
        },
        e: function (e) {
          throw e;
        },
        f: F
      };
    }

    throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
  }

  var it,
      normalCompletion = true,
      didErr = false,
      err;
  return {
    s: function () {
      it = o[Symbol.iterator]();
    },
    n: function () {
      var step = it.next();
      normalCompletion = step.done;
      return step;
    },
    e: function (e) {
      didErr = true;
      err = e;
    },
    f: function () {
      try {
        if (!normalCompletion && it.return != null) it.return();
      } finally {
        if (didErr) throw err;
      }
    }
  };
}

var Cache = /*#__PURE__*/function () {
  function Cache() {
    var cacheSize = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_CACHE_SIZE;

    _classCallCheck(this, Cache);

    _defineProperty(this, "_cache", new Map([]));

    this.cacheSize = cacheSize;
    this.softResetCache = null;
  }

  _createClass(Cache, [{
    key: "get",
    value: function get(key) {
      return this._cache.get(key);
    }
  }, {
    key: "set",
    value: function set(key, results) {
      this._cache.set(key, results);
    }
  }, {
    key: "removeItem",
    value: function removeItem(key) {
      this._cache.delete(key);
    }
  }, {
    key: "clearCache",
    value: function clearCache() {
      this._cache.clear();
    }
  }, {
    key: "clone",
    value: function clone() {
      var filter = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function (x) {
        return true;
      };
      var result = new Cache(this.cacheSize);
      result._cache = new Map(_toConsumableArray(this._cache).filter(filter));
      return result;
    }
  }, {
    key: "setPendingResult",
    value: function setPendingResult(graphqlQuery, promise) {
      var cache = this._cache; //front of the line now, to support LRU ejection

      cache.delete(graphqlQuery);

      if (cache.size === this.cacheSize) {
        //maps iterate entries and keys in insertion order - zero'th key should be oldest
        cache.delete(_toConsumableArray(cache.keys())[0]);
      }

      cache.set(graphqlQuery, promise);
    }
  }, {
    key: "setResults",
    value: function setResults(promise, cacheKey, resp, err) {
      var cache = this._cache; //cache may have been cleared while we were running. If so, we'll respect that, and not touch the cache, but we'll still use the results locally

      if (cache.get(cacheKey) !== promise) return;

      if (err) {
        cache.set(cacheKey, {
          data: null,
          error: err
        });
      } else {
        if (resp.errors) {
          cache.set(cacheKey, {
            data: null,
            error: resp.errors
          });
        } else {
          cache.set(cacheKey, {
            data: resp.data,
            error: null
          });
        }
      }
    }
  }, {
    key: "getFromCache",
    value: function getFromCache(key, ifPending, ifResults) {
      var ifNotFound = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {};
      var byPassSoftReset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
      var cache = this._cache;
      var cachedEntry = cache.get(key);

      if (!byPassSoftReset && this.softResetCache) {
        if (this.softResetCache[key]) {
          return ifResults(this.softResetCache[key]);
        }
      }

      if (cachedEntry) {
        if (typeof cachedEntry.then === "function") {
          ifPending(cachedEntry);
        } else {
          //re-insert to put it at the fornt of the line
          cache.delete(key);
          this.set(key, cachedEntry);
          ifResults(cachedEntry);
          this.softResetCache = null;
        }
      } else {
        ifNotFound();
      }
    }
  }, {
    key: "keys",
    get: function get() {
      return _toConsumableArray(this._cache.keys());
    }
  }, {
    key: "entries",
    get: function get() {
      return _toConsumableArray(this._cache);
    }
  }]);

  return Cache;
}();
var DEFAULT_CACHE_SIZE = 10;

var Client = /*#__PURE__*/function () {
  function Client() {
    var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
      cacheSize: DEFAULT_CACHE_SIZE
    };

    _classCallCheck(this, Client);

    Object.assign(this, props);
    this.caches = new Map([]);
    this.mutationListeners = new Set([]);
    this.forceListeners = new Map([]);
  }

  _createClass(Client, [{
    key: "preload",
    value: function preload(query, variables) {
      var _this = this;

      var cache = this.getCache(query);

      if (!cache) {
        cache = this.newCacheForQuery(query);
      }

      var graphqlQuery = this.getGraphqlQuery({
        query: query,
        variables: variables
      });
      var promiseResult;
      cache.getFromCache(graphqlQuery, function (promise) {
        promiseResult = promise;
        /* already preloading - cool */
      }, function (cachedEntry) {
        /* already loaded - cool */
        promiseResult = Promise.resolve(cachedEntry);
      }, function () {
        var promise = _this.runUri(graphqlQuery);

        cache.setPendingResult(graphqlQuery, promise);
        promiseResult = promise;
        promise.then(function (resp) {
          cache.setResults(promise, graphqlQuery, resp);
        });
      });
      return promiseResult;
    }
  }, {
    key: "read",
    value: function read(query, variables) {
      var _this2 = this;

      var cache = this.getCache(query);

      if (!cache) {
        cache = this.newCacheForQuery(query);
      }

      var graphqlQuery = this.getGraphqlQuery({
        query: query,
        variables: variables
      });
      var promiseResult;
      var cachedResult;
      cache.getFromCache(graphqlQuery, function (promise) {
        promiseResult = promise;
        /* already preloading - cool */
      }, function (cachedEntry) {
        /* already loaded - cool */
        cachedResult = cachedEntry;
      }, function () {
        var promise = _this2.runUri(graphqlQuery);

        cache.setPendingResult(graphqlQuery, promise);
        promiseResult = promise;
        promise.then(function (resp) {
          cache.setResults(promise, graphqlQuery, resp);
        });
      });

      if (promiseResult) {
        throw promiseResult;
      }

      return cachedResult;
    }
  }, {
    key: "getCache",
    value: function getCache(query) {
      return this.caches.get(query);
    }
  }, {
    key: "newCacheForQuery",
    value: function newCacheForQuery(query) {
      var newCache = new Cache(this.cacheSizeToUse);
      this.setCache(query, newCache);
      return newCache;
    }
  }, {
    key: "setCache",
    value: function setCache(query, cache) {
      this.caches.set(query, cache);
    }
  }, {
    key: "runQuery",
    value: function runQuery(query, variables) {
      return this.runUri(this.getGraphqlQuery({
        query: query,
        variables: variables
      }));
    }
  }, {
    key: "runUri",
    value: function runUri(uri) {
      return fetch(uri, this.fetchOptions || void 0).then(function (resp) {
        return resp.json();
      });
    }
  }, {
    key: "getGraphqlQuery",
    value: function getGraphqlQuery(_ref) {
      var query = _ref.query,
          variables = _ref.variables;
      return "".concat(this.endpoint, "?query=").concat(encodeURIComponent(query)).concat(_typeof(variables) === "object" ? "&variables=".concat(encodeURIComponent(JSON.stringify(variables))) : "");
    }
  }, {
    key: "subscribeMutation",
    value: function subscribeMutation(subscription) {
      var _this3 = this;

      var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

      if (!Array.isArray(subscription)) {
        subscription = [subscription];
      }

      var packet = {
        subscription: subscription,
        options: options
      };

      if (!options.currentResults) {
        options.currentResults = function () {
          return {};
        };
      }

      this.mutationListeners.add(packet);
      return function () {
        return _this3.mutationListeners.delete(packet);
      };
    }
  }, {
    key: "forceUpdate",
    value: function forceUpdate(query) {
      var updateListeners = this.forceListeners.get(query);

      if (updateListeners) {
        var _iterator = _createForOfIteratorHelper(updateListeners),
            _step;

        try {
          for (_iterator.s(); !(_step = _iterator.n()).done;) {
            var refresh = _step.value;
            refresh();
          }
        } catch (err) {
          _iterator.e(err);
        } finally {
          _iterator.f();
        }
      }
    }
  }, {
    key: "registerQuery",
    value: function registerQuery(query, refresh) {
      var _this4 = this;

      if (!this.forceListeners.has(query)) {
        this.forceListeners.set(query, new Set([]));
      }

      this.forceListeners.get(query).add(refresh);
      return function () {
        return _this4.forceListeners.get(query).delete(refresh);
      };
    }
  }, {
    key: "processMutation",
    value: function processMutation(mutation, variables) {
      var _this5 = this;

      var refreshActiveQueries = function refreshActiveQueries(query) {
        return _this5.forceUpdate(query);
      };

      return Promise.resolve(this.runMutation(mutation, variables)).then(function (resp) {
        var mutationKeys = Object.keys(resp);
        var mutationKeysLookup = new Set(mutationKeys);

        _toConsumableArray(_this5.mutationListeners).forEach(function (_ref2) {
          var subscription = _ref2.subscription,
              _ref2$options = _ref2.options,
              currentResults = _ref2$options.currentResults,
              isActive = _ref2$options.isActive,
              rest = _objectWithoutProperties(_ref2$options, ["currentResults", "isActive"]);

          subscription.forEach(function (singleSubscription) {
            if (typeof isActive === "function") {
              if (!isActive()) {
                return;
              }
            }

            if (typeof singleSubscription.when === "string") {
              if (mutationKeysLookup.has(singleSubscription.when)) {
                singleSubscription.run(_objectSpread2({
                  currentResults: currentResults(),
                  refreshActiveQueries: refreshActiveQueries
                }, rest), resp, variables);
              }
            } else if (_typeof(singleSubscription.when) === "object" && singleSubscription.when.test) {
              if (_toConsumableArray(mutationKeysLookup).some(function (k) {
                return singleSubscription.when.test(k);
              })) {
                singleSubscription.run(_objectSpread2({
                  currentResults: currentResults(),
                  refreshActiveQueries: refreshActiveQueries
                }, rest), resp, variables);
              }
            }
          });
        });

        return resp;
      });
    }
  }, {
    key: "runMutation",
    value: function runMutation(mutation, variables) {
      var _ref3 = this.fetchOptions || {},
          _ref3$headers = _ref3.headers,
          headers = _ref3$headers === void 0 ? {} : _ref3$headers,
          otherOptions = _objectWithoutProperties(_ref3, ["headers"]);

      return fetch(this.endpoint, _objectSpread2(_objectSpread2({
        method: "post",
        headers: _objectSpread2({
          Accept: "application/json",
          "Content-Type": "application/json"
        }, headers)
      }, otherOptions), {}, {
        body: JSON.stringify({
          query: mutation,
          variables: variables
        })
      })).then(function (resp) {
        return resp.json();
      }).then(function (resp) {
        return resp.data;
      });
    }
  }, {
    key: "cacheSizeToUse",
    get: function get() {
      return this.cacheSize > 0 ? this.cacheSize : DEFAULT_CACHE_SIZE;
    }
  }]);

  return Client;
}();

var DefaultClientManager = function DefaultClientManager() {
  var _this6 = this;

  _classCallCheck(this, DefaultClientManager);

  _defineProperty(this, "defaultClient", null);

  _defineProperty(this, "setDefaultClient", function (client) {
    return _this6.defaultClient = client;
  });

  _defineProperty(this, "getDefaultClient", function () {
    return _this6.defaultClient;
  });
};

var defaultClientManager = new DefaultClientManager();

function compress(strings) {
  for (var _len = arguments.length, expressions = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
    expressions[_key - 1] = arguments[_key];
  }

  return strings.map(function (string, i) {
    var expression = i < expressions.length ? expressions[i] : "";
    return string.replace(/\s+/g, " ").replace(/ ,/g, ",").replace(/, /g, ",").replace(/ :/g, ":").replace(/: /g, ":").replace(/{ /g, "{").replace(/} /g, "}").replace(/ {/g, "{").replace(/ }/g, "}").replace(/ \(/g, "(").replace(/ \)/g, ")").replace(/\( /g, "(").replace(/\) /g, ")") + expression;
  }).join("").trim();
}

var QueryManager = /*#__PURE__*/function () {
  function QueryManager(_ref) {
    var client = _ref.client,
        refreshCurrent = _ref.refreshCurrent,
        hookRefs = _ref.hookRefs,
        cache = _ref.cache,
        setState = _ref.setState,
        suspense = _ref.suspense;

    _classCallCheck(this, QueryManager);

    var isActiveRef = hookRefs.isActiveRef,
        queryStateRef = hookRefs.queryStateRef;
    Object.assign(this, {
      client: client,
      cache: cache,
      isActiveRef: isActiveRef,
      queryStateRef: queryStateRef,
      refreshCurrent: refreshCurrent,
      suspense: suspense,
      setState: setState
    });
    this.trackedPromises = new Set([]);
  }

  _createClass(QueryManager, [{
    key: "updateState",
    value: function updateState(newState, existingState) {
      if (!this.setState) {
        return;
      }

      if (existingState) {
        var doUpdate = Object.keys(newState).some(function (k) {
          return newState[k] !== existingState[k];
        });
        if (!doUpdate) return;
      }

      this.setState(function (state) {
        return Object.assign({}, state, newState);
      });
    }
  }, {
    key: "sync",
    value: function sync(_ref2) {
      var _this = this;

      var query = _ref2.query,
          variables = _ref2.variables,
          queryState = _ref2.queryState;
      var firstRun = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var graphqlQuery = this.client.getGraphqlQuery({
        query: query,
        variables: variables
      });
      this.cache.getFromCache(graphqlQuery, function (promise) {
        _this.promisePending(promise, queryState);
      }, function (cachedEntry) {
        _this.updateState({
          data: cachedEntry.data,
          error: cachedEntry.error || null,
          loading: false,
          loaded: true,
          currentQuery: graphqlQuery
        }, queryState);
      }, function () {
        var promise = _this.execute(graphqlQuery);

        _this.trackedPromises.add(promise);

        _this.promisePending(promise, queryState);
      }, firstRun);
    }
  }, {
    key: "refresh",
    value: function refresh() {
      this.refreshCurrent && this.refreshCurrent();
    }
  }, {
    key: "promisePending",
    value: function promisePending(promise, queryState) {
      var _this2 = this;

      if (this.suspense) {
        throw promise;
      } else {
        this.updateState({
          loading: true
        }, queryState);

        if (!this.trackedPromises.has(promise)) {
          this.trackedPromises.add(promise);
          promise.then(function () {
            return _this2.refresh();
          }).catch(function () {
            return _this2.refresh();
          });
        }
      }
    }
  }, {
    key: "execute",
    value: function execute(graphqlQuery) {
      var _this3 = this;

      var promise = this.client.runUri(graphqlQuery);
      this.cache.setPendingResult(graphqlQuery, promise);
      return Promise.resolve(promise).then(function (resp) {
        _this3.trackedPromises.delete(promise);

        _this3.cache.setResults(promise, graphqlQuery, resp);

        _this3.refresh();
      }).catch(function (err) {
        _this3.trackedPromises.delete(promise);

        _this3.cache.setResults(promise, graphqlQuery, null, err);

        _this3.refresh();
      });
    }
  }]);

  return QueryManager;
}();

var useState = React.useState,
    useRef = React.useRef,
    useLayoutEffect = React.useLayoutEffect;
var initialState = {
  loading: false,
  loaded: false,
  currentQuery: null,
  data: null,
  error: null
};
function useQuery(query, variables) {
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

  var _ref = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {},
      suspense = _ref.suspense;

  var _useState = useState(0),
      _useState2 = _slicedToArray(_useState, 2),
      deactivateQueryToken = _useState2[0],
      setDeactivateQueryToken = _useState2[1];

  var refresh = function refresh() {
    setDeactivateQueryToken(function (x) {
      return x + 1;
    });
  };

  var clientRef = useRef(options.client || defaultClientManager.getDefaultClient());
  var cacheRef = useRef(clientRef.current.getCache(query) || clientRef.current.newCacheForQuery(query));
  var isActive = !("active" in options && !options.active);
  var isActiveRef = useRef(isActive);

  var _useState3 = useState(function () {
    var existingState = {};

    if (isActiveRef.current) {
      var graphqlQuery = clientRef.current.getGraphqlQuery({
        query: query,
        variables: variables
      });
      cacheRef.current.getFromCache(graphqlQuery, function (promise) {}, function (cachedEntry) {
        existingState = {
          data: cachedEntry.data,
          error: cachedEntry.error || null,
          loading: false,
          loaded: true,
          currentQuery: graphqlQuery
        };
      }, void 0, true);
    }

    return _objectSpread2(_objectSpread2({}, initialState), existingState);
  }),
      _useState4 = _slicedToArray(_useState3, 2),
      queryState = _useState4[0],
      setQueryState = _useState4[1];

  var queryStateRef = useRef(queryState);

  var getQueryManager = function getQueryManager(cache) {
    return new QueryManager({
      client: clientRef.current,
      cache: cache,
      hookRefs: {
        isActiveRef: isActiveRef,
        queryStateRef: queryStateRef
      },
      setState: setQueryState,
      refreshCurrent: null,
      suspense: suspense
    });
  };

  var _useState5 = useState(function () {
    return getQueryManager(cacheRef.current);
  }),
      _useState6 = _slicedToArray(_useState5, 2),
      queryManager = _useState6[0],
      setQueryManager = _useState6[1];

  var resetQueryManager = function resetQueryManager(cacheFilter) {
    var newCache = cacheRef.current.clone(cacheFilter);
    clientRef.current.setCache(query, newCache);
    setQueryManager(getQueryManager(newCache));
  };

  var reload = function reload() {
    return resetQueryManager(function (_ref2) {
      var _ref3 = _slicedToArray(_ref2, 1),
          k = _ref3[0];

      return k != queryStateRef.current.currentQuery;
    });
  };

  var hardReset = function hardReset() {
    return resetQueryManager(function () {
      return false;
    });
  };

  var softReset = function softReset(newResults) {
    if (!newResults) {
      newResults = queryStateRef.current.data;
    }

    cacheRef.current.clearCache();
    cacheRef.current.softResetCache = _defineProperty({}, queryStateRef.current.currentQuery, {
      data: newResults
    });
    setQueryState(function (oldState) {
      return _objectSpread2(_objectSpread2({}, oldState), {}, {
        data: newResults
      });
    });
  }; // ------------------------------- effects -------------------------------


  useLayoutEffect(function () {
    isActiveRef.current = isActive;
    queryStateRef.current = queryState;
  }, [isActive, queryState]);
  useLayoutEffect(function () {
    var unregisterQuery = clientRef.current.registerQuery(query, refresh);

    if (!suspense) {
      queryManager.refreshCurrent = refresh;
      refresh();
    }

    var mutationSubscription;

    if (_typeof(options.onMutation) === "object") {
      var onMutation = !Array.isArray(options.onMutation) ? [options.onMutation] : options.onMutation;
      mutationSubscription = clientRef.current.subscribeMutation(onMutation, {
        cache: cacheRef.current,
        softReset: softReset,
        hardReset: hardReset,
        refresh: refresh,
        currentResults: function currentResults() {
          return queryStateRef.current.data;
        },
        isActive: function isActive() {
          return isActiveRef.current;
        }
      });
    }

    cacheRef.current = queryManager.cache;
    return function () {
      queryManager.setState = function () {};

      queryManager.refreshCurrent = function () {};

      mutationSubscription && mutationSubscription();
      unregisterQuery();
    };
  }, [queryManager]); // ------------------------------- effects -------------------------------

  var firstRun = useRef(true);
  useLayoutEffect(function () {
    firstRun.current = false;
  }, []);

  if (isActive) {
    queryManager.sync({
      query: query,
      variables: variables,
      queryState: queryState
    }, firstRun.current);
  }

  return useMemo$1(function () {
    return _objectSpread2(_objectSpread2({}, queryState), {}, {
      reload: reload,
      clearCache: function clearCache() {
        return cacheRef.current.clearCache();
      },
      clearCacheAndReload: hardReset,
      softReset: softReset
    });
  }, [queryState]);
}
var useSuspenseQuery = function useSuspenseQuery(query, variables) {
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  return useQuery(query, variables, options, {
    suspense: true
  });
};

var MutationManager = function MutationManager(_ref, mutation, options) {
  var _this = this;

  var client = _ref.client,
      setState = _ref.setState;

  _classCallCheck(this, MutationManager);

  _defineProperty(this, "runMutation", function (variables) {
    _this.setState({
      running: true,
      finished: false,
      runMutation: _this.runMutation
    });

    return _this.client.processMutation(_this.mutation, variables).then(function (resp) {
      _this.setState({
        running: false,
        finished: true,
        runMutation: _this.runMutation
      });

      return resp;
    });
  });

  _defineProperty(this, "currentState", _objectSpread2(_objectSpread2({}, MutationManager.initialState), {}, {
    runMutation: this.runMutation
  }));

  this.client = client;
  this.setState = setState;
  this.mutation = mutation;
  this.setState(this.currentState);
};

_defineProperty(MutationManager, "initialState", {
  running: false,
  finished: false
});

var useState$1 = React.useState,
    useRef$1 = React.useRef,
    useMemo = React.useMemo,
    useLayoutEffect$1 = React.useLayoutEffect;
function useMutation(mutation) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  var _useState = useState$1(null),
      _useState2 = _slicedToArray(_useState, 2),
      mutationState = _useState2[0],
      setMutationState = _useState2[1];

  var client = options.client || defaultClientManager.getDefaultClient();

  var _useState3 = useState$1(function () {
    return new MutationManager({
      client: client,
      setState: setMutationState
    }, mutation, options);
  }),
      _useState4 = _slicedToArray(_useState3, 1),
      mutationManager = _useState4[0];

  useLayoutEffect$1(function () {
    return function () {
      return mutationManager.setState = function () {};
    };
  }, []);
  return mutationState || mutationManager.currentState;
}

var setDefaultClient = defaultClientManager.setDefaultClient,
    getDefaultClient = defaultClientManager.getDefaultClient;

export { Cache, Client, compress, getDefaultClient, setDefaultClient, useMutation, useQuery, useSuspenseQuery };
