UNPKG

@vue/apollo-option

Version:

Use Apollo and GraphQL with Vue.js using the `apollo` option

1,370 lines (1,334 loc) 54.7 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global['vue-apollo'] = {})); }(this, (function (exports) { 'use strict'; function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _get() { return _get = "undefined" != typeof Reflect && Reflect.get ? Reflect.get.bind() : function (e, t, r) { var p = _superPropBase(e, t); if (p) { var n = Object.getOwnPropertyDescriptor(p, t); return n.get ? n.get.call(arguments.length < 3 ? e : r) : n.value; } }, _get.apply(null, arguments); } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } 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 _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 ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _superPropBase(t, o) { for (; !{}.hasOwnProperty.call(t, o) && null !== (t = _getPrototypeOf(t));); return t; } function _superPropGet(t, o, e, r) { var p = _get(_getPrototypeOf(1 & r ? t.prototype : t), o, e); return 2 & r && "function" == typeof p ? function (t) { return p.apply(e, t); } : p; } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } /* eslint-disable no-undefined,no-param-reassign,no-shadow */ /** * Throttle execution of a function. Especially useful for rate limiting * execution of handlers on events like resize and scroll. * * @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) * are most useful. * @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, * as-is, to `callback` when the throttled-function is executed. * @param {object} [options] - An object to configure options. * @param {boolean} [options.noTrailing] - Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds * while the throttled-function is being called. If noTrailing is false or unspecified, callback will be executed * one final time after the last throttled-function call. (After the throttled-function has not been called for * `delay` milliseconds, the internal counter is reset). * @param {boolean} [options.noLeading] - Optional, defaults to false. If noLeading is false, the first throttled-function call will execute callback * immediately. If noLeading is true, the first the callback execution will be skipped. It should be noted that * callback will never executed if both noLeading = true and noTrailing = true. * @param {boolean} [options.debounceMode] - If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is * false (at end), schedule `callback` to execute after `delay` ms. * * @returns {Function} A new, throttled, function. */ function throttle(delay, callback, options) { var _ref = options || {}, _ref$noTrailing = _ref.noTrailing, noTrailing = _ref$noTrailing === void 0 ? false : _ref$noTrailing, _ref$noLeading = _ref.noLeading, noLeading = _ref$noLeading === void 0 ? false : _ref$noLeading, _ref$debounceMode = _ref.debounceMode, debounceMode = _ref$debounceMode === void 0 ? undefined : _ref$debounceMode; /* * After wrapper has stopped being called, this timeout ensures that * `callback` is executed at the proper times in `throttle` and `end` * debounce modes. */ var timeoutID; var cancelled = false; // Keep track of the last time `callback` was executed. var lastExec = 0; // Function to clear existing timeout function clearExistingTimeout() { if (timeoutID) { clearTimeout(timeoutID); } } // Function to cancel next exec function cancel(options) { var _ref2 = options || {}, _ref2$upcomingOnly = _ref2.upcomingOnly, upcomingOnly = _ref2$upcomingOnly === void 0 ? false : _ref2$upcomingOnly; clearExistingTimeout(); cancelled = !upcomingOnly; } /* * The `wrapper` function encapsulates all of the throttling / debouncing * functionality and when executed will limit the rate at which `callback` * is executed. */ function wrapper() { for (var _len = arguments.length, arguments_ = new Array(_len), _key = 0; _key < _len; _key++) { arguments_[_key] = arguments[_key]; } var self = this; var elapsed = Date.now() - lastExec; if (cancelled) { return; } // Execute `callback` and update the `lastExec` timestamp. function exec() { lastExec = Date.now(); callback.apply(self, arguments_); } /* * If `debounceMode` is true (at begin) this is used to clear the flag * to allow future `callback` executions. */ function clear() { timeoutID = undefined; } if (!noLeading && debounceMode && !timeoutID) { /* * Since `wrapper` is being called for the first time and * `debounceMode` is true (at begin), execute `callback` * and noLeading != true. */ exec(); } clearExistingTimeout(); if (debounceMode === undefined && elapsed > delay) { if (noLeading) { /* * In throttle mode with noLeading, if `delay` time has * been exceeded, update `lastExec` and schedule `callback` * to execute after `delay` ms. */ lastExec = Date.now(); if (!noTrailing) { timeoutID = setTimeout(debounceMode ? clear : exec, delay); } } else { /* * In throttle mode without noLeading, if `delay` time has been exceeded, execute * `callback`. */ exec(); } } else if (noTrailing !== true) { /* * In trailing throttle mode, since `delay` time has not been * exceeded, schedule `callback` to execute `delay` ms after most * recent execution. * * If `debounceMode` is true (at begin), schedule `clear` to execute * after `delay` ms. * * If `debounceMode` is false (at end), schedule `callback` to * execute after `delay` ms. */ timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay); } } wrapper.cancel = cancel; // Return the wrapper function. return wrapper; } /* eslint-disable no-undefined */ /** * Debounce execution of a function. Debouncing, unlike throttling, * guarantees that a function is only executed a single time, either at the * very beginning of a series of calls, or at the very end. * * @param {number} delay - A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. * @param {Function} callback - A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is, * to `callback` when the debounced-function is executed. * @param {object} [options] - An object to configure options. * @param {boolean} [options.atBegin] - Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed `delay` milliseconds * after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call. * (After the throttled-function has not been called for `delay` milliseconds, the internal counter is reset). * * @returns {Function} A new, debounced function. */ function debounce(delay, callback, options) { var _ref = options || {}, _ref$atBegin = _ref.atBegin, atBegin = _ref$atBegin === void 0 ? false : _ref$atBegin; return throttle(delay, callback, { debounceMode: atBegin !== false }); } var esm = /*#__PURE__*/Object.freeze({ __proto__: null, debounce: debounce, throttle: throttle }); function factory(action) { return function (cb, time) { return action(time, cb); }; } var throttle$1 = factory(esm.throttle); var debounce$1 = factory(esm.debounce); var reapply = function reapply(options, context) { while (typeof options === 'function') { options = options.call(context); } return options; }; var omit = function omit(obj, properties) { return Object.entries(obj).filter(function (_ref) { var _ref2 = _slicedToArray(_ref, 1), key = _ref2[0]; return !properties.includes(key); }).reduce(function (c, _ref3) { var _ref4 = _slicedToArray(_ref3, 2), key = _ref4[0], val = _ref4[1]; c[key] = val; return c; }, {}); }; var addGqlError = function addGqlError(error) { if (error.graphQLErrors && error.graphQLErrors.length) { error.gqlError = error.graphQLErrors[0]; } }; var isServer = typeof window === 'undefined'; var VUE_APOLLO_QUERY_KEYWORDS = ['variables', 'watch', 'update', 'result', 'error', 'loadingKey', 'watchLoading', 'skip', 'throttle', 'debounce', 'subscribeToMore', 'prefetch', 'manual']; var skippAllKeys = { query: '_skipAllQueries', subscription: '_skipAllSubscriptions' }; var SmartApollo = /*#__PURE__*/function () { function SmartApollo(vm, key, options) { _classCallCheck(this, SmartApollo); // eslint-disable-next-line no-undef _defineProperty(this, "type", null); // eslint-disable-next-line no-undef _defineProperty(this, "vueApolloSpecialKeys", []); this.vm = vm; this.key = key; this.initialOptions = options; this.options = Object.assign({}, options); this._skip = false; this._pollInterval = null; this._watchers = []; this._destroyed = false; this.lastApolloOptions = null; } return _createClass(SmartApollo, [{ key: "autostart", value: function autostart() { var _this = this; if (typeof this.options.skip === 'function') { this._skipWatcher = this.vm.$watch(function () { return _this.options.skip.call(_this.vm, _this.vm, _this.key); }, this.skipChanged.bind(this), { immediate: true, deep: this.options.deep }); } else if (!this.options.skip && !this.allSkip) { this.start(); } else { this._skip = true; } if (typeof this.options.pollInterval === 'function') { this._pollWatcher = this.vm.$watch(this.options.pollInterval.bind(this.vm), this.pollIntervalChanged.bind(this), { immediate: true }); } } }, { key: "pollIntervalChanged", value: function pollIntervalChanged(value, oldValue) { if (value !== oldValue) { this.pollInterval = value; if (value == null) { this.stopPolling(); } else { this.startPolling(value); } } } }, { key: "skipChanged", value: function skipChanged(value, oldValue) { if (value !== oldValue) { this.skip = value; } } }, { key: "pollInterval", get: function get() { return this._pollInterval; }, set: function set(value) { this._pollInterval = value; } }, { key: "skip", get: function get() { return this._skip; }, set: function set(value) { if (value || this.allSkip) { this.stop(); } else { this.start(); } this._skip = value; } }, { key: "allSkip", get: function get() { return this.vm.$apollo[skippAllKeys[this.type]]; } }, { key: "refresh", value: function refresh() { if (!this._skip) { this.stop(); this.start(); } } }, { key: "start", value: function start() { var _this2 = this; this.starting = true; // Reactive options var _loop = function _loop() { var prop = _ref2[_i2]; if (typeof _this2.initialOptions[prop] === 'function') { var queryCb = _this2.initialOptions[prop].bind(_this2.vm); _this2.options[prop] = queryCb(); var cb = function cb(query) { if (_this2._destroyed) return; _this2.options[prop] = query; _this2.refresh(); }; if (!isServer) { cb = _this2.options.throttle ? throttle$1(cb, _this2.options.throttle) : cb; cb = _this2.options.debounce ? debounce$1(cb, _this2.options.debounce) : cb; } _this2._watchers.push(_this2.vm.$watch(queryCb, cb, { deep: _this2.options.deep })); } }; for (var _i2 = 0, _ref2 = ['query', 'document', 'context']; _i2 < _ref2.length; _i2++) { _loop(); } // GraphQL Variables if (typeof this.options.variables === 'function') { var cb = this.executeApollo.bind(this); if (!isServer) { cb = this.options.throttle ? throttle$1(cb, this.options.throttle) : cb; cb = this.options.debounce ? debounce$1(cb, this.options.debounce) : cb; } this._watchers.push(this.vm.$watch(function () { return typeof _this2.options.variables === 'function' ? _this2.options.variables.call(_this2.vm) : _this2.options.variables; }, cb, { immediate: true, deep: this.options.deep })); } else { this.executeApollo(this.options.variables); } } }, { key: "stop", value: function stop() { for (var _i4 = 0, _this$_watchers2 = this._watchers; _i4 < _this$_watchers2.length; _i4++) { var unwatch = _this$_watchers2[_i4]; unwatch(); } if (this.sub) { this.sub.unsubscribe(); this.sub = null; } } }, { key: "generateApolloOptions", value: function generateApolloOptions(variables) { var apolloOptions = omit(this.options, this.vueApolloSpecialKeys); apolloOptions.variables = variables; this.lastApolloOptions = apolloOptions; return apolloOptions; } }, { key: "executeApollo", value: function executeApollo(variables) { this.starting = false; } }, { key: "nextResult", value: function nextResult(result) { var error = result.error; if (error) addGqlError(error); } }, { key: "callHandlers", value: function callHandlers(handlers) { var catched = false; for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; } for (var _i6 = 0; _i6 < handlers.length; _i6++) { var handler = handlers[_i6]; if (handler) { catched = true; var result = handler.apply(this.vm, args); if (typeof result !== 'undefined' && !result) { break; } } } return catched; } }, { key: "errorHandler", value: function errorHandler() { for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } return this.callHandlers.apply(this, [[this.options.error, this.vm.$apollo.error, this.vm.$apollo.provider.errorHandler]].concat(args)); } }, { key: "catchError", value: function catchError(error) { addGqlError(error); var catched = this.errorHandler(error, this.vm, this.key, this.type, this.lastApolloOptions); if (catched) return; if (error.graphQLErrors && error.graphQLErrors.length !== 0) { console.error("GraphQL execution errors for ".concat(this.type, " '").concat(this.key, "'")); for (var _i8 = 0, _error$graphQLErrors2 = error.graphQLErrors; _i8 < _error$graphQLErrors2.length; _i8++) { var e = _error$graphQLErrors2[_i8]; console.error(e); } } else if (error.networkError) { console.error("Error sending the ".concat(this.type, " '").concat(this.key, "'"), error.networkError); } else { console.error("[vue-apollo] An error has occurred for ".concat(this.type, " '").concat(this.key, "'")); if (Array.isArray(error)) { var _console; (_console = console).error.apply(_console, _toConsumableArray(error)); } else { console.error(error); } } } }, { key: "destroy", value: function destroy() { if (this._destroyed) return; this._destroyed = true; this.stop(); if (this._skipWatcher) { this._skipWatcher(); } } }]); }(); var SmartQuery = /*#__PURE__*/function (_SmartApollo) { // @ts-ignore function SmartQuery(vm, key, options) { var _this; var autostart = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; _classCallCheck(this, SmartQuery); // Add reactive data related to the query if (vm.$data.$apolloData && !vm.$data.$apolloData.queries[key]) { vm.$data.$apolloData.queries[key] = { loading: false }; } _this = _callSuper(this, SmartQuery, [vm, key, options]); // eslint-disable-next-line no-undef _defineProperty(_this, "type", 'query'); // eslint-disable-next-line no-undef _defineProperty(_this, "vueApolloSpecialKeys", VUE_APOLLO_QUERY_KEYWORDS); // eslint-disable-next-line no-undef _defineProperty(_this, "_loading", false); // eslint-disable-next-line no-undef _defineProperty(_this, "_linkedSubscriptions", []); if (isServer) { _this.firstRun = new Promise(function (resolve, reject) { _this._firstRunResolve = resolve; _this._firstRunReject = reject; }); } if (isServer) { _this.options.fetchPolicy = 'network-only'; } if (!options.manual) { _this.hasDataField = Object.prototype.hasOwnProperty.call(_this.vm.$data, key); if (_this.hasDataField) { Object.defineProperty(_this.vm.$data.$apolloData.data, key, { get: function get() { return _this.vm.$data[key]; }, enumerable: true, configurable: true }); } else { Object.defineProperty(_this.vm.$data, key, { get: function get() { return _this.vm.$data.$apolloData.data[key]; }, enumerable: true, configurable: true }); } } if (autostart) { _this.autostart(); } return _this; } _inherits(SmartQuery, _SmartApollo); return _createClass(SmartQuery, [{ key: "client", get: function get() { return this.vm.$apollo.getClient(this.options); } }, { key: "loading", get: function get() { return this.vm.$data.$apolloData && this.vm.$data.$apolloData.queries[this.key] ? this.vm.$data.$apolloData.queries[this.key].loading : this._loading; }, set: function set(value) { if (this._loading !== value) { this._loading = value; if (this.vm.$data.$apolloData && this.vm.$data.$apolloData.queries[this.key]) { this.vm.$data.$apolloData.queries[this.key].loading = value; this.vm.$data.$apolloData.loading += value ? 1 : -1; } } } }, { key: "stop", value: function stop() { _superPropGet(SmartQuery, "stop", this, 3)([]); this.loadingDone(); if (this.observer) { this.observer.stopPolling(); this.observer = null; } } }, { key: "generateApolloOptions", value: function generateApolloOptions(variables) { var apolloOptions = _superPropGet(SmartQuery, "generateApolloOptions", this, 3)([variables]); if (this.vm.$isServer) { // Don't poll on the server, that would run indefinitely delete apolloOptions.pollInterval; } return apolloOptions; } }, { key: "executeApollo", value: function executeApollo(variables) { if (this._destroyed) return; var variablesJson = JSON.stringify(variables); if (this.sub) { if (variablesJson === this.previousVariablesJson) { return; } this.sub.unsubscribe(); // Subscribe to more subs for (var _i2 = 0, _this$_linkedSubscrip2 = this._linkedSubscriptions; _i2 < _this$_linkedSubscrip2.length; _i2++) { var sub = _this$_linkedSubscrip2[_i2]; sub.stop(); } } this.previousVariablesJson = variablesJson; // Create observer this.observer = this.vm.$apollo.watchQuery(this.generateApolloOptions(variables)); this.startQuerySubscription(); if (this.options.fetchPolicy !== 'no-cache' || this.options.notifyOnNetworkStatusChange) { var currentResult = this.retrieveCurrentResult(); if (this.options.notifyOnNetworkStatusChange // Initial call of next result when it's not loading (for Apollo Client 3) || this.observer.getCurrentResult && !currentResult.loading) { this.nextResult(currentResult); } } _superPropGet(SmartQuery, "executeApollo", this, 3)([variables]); // Subscribe to more subs for (var _i4 = 0, _this$_linkedSubscrip4 = this._linkedSubscriptions; _i4 < _this$_linkedSubscrip4.length; _i4++) { var _sub = _this$_linkedSubscrip4[_i4]; _sub.start(); } } }, { key: "startQuerySubscription", value: function startQuerySubscription() { if (this.sub && !this.sub.closed) return; // Create subscription this.sub = this.observer.subscribe({ next: this.nextResult.bind(this), error: this.catchError.bind(this) }); } /** * May update loading state */ }, { key: "retrieveCurrentResult", value: function retrieveCurrentResult() { var force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; var currentResult = this.observer.getCurrentResult ? this.observer.getCurrentResult() : this.observer.currentResult(); if (force || currentResult.loading) { if (!this.loading) { this.applyLoadingModifier(1); } this.loading = true; } return currentResult; } }, { key: "nextResult", value: function nextResult(result) { _superPropGet(SmartQuery, "nextResult", this, 3)([result]); var data = result.data, loading = result.loading, error = result.error, errors = result.errors; var anyErrors = errors && errors.length; if (error || anyErrors) { this.firstRunReject(error); } if (!loading) { this.loadingDone(); } // If `errorPolicy` is set to `all`, an error won't be thrown // Instead result will have an `errors` array of GraphQL Errors // so we need to reconstruct an error object similar to the normal one if (!error && anyErrors) { var e = new Error("GraphQL error: ".concat(errors.map(function (e) { return e.message; }).join(' | '))); Object.assign(e, { graphQLErrors: errors, networkError: null }); // We skip query catchError logic // as we only want to dispatch the error _superPropGet(SmartQuery, "catchError", this, 3)([e]); } if (this.observer.options.errorPolicy === 'none' && (error || anyErrors)) { // Don't apply result return; } var hasResultCallback = typeof this.options.result === 'function'; if (data == null) ; else if (!this.options.manual) { if (typeof this.options.update === 'function') { this.setData(this.options.update.call(this.vm, data)); } else if (typeof data[this.key] === 'undefined' && Object.keys(data).length) { console.error("Missing ".concat(this.key, " attribute on result"), data); } else { this.setData(data[this.key]); } } else if (!hasResultCallback) { console.error("".concat(this.key, " query must have a 'result' hook in manual mode")); } if (hasResultCallback) { this.options.result.call(this.vm, result, this.key); } } }, { key: "setData", value: function setData(value) { var target = this.hasDataField ? this.vm.$data : this.vm.$data.$apolloData.data; target[this.key] = value; } }, { key: "catchError", value: function catchError(error) { _superPropGet(SmartQuery, "catchError", this, 3)([error]); this.firstRunReject(error); this.loadingDone(error); this.nextResult(this.observer.getCurrentResult ? this.observer.getCurrentResult() : this.observer.currentResult()); // The observable closes the sub if an error occurs this.resubscribeToQuery(); } }, { key: "resubscribeToQuery", value: function resubscribeToQuery() { var lastError = this.observer.getLastError(); var lastResult = this.observer.getLastResult(); this.observer.resetLastResults(); this.startQuerySubscription(); Object.assign(this.observer, { lastError: lastError, lastResult: lastResult }); } }, { key: "loadingKey", get: function get() { return this.options.loadingKey || this.vm.$apollo.loadingKey; } }, { key: "watchLoading", value: function watchLoading() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return this.callHandlers.apply(this, [[this.options.watchLoading, this.vm.$apollo.watchLoading, this.vm.$apollo.provider.watchLoading]].concat(args, [this])); } }, { key: "applyLoadingModifier", value: function applyLoadingModifier(value) { var loadingKey = this.loadingKey; if (loadingKey && typeof this.vm[loadingKey] === 'number') { this.vm[loadingKey] += value; } this.watchLoading(value === 1, value); } }, { key: "loadingDone", value: function loadingDone() { var error = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; if (this.loading) { this.applyLoadingModifier(-1); } this.loading = false; if (!error) { this.firstRunResolve(); } } }, { key: "fetchMore", value: function fetchMore() { var _this2 = this; if (this.observer) { var _this$observer; this.retrieveCurrentResult(true); return (_this$observer = this.observer).fetchMore.apply(_this$observer, arguments).then(function (result) { if (!result.loading) { _this2.loadingDone(); } return result; }); } } }, { key: "subscribeToMore", value: function subscribeToMore() { if (this.observer) { var _this$observer2; return { unsubscribe: (_this$observer2 = this.observer).subscribeToMore.apply(_this$observer2, arguments) }; } } }, { key: "refetch", value: function refetch(variables) { var _this3 = this; variables && (this.options.variables = variables); if (this.observer) { var result = this.observer.refetch(variables).then(function (result) { if (!result.loading) { _this3.loadingDone(); } return result; }); this.retrieveCurrentResult(); return result; } } }, { key: "setVariables", value: function setVariables(variables, tryFetch) { this.options.variables = variables; if (this.observer) { var result = this.observer.setVariables(variables, tryFetch); this.retrieveCurrentResult(); return result; } } }, { key: "setOptions", value: function setOptions(options) { Object.assign(this.options, options); if (this.observer) { var result = this.observer.setOptions(options); this.retrieveCurrentResult(); return result; } } }, { key: "startPolling", value: function startPolling() { if (this.observer) { var _this$observer3; return (_this$observer3 = this.observer).startPolling.apply(_this$observer3, arguments); } } }, { key: "stopPolling", value: function stopPolling() { if (this.observer) { var _this$observer4; return (_this$observer4 = this.observer).stopPolling.apply(_this$observer4, arguments); } } }, { key: "firstRunResolve", value: function firstRunResolve() { if (this._firstRunResolve) { this._firstRunResolve(); this._firstRunResolve = null; } } }, { key: "firstRunReject", value: function firstRunReject(error) { if (this._firstRunReject) { this._firstRunReject(error); this._firstRunReject = null; } } }, { key: "destroy", value: function destroy() { _superPropGet(SmartQuery, "destroy", this, 3)([]); if (this.loading) { this.watchLoading(false, -1); } this.loading = false; } }]); }(SmartApollo); var MAX_RETRIES = 5; var DELAY_MS = 500; var SmartSubscription = /*#__PURE__*/function (_SmartApollo) { function SmartSubscription(vm, key, options) { var _this; var autostart = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; _classCallCheck(this, SmartSubscription); _this = _callSuper(this, SmartSubscription, [vm, key, options]); // eslint-disable-next-line no-undef _defineProperty(_this, "type", 'subscription'); // eslint-disable-next-line no-undef _defineProperty(_this, "vueApolloSpecialKeys", ['variables', 'result', 'error', 'throttle', 'debounce', 'linkedQuery']); _this.attempts = 0; if (autostart) { _this.autostart(); } return _this; } _inherits(SmartSubscription, _SmartApollo); return _createClass(SmartSubscription, [{ key: "generateApolloOptions", value: function generateApolloOptions(variables) { var apolloOptions = _superPropGet(SmartSubscription, "generateApolloOptions", this, 3)([variables]); apolloOptions.onError = this.catchError.bind(this); return apolloOptions; } }, { key: "executeApollo", value: function executeApollo(variables) { if (this._destroyed) return; var variablesJson = JSON.stringify(variables); if (this.sub) { // do nothing if subscription is already running using exactly the same variables if (variablesJson === this.previousVariablesJson) { return; } this.sub.unsubscribe(); } this.previousVariablesJson = variablesJson; var apolloOptions = this.generateApolloOptions(variables); if (typeof apolloOptions.updateQuery === 'function') { apolloOptions.updateQuery = apolloOptions.updateQuery.bind(this.vm); } if (this.options.linkedQuery) { if (typeof this.options.result === 'function') { var rcb = this.options.result.bind(this.vm); var ucb = apolloOptions.updateQuery && apolloOptions.updateQuery.bind(this.vm); apolloOptions.updateQuery = function () { rcb.apply(void 0, arguments); return ucb && ucb.apply(void 0, arguments); }; } this.sub = this.options.linkedQuery.subscribeToMore(apolloOptions); } else { // Create observer this.observer = this.vm.$apollo.subscribe(apolloOptions); // Create subscription this.sub = this.observer.subscribe({ next: this.nextResult.bind(this), error: this.catchError.bind(this) }); } _superPropGet(SmartSubscription, "executeApollo", this, 3)([variables]); } }, { key: "nextResult", value: function nextResult(data) { _superPropGet(SmartSubscription, "nextResult", this, 3)([data]); this.attempts = 0; if (typeof this.options.result === 'function') { this.options.result.call(this.vm, data, this.key); } } }, { key: "catchError", value: function catchError(error) { _superPropGet(SmartSubscription, "catchError", this, 3)([error]); // Restart the subscription if (this.skip || this.attempts >= MAX_RETRIES) { return; } this.stop(); // Restart the subscription with exponential backoff this.retryTimeout = setTimeout(this.start.bind(this), Math.pow(2, this.attempts) * DELAY_MS); this.attempts++; } }, { key: "stop", value: function stop() { _superPropGet(SmartSubscription, "stop", this, 3)([]); clearTimeout(this.retryTimeout); } }]); }(SmartApollo); var DollarApollo = /*#__PURE__*/function () { function DollarApollo(vm, provider) { _classCallCheck(this, DollarApollo); this._apolloSubscriptions = []; this._watchers = []; this.vm = vm; this.provider = provider; this.queries = {}; this.subscriptions = {}; this.client = undefined; this.loadingKey = undefined; this.error = undefined; } return _createClass(DollarApollo, [{ key: "getClient", value: function getClient() { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; if (!options || !options.client) { if (_typeof(this.client) === 'object') { return this.client; } if (this.client) { if (!this.provider.clients) { throw new Error("[vue-apollo] Missing 'clients' options in 'apolloProvider'"); } else { var _client = this.provider.clients[this.client]; if (!_client) { throw new Error("[vue-apollo] Missing client '".concat(this.client, "' in 'apolloProvider'")); } return _client; } } return this.provider.defaultClient; } var client = this.provider.clients[options.client]; if (!client) { throw new Error("[vue-apollo] Missing client '".concat(options.client, "' in 'apolloProvider'")); } return client; } }, { key: "query", value: function query(options) { return this.getClient(options).query(options); } }, { key: "watchQuery", value: function watchQuery(options) { var _this = this; var observable = this.getClient(options).watchQuery(options); var _subscribe = observable.subscribe.bind(observable); observable.subscribe = function (options) { var sub = _subscribe(options); _this._apolloSubscriptions.push(sub); return sub; }; return observable; } }, { key: "mutate", value: function mutate(options) { return this.getClient(options).mutate(options); } }, { key: "subscribe", value: function subscribe(options) { var _this2 = this; if (!isServer) { var observable = this.getClient(options).subscribe(options); var _subscribe = observable.subscribe.bind(observable); observable.subscribe = function (options) { var sub = _subscribe(options); _this2._apolloSubscriptions.push(sub); return sub; }; return observable; } } }, { key: "loading", get: function get() { return this.vm.$data.$apolloData.loading !== 0; } }, { key: "data", get: function get() { return this.vm.$data.$apolloData.data; } }, { key: "addSmartQuery", value: function addSmartQuery(key, options) { var _this3 = this; var finalOptions = reapply(options, this.vm); // Simple query if (!finalOptions.query) { var query = finalOptions; finalOptions = { query: query }; } var apollo = this.vm.$options.apollo; var defaultOptions = this.provider.defaultOptions; var $query; if (defaultOptions && defaultOptions.$query) { $query = defaultOptions.$query; } if (apollo && apollo.$query) { $query = _objectSpread2(_objectSpread2({}, $query || {}), apollo.$query); } if ($query) { // Also replaces 'undefined' values for (var _key in $query) { if (typeof finalOptions[_key] === 'undefined') { finalOptions[_key] = $query[_key]; } } } var smart = this.queries[key] = new SmartQuery(this.vm, key, finalOptions, false); if (!isServer || finalOptions.prefetch !== false) { smart.autostart(); } if (!isServer) { var subs = finalOptions.subscribeToMore; if (subs) { if (Array.isArray(subs)) { subs.forEach(function (sub, index) { _this3.addSmartSubscription("".concat(key).concat(index), _objectSpread2(_objectSpread2({}, sub), {}, { linkedQuery: smart })); }); } else { this.addSmartSubscription(key, _objectSpread2(_objectSpread2({}, subs), {}, { linkedQuery: smart })); } } } return smart; } }, { key: "addSmartSubscription", value: function addSmartSubscription(key, options) { if (!isServer) { options = reapply(options, this.vm); var smart = this.subscriptions[key] = new SmartSubscription(this.vm, key, options, false); smart.autostart(); if (options.linkedQuery) { // prevent subscriptions leak on fetching query with another parameters var index = options.linkedQuery._linkedSubscriptions.findIndex(function (x) { return x.key === key; }); if (index !== -1) { options.linkedQuery._linkedSubscriptions[index] = smart; } else { options.linkedQuery._linkedSubscriptions.push(smart); } } return smart; } } }, { key: "defineReactiveSetter", value: function defineReactiveSetter(key, func, deep) { var _this4 = this; this._watchers.push(this.vm.$watch(func, function (value) { _this4[key] = value; }, { immediate: true, deep: deep })); } }, { key: "skipAllQueries", set: function set(value) { this._skipAllQueries = value; for (var key in this.queries) { this.queries[key].skip = value; } } }, { key: "skipAllSubscriptions", set: function set(value) { this._skipAllSubscriptions = value; for (var key in this.subscriptions) { this.subscriptions[key].skip = value; } } }, { key: "skipAll", set: function set(value) { this.skipAllQueries = value; this.skipAllSubscriptions = value; } }, { key: "destroy", value: function destroy() { for (var _i2 = 0, _this$_watchers2 = this._watchers; _i2 < _this$_watchers2.length; _i2++) { var unwatch = _this$_watchers2[_i2]; unwatch(); } for (var key in this.queries) { this.queries[key].destroy(); } for (var _key2 in this.subscriptions) { this.subscriptions[_key2].destroy(); } this._apolloSubscriptions.forEach(function (sub) { sub.unsubscribe(); }); this._apolloSubscriptions = null; this.vm = null; } }]); }(); function hasProperty(holder, key) { return typeof holder !== 'undefined' && Object.prototype.hasOwnProperty.call(holder, key); } function launch() { var _this = this; var apolloProvider = this.$apolloProvider; if (this._apolloLaunched || !apolloProvider) return; this._apolloLaunched = true; // Prepare properties var apollo = this.$options.apollo; if (apollo) { this.$_apolloPromises = []; if (!apollo.$init) { apollo.$init = true; // Default options applied to `apollo` options if (apolloProvider.defaultOptions) { apollo = this.$options.apollo = Object.assign({}, apolloProvider.defaultOptions, apollo); } } defineReactiveSetter(this.$apollo, 'skipAll', apollo.$skipAll, apollo.$deep); defineReactiveSetter(this.$apollo, 'skipAllQueries', apollo.$skipAllQueries, apollo.$deep); defineReactiveSetter(this.$apollo, 'skipAllSubscriptions', apollo.$skipAllSubscriptions, apollo.$deep); defineReactiveSetter(this.$apollo, 'client', apollo.$client, apollo.$deep); defineReactiveSetter(this.$apollo, 'loadingKey', apollo.$loadingKey, apollo.$deep); defineReactiveSetter(this.$apollo, 'error', apollo.$error, apollo.$deep); defineReactiveSetter(this.$apollo, 'watchLoading', apollo.$watchLoading, apollo.$deep); // Apollo Data Object.defineProperty(this, '$apolloData', { get: function get() { return _this.$data.$apolloData; }, enumerable: true, configurable: true }); // watchQuery for (var key in apollo) { if (key.charAt(0) !== '$') { var options = apollo[key]; var smart = this.$apollo.addSmartQuery(key, options); if (isServer) { options = reapply(options, this); if (apolloProvider.prefetch !== false && options.prefetch !== false && apollo