UNPKG

vulcain-corejs

Version:
175 lines (173 loc) 6.1 kB
"use strict"; class MongoQueryParser { constructor(query) { this.query = query; } execute(entity) { if (!this.query) return true; return this.executeExpression(entity, this.query); } executeExpression(entity, query) { let keys = Object.keys(query); if (keys.length === 0) return true; let op = keys[0]; let val; switch (op) { case "$or": val = query[op]; if (!Array.isArray(val)) throw new Error("Syntax error in logical expression"); for (let o of val) { if (this.executeExpression(entity, o)) return true; } return false; case "$and": val = query[op]; if (!Array.isArray(val)) throw new Error("Syntax error in logical expression"); for (let o of val) { if (!this.executeExpression(entity, o)) return false; } return true; case "$nor": val = query[op]; if (!Array.isArray(val)) throw new Error("Syntax error in logical expression"); for (let o of val) { if (this.executeExpression(entity, o)) return false; } return true; default: if (keys.length > 1) { for (let k of keys) { let obj = {}; obj[k] = query[k]; if (!this.executeOperator(entity, obj)) return false; } } else { if (!this.executeOperator(entity, query)) return false; } } return true; } executeOperator(entity, query) { let keys = Object.keys(query); if (keys.length !== 1) throw new Error("Syntax error"); let k = keys[0]; let left = this.getFieldValue(entity, k); let val = query[k]; if (typeof val !== "object") { return this.evaluate("$eq", left, val); } let v = this.getExpressionValue(val); if (v.op === "$not") { v = this.getExpressionValue(v.val); return !this.evaluate(v.op, left, v.val); } return this.evaluate(v.op, left, v.val); } getExpressionValue(val) { let keys = Object.keys(val); if (keys.length !== 1) throw new Error("Syntax error"); let op = keys[0]; return { op, val: val[op] }; } evaluate(op, left, right) { switch (op) { case "$eq": if (Array.isArray(left)) return left.indexOf(right) >= 0; return (left === right); case "$comment": return true; case "$lt": return (left < right); case "$gt": return (left > right); case "$lte": return (left <= right); case "$gte": return (left >= right); case "$ne": return (left !== right); case "$exists": return (left !== undefined) === right; case "$regex": return left.match(RegExp(right)) !== null; case "$in": if (!Array.isArray(right)) throw new Error("Syntax error for $in"); let arr = Array.isArray(left) ? left : [left]; for (let i of arr) { if (right.indexOf(i) >= 0) return true; } return false; case "$nin": if (!Array.isArray(right)) throw new Error("Syntax error for $nin"); let arr2 = Array.isArray(left) ? left : [left]; for (let i of arr2) { if (right.indexOf(i) >= 0) return false; } return true; case "$startsWith": return (left.startsWith(right)); case "$mod": if (!Array.isArray(right)) throw new Error("Syntax error for $mod"); let divider = parseInt(right[0]); let remainder = parseInt(right[1]); return left % divider === remainder; case "$elemMatch": if (!left) return false; if (!Array.isArray(left)) throw new Error("Syntax error for $elemMatch"); for (let elem of left) { if (this.executeExpression(elem, right)) return true; } return false; case "$all": if (!left) return false; if (!Array.isArray(right) && !Array.isArray(left)) throw new Error("Syntax error for $all"); for (let elem of left) { if (right.indexOf(elem) <= 0) return false; } return true; case "$size": if (!left) return false; if (!Array.isArray(left)) throw new Error("Syntax error for $size"); return left.length === right; default: throw new Error("Operator not implemented"); } } getFieldValue(entity, path) { let current = entity; let parts = path.split('.'); for (let part of parts) { current = current && current[part]; } return current; } } exports.MongoQueryParser = MongoQueryParser; //# sourceMappingURL=mongoQueryParser.js.map