query = {
const allKey = "__all";
const applyRule = (rule, data, queryOut) => {
let from, k, x, to, pred, pre;
[k, x] = rule;
const predDelete = (k, x, toKey, fromKey) => {
pred = typeof x === "function" ? x : v => x == v;
if (typeof k === "function") {
pre = k;
pred = tx.identity;
toKey = x;
} else {
pre = obj => obj[k];
}
const curr = [
...((fromKey && queryOut[fromKey]) || queryOut[allKey] || data)
];
queryOut[toKey] = new Set(curr.filter(d => pred(pre(d))));
};
switch (rule.length) {
case 1:
return predDelete(k, tx.identity, allKey);
break;
case 2:
return predDelete(k, x, allKey);
break;
case 3:
[k, x, to] = rule;
return predDelete(k, x, to);
break;
case 4:
[from, k, x, to] = rule;
return predDelete(k, x, to, from);
break;
}
};
const wrapQueryOut = qOut =>
Object.keys(qOut).length == 1 && qOut[allKey] ? qOut[allKey] : qOut;
const query = (q, data) => {
const queryOut = {};
return !data
? data => query(q, data)
: q.length == 0
? data
: (q.forEach(r => applyRule(r, data, queryOut)), wrapQueryOut(queryOut));
};
return query;
}