@vue/apollo-components
Version:
Apollo GraphQL components for Vue.js
617 lines (590 loc) • 20 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('graphql-tag'), require('vue')) :
typeof define === 'function' && define.amd ? define(['exports', 'graphql-tag', 'vue'], factory) :
(global = global || self, factory(global['vue-apollo-components'] = {}, global.gql, global.vue));
}(this, (function (exports, gql, vue) { 'use strict';
gql = gql && Object.prototype.hasOwnProperty.call(gql, 'default') ? gql['default'] : gql;
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 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 _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 + "";
}
/* 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 addGqlError = function addGqlError(error) {
if (error.graphQLErrors && error.graphQLErrors.length) {
error.gqlError = error.graphQLErrors[0];
}
};
var CApolloMutation = {
props: {
mutation: {
type: [Function, Object],
required: true
},
variables: {
type: Object,
"default": undefined
},
optimisticResponse: {
type: Object,
"default": undefined
},
update: {
type: Function,
"default": undefined
},
refetchQueries: {
type: Function,
"default": undefined
},
clientId: {
type: String,
"default": undefined
},
tag: {
type: String,
"default": 'div'
},
context: {
type: Object,
"default": undefined
}
},
data: function data() {
return {
loading: false,
error: null
};
},
emits: ['loading', 'done', 'error'],
watch: {
loading: function loading(value) {
this.$emit('loading', value);
}
},
methods: {
mutate: function mutate(options) {
var _this = this;
this.loading = true;
this.error = null;
var mutation = this.mutation;
if (typeof mutation === 'function') {
mutation = mutation(gql);
}
return this.$apollo.mutate(_objectSpread2({
mutation: mutation,
client: this.clientId,
variables: this.variables,
optimisticResponse: this.optimisticResponse,
update: this.update,
refetchQueries: this.refetchQueries,
context: this.context
}, options)).then(function (result) {
_this.$emit('done', result);
_this.loading = false;
return result;
})["catch"](function (e) {
addGqlError(e);
_this.error = e;
_this.$emit('error', e);
_this.loading = false;
});
}
},
render: function render() {
var result = this.$slots["default"]({
mutate: this.mutate,
loading: this.loading,
error: this.error,
gqlError: this.error && this.error.gqlError
});
return this.tag ? vue.h(this.tag, result) : result;
}
};
function isDataFilled(data) {
return data && Object.keys(data).length > 0;
}
var CApolloQuery = {
name: 'ApolloQuery',
provide: function provide() {
return {
getDollarApollo: this.getDollarApollo,
getApolloQuery: this.getApolloQuery
};
},
emits: ['loading', 'result', 'error'],
props: {
query: {
type: [Function, Object],
required: true
},
variables: {
type: Object,
"default": undefined
},
fetchPolicy: {
type: String,
"default": undefined
},
pollInterval: {
type: Number,
"default": undefined
},
notifyOnNetworkStatusChange: {
type: Boolean,
"default": undefined
},
context: {
type: Object,
"default": undefined
},
update: {
type: Function,
"default": function _default(data) {
return data;
}
},
skip: {
type: Boolean,
"default": false
},
debounce: {
type: Number,
"default": 0
},
throttle: {
type: Number,
"default": 0
},
clientId: {
type: String,
"default": undefined
},
deep: {
type: Boolean,
"default": undefined
},
tag: {
type: String,
"default": 'div'
},
prefetch: {
type: Boolean,
"default": true
},
options: {
type: Object,
"default": function _default() {
return {};
}
}
},
data: function data() {
return {
result: {
data: null,
loading: false,
networkStatus: 7,
error: null
},
times: 0
};
},
watch: {
fetchPolicy: function fetchPolicy(value) {
this.$apollo.queries.query.setOptions({
fetchPolicy: value
});
},
pollInterval: function pollInterval(value) {
this.$apollo.queries.query.setOptions({
pollInterval: value
});
},
notifyOnNetworkStatusChange: function notifyOnNetworkStatusChange(value) {
this.$apollo.queries.query.setOptions({
notifyOnNetworkStatusChange: value
});
},
'$data.$apolloData.loading': function $data$apolloDataLoading(value) {
this.$emit('loading', !!value);
}
},
apollo: {
$client: function $client() {
return this.clientId;
},
query: function query() {
return _objectSpread2(_objectSpread2({
query: function query() {
if (typeof this.query === 'function') {
return this.query(gql);
}
return this.query;
},
variables: function variables() {
return this.variables;
},
fetchPolicy: this.fetchPolicy,
pollInterval: this.pollInterval,
debounce: this.debounce,
throttle: this.throttle,
notifyOnNetworkStatusChange: this.notifyOnNetworkStatusChange,
context: function context() {
return this.context;
},
skip: function skip() {
return this.skip;
},
deep: this.deep,
prefetch: this.prefetch
}, this.options), {}, {
manual: true,
result: function result(_result) {
var _result2 = _result,
errors = _result2.errors,
loading = _result2.loading,
networkStatus = _result2.networkStatus;
var _result3 = _result,
error = _result3.error;
_result = Object.assign({}, _result);
if (errors && errors.length) {
error = new Error("Apollo errors occurred (".concat(errors.length, ")"));
error.graphQLErrors = errors;
}
var data = {};
if (loading) {
Object.assign(data, this.$_previousData, _result.data);
} else if (error) {
Object.assign(data, this.$apollo.queries.query.observer.getLastResult() || {}, _result.data);
} else {
data = _result.data;
this.$_previousData = _result.data;
}
var dataNotEmpty = isDataFilled(data);
this.result = {
data: dataNotEmpty ? this.update(data) : undefined,
fullData: dataNotEmpty ? data : undefined,
loading: loading,
error: error,
networkStatus: networkStatus
};
this.times = ++this.$_times;
this.$emit('result', this.result);
},
error: function error(_error) {
this.result.loading = false;
this.result.error = _error;
this.$emit('error', _error);
}
});
}
},
created: function created() {
this.$_times = 0;
},
methods: {
getDollarApollo: function getDollarApollo() {
return this.$apollo;
},
getApolloQuery: function getApolloQuery() {
return this.$apollo.queries.query;
}
},
render: function render() {
var result = this.$slots["default"]({
result: this.result,
times: this.times,
query: this.$apollo.queries.query,
isLoading: this.$apolloData.loading,
gqlError: this.result && this.result.error && this.result.error.gqlError
});
return this.tag ? vue.h(this.tag, result) : result;
}
};
var uid = 0;
var CApolloSubscribeToMore = {
name: 'ApolloSubscribeToMore',
inject: ['getDollarApollo', 'getApolloQuery'],
props: {
document: {
type: [Function, Object],
required: true
},
variables: {
type: Object,
"default": undefined
},
updateQuery: {
type: Function,
"default": undefined
}
},
watch: {
document: 'refresh',
variables: 'refresh'
},
created: function created() {
this.$_key = "sub_component_".concat(uid++);
},
mounted: function mounted() {
this.refresh();
},
beforeUnmount: function beforeUnmount() {
this.destroy();
},
methods: {
destroy: function destroy() {
if (this.$_sub) {
this.$_sub.destroy();
}
},
refresh: function refresh() {
this.destroy();
var document = this.document;
if (typeof document === 'function') {
document = document(gql);
}
this.$_sub = this.getDollarApollo().addSmartSubscription(this.$_key, {
document: document,
variables: this.variables,
updateQuery: this.updateQuery,
linkedQuery: this.getApolloQuery()
});
}
},
render: function render() {
return null;
}
};
var plugin = {};
function install(app, options) {
app.component('ApolloQuery', CApolloQuery);
app.component('ApolloSubscribeToMore', CApolloSubscribeToMore);
app.component('ApolloMutation', CApolloMutation);
}
plugin.install = install;
// eslint-disable-next-line no-undef
plugin.version = "4.2.2";
// Apollo provider
var ApolloProvider = plugin;
// Components
var ApolloQuery = CApolloQuery;
var ApolloSubscribeToMore = CApolloSubscribeToMore;
var ApolloMutation = CApolloMutation;
// Auto-install
var GlobalVue = null;
if (typeof window !== 'undefined') {
GlobalVue = window.Vue;
} else if (typeof globalThis !== 'undefined') {
GlobalVue = globalThis.Vue;
}
if (GlobalVue) {
GlobalVue.use(plugin);
}
exports.ApolloMutation = ApolloMutation;
exports.ApolloProvider = ApolloProvider;
exports.ApolloQuery = ApolloQuery;
exports.ApolloSubscribeToMore = ApolloSubscribeToMore;
exports.default = plugin;
exports.install = install;
Object.defineProperty(exports, '__esModule', { value: true });
})));