r2query
Version:
Mongoose api query plugin
129 lines (104 loc) • 3.1 kB
JavaScript
const async = require('async');
const run = (query = {}, model, options = {}) => (
new Promise((resolve, reject) => {
let Model = model;
const { sort, skip = 0, fields, populate } = options;
const { qName } = query;
let { qType = 'all' } = query;
let { limit = 10 } = options;
let treeFunc;
if (qType) {
delete query.qType;
}
if (qName) {
delete query.qName;
}
// set maximum limit
if (['all', 'allTotal'].includes(qType) && limit > 1000) {
limit = 1000;
}
// query type
switch (qType) {
case 'all':
case 'allTotal':
Model = Model.find(query);
break;
case 'one':
Model = Model.findOne(query);
break;
case 'total':
Model = Model.count(query);
break;
case 'tree':
treeFunc = 'GetTree';
break;
case 'arrayTree':
treeFunc = 'GetArrayTree';
break;
case 'fullArrayTree':
treeFunc = 'GetFullArrayTree';
break;
default:
return reject({ type: 'notSupportedQueryType' });
}
if (['tree', 'arrayTree'].includes(qType)) {
if (!Model[treeFunc]) {
return reject({ type: 'notSupportedTreeModel' });
}
const childOpts = query.childOpts || {};
if (query.childOpts) {
delete query.childOpts;
}
return Model[treeFunc](query, childOpts, (err, tree) => {
resolve(tree);
});
}
if (['fullArrayTree'].includes(qType)) {
if (!Model[treeFunc]) {
return reject({ type: 'notSupportedTreeModel' });
}
return Model[treeFunc]((err, tree) => resolve(tree));
}
if (['all', 'allTotal', 'one'].includes(qType)) {
if (sort) Model.sort(sort);
if (skip) Model.skip(skip);
if (limit) Model.limit(limit);
if (fields) Model.select(fields);
if (populate) Model.populate(populate);
}
const qFunc = qName && (typeof model[qName] === 'function' || typeof Model[qName] === 'function');
let qModel = Model;
// get statics or query function
if (qFunc) {
qModel = model[qName] ? model[qName](query, options) : Model[qName](query, options);
// override qName as 'all' for statics (because qFind[qName] could throw error)
if (model[qName]) {
qType = 'all';
}
}
if (['all', 'one', 'total'].includes(qType)) {
return resolve(qModel.exec ? qModel.exec() : qModel);
}
if (['allTotal'].includes(qType)) {
const qFind = model.find(query);
const a = {
rows: cb => qModel.exec(cb),
total: cb => (qFunc ? qFind[qName](query, options) : qFind).count().exec(cb),
};
async.parallel(a, (err, results = {}) => {
const { rows, total } = results;
return resolve({ rows, total });
});
}
return true;
})
);
module.exports = function Query() {
return {
plugin(schema) {
schema.statics.apiQuery = function (query, options) { // eslint-disable-line
return run(query, this, options);
};
},
};
};