jsonapi-server-mini
Version:
Minimalistic JSON:API server for Node.js and MongoDB
73 lines (68 loc) • 2.36 kB
JavaScript
/**
* @author Sander Steenhuis <info@redsandro.com> (https://www.Redsandro.com)
* @author Stone Circle <info@stonecircle.ie> (https://www.stonecircle.ie)
* @license MIT
*/
const serializer = require('../helpers/serializer')
const parseInclude = require('../helpers/parseInclude')
const filter = require('../helpers/filter')
const middlefy = require('../helpers/middlefy')
module.exports = (options) => async(req, res, next) => {
const {
args,
model:Model,
} = options
const {
sample,
page = {},
} = req.query
const {
select,
sort,
} = req.jsMini
const pageLimit = Math.min(+page.limit || +page.size, Math.max(args.limitMax || 0, 100))
const limit = pageLimit || options.find.limit || args.limit || 50
const offset = +page.offset || +(page.number || 0) * limit || 0
const relInclude = parseInclude(req, options)
const match = { ...filter(req), ...req.jsMini.query }
let results, count, meta = {}
try {
if (options.find.query) {
/*
* If a custom query function was specified, all logic is expected to be there.
* All we need to do is serialize the response according to the scheme.
*/
results = await options.find.query(req, 'findMany')
}
else if (sample) {
/*
* Random set is only available through aggregate, so we need to set up
* the pipeline a bit differently
*/
const size = +sample || 1
const result = await Model.aggregate().match(match).sample(size).project({_id: 1}).exec()
const ids = result.map(m => m._id)
const find = Model.find({_id: {$in: ids}}).lean(false)
const query = relInclude.reduce((findOne, rel) => findOne.populate(rel), find)
results = await query.exec()
meta = { ...meta, count:size }
}
else {
/*
* Execute the default query pipeline.
*/
const find = Model.find(match).select(select).sort(sort).lean(false).skip(offset).limit(limit)
const query = relInclude.reduce((findOne, rel) => findOne.populate(rel), find)
results = await query.exec()
count = await Model.countDocuments(match)
meta = { ...meta, count }
}
results = middlefy(options, 'beforeSerializer', 'find', results)
results = serializer(req, results, relInclude, meta, options)
results = middlefy(options, 'afterSerializer', 'find', results)
return res.json(results)
}
catch (err) {
return next(err)
}
}