UNPKG

@jsonquerylang/jsonquery

Version:

A small, flexible, and expandable JSON query language

383 lines (382 loc) 10 kB
const A = (t) => Array.isArray(t), L = (t) => t && typeof t == "object" && !A(t), W = (t) => typeof t == "string"; function f(t) { return (...e) => { const n = e.map((c) => m(c)), r = n[0], s = n[1]; return n.length === 1 ? (c) => t(r(c)) : n.length === 2 ? (c) => t(r(c), s(c)) : (c) => t(...n.map(($) => $(c))); }; } const x = { pipe: (...t) => { const e = t.map((n) => m(n)); return (n) => e.reduce((r, s) => s(r), n); }, object: (t) => { const e = Object.keys(t).map((n) => [n, m(t[n])]); return (n) => { const r = {}; for (const [s, c] of e) r[s] = c(n); return r; }; }, array: (...t) => { const e = t.map((n) => m(n)); return (n) => e.map((r) => r(n)); }, get: (...t) => { if (t.length === 0) return (e) => e ?? null; if (t.length === 1) { const e = t[0]; return (n) => (n == null ? void 0 : n[e]) ?? null; } return (e) => { let n = e; for (const r of t) n = n == null ? void 0 : n[r]; return n ?? null; }; }, map: (t) => { const e = m(t); return (n) => n.map(e); }, mapObject: (t) => { const e = m(t); return (n) => { const r = {}; for (const s of Object.keys(n)) { const c = e({ key: s, value: n[s] }); r[c.key] = c.value; } return r; }; }, mapKeys: (t) => { const e = m(t); return (n) => { const r = {}; for (const s of Object.keys(n)) { const c = e(s); r[c] = n[s]; } return r; }; }, mapValues: (t) => { const e = m(t); return (n) => { const r = {}; for (const s of Object.keys(n)) r[s] = e(n[s]); return r; }; }, filter: (t) => { const e = m(t); return (n) => n.filter((r) => E(e(r))); }, sort: (t = ["get"], e) => { const n = m(t), r = e === "desc" ? -1 : 1; function s(c, $) { const k = n(c), O = n($); return k > O ? r : k < O ? -r : 0; } return (c) => c.slice().sort(s); }, reverse: () => (t) => t.toReversed(), pick: (...t) => { const e = t.map( ([r, ...s]) => [s[s.length - 1], x.get(...s)] ), n = (r, s) => { const c = {}; for (const [$, k] of s) c[$] = k(r); return c; }; return (r) => A(r) ? r.map((s) => n(s, e)) : n(r, e); }, groupBy: (t) => { const e = m(t); return (n) => { const r = {}; for (const s of n) { const c = e(s); r[c] ? r[c].push(s) : r[c] = [s]; } return r; }; }, keyBy: (t) => { const e = m(t); return (n) => { const r = {}; for (const s of n) { const c = e(s); c in r || (r[c] = s); } return r; }; }, flatten: () => (t) => t.flat(), join: (t = "") => (e) => e.join(t), split: f( (t, e) => e !== void 0 ? t.split(e) : t.trim().split(/\s+/) ), substring: f( (t, e, n) => t.slice(Math.max(e, 0), n) ), uniq: () => (t) => [...new Set(t)], uniqBy: (t) => (e) => Object.values(x.keyBy(t)(e)), limit: (t) => (e) => e.slice(0, Math.max(t, 0)), size: () => (t) => t.length, keys: () => Object.keys, values: () => Object.values, prod: () => (t) => t.reduce((e, n) => e * n), sum: () => (t) => t.reduce((e, n) => e + n), average: () => (t) => x.sum()(t) / t.length, min: () => (t) => Math.min(...t), max: () => (t) => Math.max(...t), and: f((t, e) => !!(t && e)), or: f((t, e) => !!(t || e)), not: f((t) => !t), exists: (t) => { const e = t.slice(1), n = e.pop(), r = x.get(...e); return (s) => { const c = r(s); return !!c && Object.hasOwnProperty.call(c, n); }; }, if: (t, e, n) => { const r = m(t), s = m(e), c = m(n); return ($) => E(r($)) ? s($) : c($); }, in: (t, e) => { const n = m(t), r = m(e); return (s) => r(s).includes(n(s)); }, "not in": (t, e) => { const n = x.in(t, e); return (r) => !n(r); }, regex: (t, e, n) => { const r = new RegExp(e, n), s = m(t); return (c) => r.test(s(c)); }, eq: f((t, e) => t === e), gt: f((t, e) => t > e), gte: f((t, e) => t >= e), lt: f((t, e) => t < e), lte: f((t, e) => t <= e), ne: f((t, e) => t !== e), add: f((t, e) => t + e), subtract: f((t, e) => t - e), multiply: f((t, e) => t * e), divide: f((t, e) => t / e), pow: f((t, e) => t ** e), mod: f((t, e) => t % e), abs: f(Math.abs), round: f((t, e = 0) => +`${Math.round(+`${t}e${e}`)}e${-e}`), number: f((t) => { const e = Number(t); return Number.isNaN(Number(t)) ? null : e; }), string: f(String) }, E = (t) => t !== null && t !== 0 && t !== !1, v = []; function m(t, e) { v.unshift({ ...x, ...v[0], ...e == null ? void 0 : e.functions }); try { const n = A(t) ? J(t, v[0]) : L(t) ? P( `Function notation ["object", {...}] expected but got ${JSON.stringify(t)}` ) : () => t; return (r) => { try { return n(r); } catch (s) { throw s.jsonquery = [{ data: r, query: t }, ...s.jsonquery ?? []], s; } }; } finally { v.shift(); } } function J(t, e) { const [n, ...r] = t, s = e[n]; return s || P(`Unknown function '${n}'`), s(...r); } function P(t) { throw new Error(t); } const R = { and: "and", or: "or", eq: "==", gt: ">", gte: ">=", lt: "<", lte: "<=", ne: "!=", add: "+", subtract: "-", multiply: "*", divide: "/", pow: "^", mod: "%", in: "in", "not in": "not in" }, M = /^[a-zA-Z_$][a-zA-Z\d_$]*$/, T = /^[a-zA-Z_$][a-zA-Z\d_$]*/, U = /^"(?:[^"\\]|\\.)*"/, z = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?/, B = /^(0|[1-9][0-9]*)/, K = /^(true|false|null)/, Z = /^[ \n\t\r]+/; function D(t, e) { const n = { ...R, ...e == null ? void 0 : e.operators }, r = Object.keys(n).sort((o, a) => a.length - o.length), s = () => { g(); const o = c(); if (g(), t[u] === "|") { const a = [o]; for (; t[u] === "|"; ) u++, g(), a.push(c()); return ["pipe", ...a]; } return o; }, c = () => { const o = $(); g(); for (const a of r) { const y = n[a]; if (t.substring(u, u + y.length) === y) { u += y.length, g(); const F = $(); return [a, o, F]; } } return o; }, $ = () => { if (t[u] === "(") { u++; const o = s(); return d(")"), o; } return k(); }, k = () => { if (t[u] === ".") { const o = []; for (; t[u] === "."; ) u++, o.push( l() ?? p() ?? j() ?? _("Property expected") ); return ["get", ...o]; } return O(); }, O = () => { const o = u, a = p(); if (g(), !a || t[u] !== "(") return u = o, h(); u++, !(e != null && e.functions[a]) && !x[a] && _(`Unknown function '${a}'`), g(); const y = t[u] !== ")" ? [s()] : []; for (; u < t.length && t[u] !== ")"; ) g(), d(","), y.push(s()); return d(")"), [a, ...y]; }, h = () => { if (t[u] === "{") { u++, g(); const o = {}; let a = !0; for (; u < t.length && t[u] !== "}"; ) { a ? a = !1 : (d(","), g()); const y = l() ?? p() ?? j() ?? _("Key expected"); g(), d(":"), o[y] = s(); } return d("}"), ["object", o]; } return i(); }, i = () => { if (t[u] === "[") { u++, g(); const o = []; let a = !0; for (; u < t.length && t[u] !== "]"; ) a ? a = !1 : (d(","), g()), o.push(s()); return d("]"), ["array", ...o]; } return l() ?? N() ?? w(); }, l = () => b(U, JSON.parse), p = () => b(T, (o) => o), N = () => b(z, JSON.parse), j = () => b(B, JSON.parse), w = () => { const o = b(K, JSON.parse); if (o !== void 0) return o; _("Value expected"); }, S = () => { g(), u < t.length && _(`Unexpected part '${t.substring(u)}'`); }, b = (o, a) => { const y = t.substring(u).match(o); if (y) return u += y[0].length, a(y[0]); }, g = () => b(Z, (o) => o), d = (o) => { t[u] !== o && _(`Character '${o}' expected`), u++; }, _ = (o, a = u) => { throw new SyntaxError(`${o} (pos: ${a})`); }; let u = 0; const I = s(); return S(), I; } const C = 40, V = " ", G = (t, e) => { const n = (e == null ? void 0 : e.indentation) ?? V, r = (h, i) => A(h) ? s(h, i) : JSON.stringify(h), s = (h, i) => { var S; const [l, ...p] = h; if (l === "get" && p.length > 0) return $(p); if (l === "pipe") { const b = p.map((g) => r(g, i + n)); return O(b, ["", " | ", ""], ["", ` ${i + n}| `, ""]); } if (l === "object") return c(p[0], i); if (l === "array") { const b = p.map((g) => r(g, i)); return O( b, ["[", ", ", "]"], [`[ ${i + n}`, `, ${i + n}`, ` ${i}]`] ); } const N = ((S = e == null ? void 0 : e.operators) == null ? void 0 : S[l]) ?? R[l]; if (N && p.length === 2) { const [b, g] = p, d = r(b, i), _ = r(g, i); return `(${d} ${N} ${_})`; } const j = p.length === 1 ? i : i + n, w = p.map((b) => r(b, j)); return p.length === 1 && w[0][0] === "(" ? `${l}${w[0]}` : O( w, [`${l}(`, ", ", ")"], p.length === 1 ? [`${l}(`, `, ${i}`, ")"] : [`${l}( ${j}`, `, ${j}`, ` ${i})`] ); }, c = (h, i) => { const l = i + n, p = Object.entries(h).map(([N, j]) => `${k(N)}: ${r(j, l)}`); return O( p, ["{ ", ", ", " }"], [`{ ${l}`, `, ${l}`, ` ${i}}`] ); }, $ = (h) => h.map((i) => `.${k(i)}`).join(""), k = (h) => M.test(h) ? h : JSON.stringify(h), O = (h, [i, l, p], [N, j, w]) => i.length + h.reduce((b, g) => b + g.length + l.length, 0) - l.length + p.length <= ((e == null ? void 0 : e.maxLineLength) ?? C) ? i + h.join(l) + p : N + h.join(j) + w; return r(t, ""); }; function H(t, e, n) { return m(W(e) ? D(e, n) : e, n)(t); } export { f as buildFunction, m as compile, H as jsonquery, D as parse, G as stringify }; //# sourceMappingURL=jsonquery.js.map