open-rest-helper-rest
Version:
open-rest 的 helper 插件,用来实现 CRUD 的标准操作
104 lines (98 loc) • 3.2 kB
JavaScript
const delegate = require('func-delegate');
const U = require('../lib/utils');
const _ = require('lodash');
// 统计符合条件的条目数
const getTotal = (Model, opt, ignoreTotal, callback) => {
if (ignoreTotal) return callback();
return U.callback(Model.count(opt), callback);
};
/**
* 获取资源列表的通用方法
* Model Sequlize 定义的Model,表明数据从哪里获取
* _options 是否要去req.hooks上去options
* allowAttrs 那些字段是被允许的
* hook 默认为空,如果指定了hook,则数据不直接输出而是先挂在 hook上
* fixOptFn 可选函数,用来完善查询数据库的条件。可根据req.param上的数据,对option做加减。
*/
const list = (Model, opt, allowAttrs, hook, fixOptFn) => (
(req, res, next) => {
const params = req.params;
const options = opt ? req.hooks[opt] : U.findAllOpts(Model, req.params);
const countOpt = {};
if (options.where) countOpt.where = options.where;
if (options.include) countOpt.include = options.include;
// 完善opt
if (fixOptFn && _.isFunction(fixOptFn)) fixOptFn(options, params);
// 是否忽略总条目数,这样就可以不需要count了。在某些时候可以
// 提高查询速度
const ignoreTotal = req.params._ignoreTotal === 'yes';
getTotal(Model, countOpt, ignoreTotal, (error, count) => {
if (error) return next(error);
if (ignoreTotal || count) {
return Model.findAll(options).then((result) => {
let ls = U.listAttrFilter(result, allowAttrs);
if (!ignoreTotal) res.header('X-Content-Record-Total', count);
if (!hook && params.attrs) {
ls = U.listAttrFilter(ls, params.attrs.split(','));
}
if (hook) {
req.hooks[hook] = ls;
} else {
res.send(ls);
}
next();
}).catch(next);
}
res.header('X-Content-Record-Total', 0);
if (hook) {
req.hooks[hook] = [];
} else {
res.send([]);
}
return next();
});
}
);
module.exports = (rest) => {
const Sequelize = rest.Sequelize;
const schemas = [{
name: 'Model',
type: Sequelize.Model,
message: 'Model must be a class of Sequelize defined',
}, {
name: 'opt',
type: String,
allowNull: true,
message: "FindAll option hooks's name, so `opt` must be a string",
}, {
name: 'allowAttrs',
type: Array,
allowNull: true,
validate: {
check(keys, schema, args) {
const Model = args[0];
_.each(keys, (v) => {
if (!_.isString(v)) {
throw Error('Every item in allowAttrs must be a string.');
}
if (!Model.rawAttributes[v]) {
throw Error(`Attr non-exists: ${v}`);
}
});
return true;
},
},
message: 'Allow return attrs\'s name array',
}, {
name: 'hook',
type: String,
allowNull: true,
message: 'Geted list will hook on req.hooks[hook], so `hook` must be a string',
}, {
name: 'fixOptFn',
type: Function,
allowNull: true,
message: 'FixOptFn must be a function',
}];
return delegate(list, schemas);
};