grapher/lib/namedQuery/namedQuery.client.js
2018-09-24 11:44:35 -07:00

191 lines
5 KiB
JavaScript
Executable file

import CountSubscription from '../query/counts/countSubscription';
import createGraph from '../query/lib/createGraph.js';
import recursiveFetch from '../query/lib/recursiveFetch.js';
import prepareForProcess from '../query/lib/prepareForProcess.js';
import {_} from 'meteor/underscore';
import callWithPromise from '../query/lib/callWithPromise';
import Base from './namedQuery.base';
import {LocalCollection} from 'meteor/minimongo';
export default class extends Base {
/**
* Subscribe
*
* @param callback
* @returns {null|any|*}
*/
subscribe(callback) {
if (this.isResolver) {
throw new Meteor.Error('not-allowed', `You cannot subscribe to a resolver query`);
}
this.subscriptionHandle = Meteor.subscribe(
this.name,
this.params,
callback
);
return this.subscriptionHandle;
}
/**
* Subscribe to the counts for this query
*
* @param callback
* @returns {Object}
*/
subscribeCount(callback) {
if (this.isResolver) {
throw new Meteor.Error('not-allowed', `You cannot subscribe to a resolver query`);
}
if (!this._counter) {
this._counter = new CountSubscription(this);
}
return this._counter.subscribe(this.params, callback);
}
/**
* Unsubscribe if an existing subscription exists
*/
unsubscribe() {
if (this.subscriptionHandle) {
this.subscriptionHandle.stop();
}
this.subscriptionHandle = null;
}
/**
* Unsubscribe to the counts if a subscription exists.
*/
unsubscribeCount() {
if (this._counter) {
this._counter.unsubscribe();
this._counter = null;
}
}
/**
* Fetches elements in sync using promises
* @return {*}
*/
async fetchSync() {
if (this.subscriptionHandle) {
throw new Meteor.Error('This query is reactive, meaning you cannot use promises to fetch the data.');
}
return await callWithPromise(this.name, this.params);
}
/**
* Fetches one element in sync
* @return {*}
*/
async fetchOneSync() {
return _.first(await this.fetchSync())
}
/**
* Retrieves the data.
* @param callbackOrOptions
* @returns {*}
*/
fetch(callbackOrOptions) {
if (!this.subscriptionHandle) {
return this._fetchStatic(callbackOrOptions)
} else {
return this._fetchReactive(callbackOrOptions);
}
}
/**
* @param args
* @returns {*}
*/
fetchOne(...args) {
if (!this.subscriptionHandle) {
const callback = args[0];
if (!_.isFunction(callback)) {
throw new Meteor.Error('You did not provide a valid callback');
}
this.fetch((err, res) => {
callback(err, res ? _.first(res) : null);
})
} else {
return _.first(this.fetch(...args));
}
}
/**
* Gets the count of matching elements in sync.
* @returns {any}
*/
async getCountSync() {
if (this._counter) {
throw new Meteor.Error('This query is reactive, meaning you cannot use promises to fetch the data.');
}
return await callWithPromise(this.name + '.count', this.params);
}
/**
* Gets the count of matching elements.
* @param callback
* @returns {any}
*/
getCount(callback) {
if (this._counter) {
return this._counter.getCount();
} else {
if (!callback) {
throw new Meteor.Error('not-allowed', 'You are on client so you must either provide a callback to get the count or subscribe first.');
} else {
return Meteor.call(this.name + '.count', this.params, callback);
}
}
}
/**
* Fetching non-reactive queries
* @param callback
* @private
*/
_fetchStatic(callback) {
if (!callback) {
throw new Meteor.Error('not-allowed', 'You are on client so you must either provide a callback to get the data or subscribe first.');
}
Meteor.call(this.name, this.params, callback);
}
/**
* Fetching when we've got an active publication
*
* @param options
* @returns {*}
* @private
*/
_fetchReactive(options = {}) {
let body = this.body;
if (this.params.$body) {
body = intersectDeep(body, this.params.$body);
}
body = prepareForProcess(body, this.params);
if (!options.allowSkip && body.$options && body.$options.skip) {
delete body.$options.skip;
}
return recursiveFetch(
createGraph(this.collection, body),
undefined, {
scoped: this.options.scoped,
queryScoped: true,
subscriptionHandle: this.subscriptionHandle,
});
}
}