2016-10-07 10:31:58 +03:00
|
|
|
import NamedQuery from '../namedQuery.js';
|
|
|
|
import ExposeSchema from './schema.js';
|
|
|
|
import mergeDeep from './lib/mergeDeep.js';
|
|
|
|
import createGraph from '../../query/lib/createGraph.js';
|
|
|
|
import recursiveCompose from '../../query/lib/recursiveCompose.js';
|
2016-11-07 18:44:09 +02:00
|
|
|
import prepareForProcess from '../../query/lib/prepareForProcess.js';
|
2017-11-25 14:17:33 +02:00
|
|
|
import deepClone from 'lodash.cloneDeep';
|
2016-10-07 10:31:58 +03:00
|
|
|
|
|
|
|
_.extend(NamedQuery.prototype, {
|
|
|
|
expose(config = {}) {
|
|
|
|
if (!Meteor.isServer) {
|
|
|
|
throw new Meteor.Error('invalid-environment', `You must run this in server-side code`);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.isExposed) {
|
|
|
|
throw new Meteor.Error('query-already-exposed', `You have already exposed: "${this.name}" named query`);
|
|
|
|
}
|
|
|
|
|
|
|
|
ExposeSchema.clean(config);
|
|
|
|
this.exposeConfig = config;
|
|
|
|
|
|
|
|
if (config.method) {
|
|
|
|
this._initMethod();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (config.publication) {
|
|
|
|
this._initPublication();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!config.method && !config.publication) {
|
2016-10-07 13:08:36 +03:00
|
|
|
throw new Meteor.Error('weird', 'If you want to expose your named query you need to specify at least one of ["method", "publication"] options to true')
|
2016-10-07 10:31:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
this._initCountMethod();
|
|
|
|
|
|
|
|
if (config.embody) {
|
2016-10-19 15:22:50 +03:00
|
|
|
this.body = mergeDeep(
|
|
|
|
deepClone(this.body),
|
|
|
|
config.embody
|
|
|
|
);
|
2016-10-07 10:31:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
this.isExposed = true;
|
|
|
|
},
|
|
|
|
|
|
|
|
_initMethod() {
|
|
|
|
const self = this;
|
|
|
|
Meteor.methods({
|
|
|
|
[this.name](newParams) {
|
|
|
|
this.unblock();
|
|
|
|
|
2016-10-07 11:59:18 +03:00
|
|
|
self._validateParams(newParams);
|
|
|
|
|
2016-10-07 10:31:58 +03:00
|
|
|
if (self.exposeConfig.firewall) {
|
|
|
|
self.exposeConfig.firewall.call(this, this.userId, newParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
return self.clone(newParams).fetch();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
_initCountMethod() {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
Meteor.methods({
|
|
|
|
[this.name + '.count'](newParams) {
|
|
|
|
this.unblock();
|
2016-10-07 11:59:18 +03:00
|
|
|
self._validateParams(newParams);
|
2016-10-07 10:31:58 +03:00
|
|
|
|
2017-06-23 15:44:48 +12:00
|
|
|
if (self.exposeConfig.firewall) {
|
|
|
|
self.exposeConfig.firewall.call(this, this.userId, newParams);
|
|
|
|
}
|
|
|
|
|
2016-10-07 10:31:58 +03:00
|
|
|
return self.clone(newParams).getCount();
|
|
|
|
}
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
_initPublication() {
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
Meteor.publishComposite(this.name, function (newParams) {
|
2016-10-07 11:59:18 +03:00
|
|
|
self._validateParams(newParams);
|
|
|
|
|
2016-10-07 10:31:58 +03:00
|
|
|
if (self.exposeConfig.firewall) {
|
|
|
|
self.exposeConfig.firewall.call(this, this.userId, newParams);
|
|
|
|
}
|
|
|
|
|
|
|
|
let params = _.extend({}, self.params, newParams);
|
2016-11-07 18:44:09 +02:00
|
|
|
let body = prepareForProcess(self.body, params);
|
2016-10-07 10:31:58 +03:00
|
|
|
|
|
|
|
const rootNode = createGraph(self.collection, body);
|
|
|
|
|
|
|
|
return recursiveCompose(rootNode);
|
|
|
|
});
|
2016-10-07 11:59:18 +03:00
|
|
|
},
|
|
|
|
|
|
|
|
_validateParams(params) {
|
2016-10-07 12:49:02 +03:00
|
|
|
if (params && this.exposeConfig.schema) {
|
2017-06-23 15:44:48 +12:00
|
|
|
if (process.env.NODE_ENV !== 'production') {
|
|
|
|
try {
|
|
|
|
(new SimpleSchema(this.exposeConfig.schema)).validate(params);
|
|
|
|
} catch (validationError) {
|
|
|
|
console.error(`Invalid parameters supplied to query ${this.queryName}`, validationError);
|
|
|
|
throw validationError; // rethrow
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
(new SimpleSchema(this.exposeConfig.schema)).validate(params);
|
|
|
|
}
|
2016-10-07 11:59:18 +03:00
|
|
|
}
|
2016-10-07 10:31:58 +03:00
|
|
|
}
|
|
|
|
});
|