UNPKG

@thi.ng/oquery

Version:

Datalog-inspired, optimized pattern/predicate query engine for JS objects & arrays of objects

77 lines (76 loc) 1.97 kB
import { isNumber } from "@thi.ng/checks/is-number"; import { isString } from "@thi.ng/checks/is-string"; import { numericOp, stringOp } from "@thi.ng/compare"; const matchStrings = (key, matches, opts) => { const [includes, excludes] = matches.reduce( (acc, x) => { x[0] === "!" ? acc[1].push(x.substring(1)) : acc[0].push(x); return acc; }, [[], []] ); return matchMultiple(key, includes, excludes, opts); }; const matchMultiple = (key, includes, excludes, opts = {}) => { const { union = false, value: valueFn } = opts; return excludes.length ? { q: [ key, (values) => { const $values = valueFn ? valueFn(values) : values; for (let x of excludes) { if ($values.includes(x)) return false; } let match = false; for (let x of includes) { if ($values.includes(x)) { match = true; if (union) break; } else if (!union) { match = false; break; } } return match; } ], opts: { cwise: false } } : { q: [key, includes], opts: { intersect: !union } }; }; const matchPattern = (key, expr, opts) => { let re; if (expr instanceof RegExp) { re = expr; } else { if (expr === "*") return { q: [key, (x) => x != null], opts }; if (/^[<>=!]/.test(expr)) { const op = /^[<>=!]+/.exec(expr)[0]; const arg = expr.substring(op.length).trim(); const argN = parseFloat(arg); return matchCompare( key, op, isNaN(argN) ? arg : argN, opts ); } re = new RegExp(expr, "i"); } return { q: [ key, (x) => (isString(x) || isNumber(x)) && re.test(String(x)) ], opts }; }; const matchCompare = (key, op, arg, opts) => ({ q: [key, isNumber(arg) ? numericOp(op, arg) : stringOp(op, arg)], opts }); export { matchCompare, matchMultiple, matchPattern, matchStrings };