jsonapi-server-mini
Version:
Minimalistic JSON:API server for Node.js and MongoDB
53 lines (48 loc) • 1.79 kB
JavaScript
/**
* @author Sander Steenhuis <info@redsandro.com> (https://www.Redsandro.com)
* @license MIT
*/
const operatorMap = {
'<=' : [ value => ({ $lte: value }) ],
'>=' : [ value => ({ $gte: value }) ],
'<' : [ value => ({ $lt: value }) ],
'>' : [ value => ({ $gt: value }) ],
':' : [ value => RegExp(value, 'i') ],
'~' : [ value => RegExp(`^${value}$`, 'i') ],
':~' : [ value => RegExp(`${value}$`, 'i') ],
'~:' : [ value => RegExp(`^${value}`, 'i') ],
'!' : [ value => ({ $ne: value }), values => ({ $nin: values }) ],
}
const operators = Object.keys(operatorMap).sort((a, b) => a.length > b.length && -1 || a.length < b.length && 1)
/**
* Convert JSON:API `filter` query string to mongo find commands
* @param {IncomingMessage} req
* @param {Object} options
* @return {Object} MongoDB `find` query
* @todo Parse custom filters from options.
* @todo Split keys for filtering post-includes
*/
module.exports = (req, options) => {
if (typeof req.query.filter == 'object') {
return Object.entries(req.query.filter)
.reduce((acc, [key, expression]) => {
const operator = operators.find(op => RegExp(`^${op}`).test(expression))
if (key == 'id') key = '_id'
if (key == '$text') acc[key] = typeof expression == 'string' ? {$search: expression} : expression // allow both search string and options object
else if (operator) {
const ops = operatorMap[operator]
const value = expression.substr(operator.length)
if (value.includes(',') && ops.length > 1)
acc[key] = ops[1](value.split(','))
else
acc[key] = ops[0](value)
}
else if (expression.length >= 3 && expression.includes(',')) {
acc[key] = { $in: expression.split(',') }
}
else acc[key] = expression
return acc
}, {})
}
return {}
}