🚨 Active Supply Chain Attack:node-ipc Package Compromised.Learn More
Socket
Book a DemoSign in
Socket

@josdejong/jsonquery

Package Overview
Dependencies
Maintainers
1
Versions
24
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@josdejong/jsonquery - npm Package Compare versions

Comparing version
1.1.6
to
1.2.0
+1
-1
lib/compile.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAET,SAAS,EAIT,gBAAgB,EAGjB,MAAM,SAAS,CAAA;AAShB,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAU/E"}
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EAET,SAAS,EAIT,gBAAgB,EAGjB,MAAM,SAAS,CAAA;AAShB,wBAAgB,OAAO,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAqB/E"}

@@ -1,2 +0,2 @@

const m = (t) => Array.isArray(t), y = (t) => t && typeof t == "object" && !m(t), b = (t) => typeof t == "string", o = (t) => m(t) ? (n) => {
const m = (t) => Array.isArray(t), x = (t) => t && typeof t == "object" && !m(t), b = (t) => typeof t == "string", o = (t) => m(t) ? (n) => {
let e = n;

@@ -6,6 +6,6 @@ for (const r of t)

return e;
} : (n) => n == null ? void 0 : n[t], d = (t) => () => t, h = (t) => {
} : (n) => n == null ? void 0 : n[t], S = (t) => () => t, h = (t) => {
const n = t.map((e) => u(e));
return (e) => n.reduce((r, c) => c(r), e);
}, _ = (t) => {
}, y = (t) => {
const n = Object.keys(t).map((e) => [e, u(t[e])]);

@@ -16,3 +16,3 @@ return (e) => {

};
}, S = (t) => {
}, d = (t) => {
const n = u(t);

@@ -26,4 +26,4 @@ return (e) => e.map(n);

function c(s, i) {
const f = e(s), O = e(i);
return f > O ? r : f < O ? -r : 0;
const f = e(s), j = e(i);
return f > j ? r : f < j ? -r : 0;
}

@@ -36,4 +36,4 @@ return (s) => s.slice().sort(c);

]);
return (e) => m(e) ? e.map((r) => j(r, n)) : j(e, n);
}, j = (t, n) => {
return (e) => m(e) ? e.map((r) => O(r, n)) : O(e, n);
}, O = (t, n) => {
const e = {};

@@ -43,3 +43,3 @@ return n.forEach(([r, c]) => {

}), e;
}, k = (t) => {
}, _ = (t) => {
const n = o(t);

@@ -63,3 +63,3 @@ return (e) => {

};
}, A = () => (t) => t.flat(), B = () => (t) => [...new Set(t)], w = (t) => (n) => Object.values(k(t)(n)).map((e) => e[0]), z = (t) => {
}, w = () => (t) => t.flat(), A = () => (t) => [...new Set(t)], B = (t) => (n) => Object.values(_(t)(n)).map((e) => e[0]), z = (t) => {
const n = u(t);

@@ -70,3 +70,3 @@ return (e) => !n(e);

return (e) => n(e) !== void 0;
}, F = (t) => (n) => n.slice(0, t), P = () => Object.keys, R = () => Object.values, T = () => (t) => t.reduce((n, e) => n * e), x = () => (t) => t.reduce((n, e) => n + e), V = () => (t) => x()(t) / t.length, D = () => (t) => Math.min(...t), G = () => (t) => Math.max(...t), H = () => Math.abs, I = (t = 0) => (n) => +(Math.round(+(n + "e" + t)) + "e" + -t), J = () => (t) => t.length, K = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
}, F = (t) => (n) => n.slice(0, t), P = () => Object.keys, R = () => Object.values, T = () => (t) => t.reduce((n, e) => n * e), k = () => (t) => t.reduce((n, e) => n + e), V = () => (t) => k()(t) / t.length, D = () => (t) => Math.min(...t), G = () => (t) => Math.max(...t), H = () => Math.abs, I = (t = 0) => (n) => +(Math.round(+(n + "e" + t)) + "e" + -t), J = () => (t) => t.length, K = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
__proto__: null,

@@ -77,13 +77,13 @@ abs: H,

filter: v,
flatten: A,
flatten: w,
get: o,
groupBy: k,
groupBy: _,
keyBy: N,
keys: P,
limit: F,
map: S,
map: d,
max: G,
min: D,
not: z,
object: _,
object: y,
pick: E,

@@ -95,6 +95,6 @@ pipe: h,

sort: M,
string: d,
sum: x,
uniq: B,
uniqBy: w,
string: S,
sum: k,
uniq: A,
uniqBy: B,
values: R

@@ -139,19 +139,26 @@ }, Symbol.toStringTag, { value: "Module" })), g = (t, n = !1) => (e, r) => {

}
}, a = [K], l = [W];
}, l = [K], a = [W];
function u(t, n) {
a.unshift({ ...a[0], ...n == null ? void 0 : n.functions }), l.unshift({ ...l[0], ...n == null ? void 0 : n.operators });
l.unshift({ ...l[0], ...n == null ? void 0 : n.functions }), a.unshift({ ...a[0], ...n == null ? void 0 : n.operators });
try {
return X(t);
const e = X(t);
return (r) => {
try {
return e(r);
} catch (c) {
throw c.jsonquery = [{ data: r, query: t }, ...c.jsonquery ?? []], c;
}
};
} finally {
a.shift(), l.shift();
l.shift(), a.shift();
}
}
function X(t) {
if (y(t))
return _(t);
if (x(t))
return y(t);
if (m(t)) {
const [n, ...e] = t, r = a[0][n];
const [n, ...e] = t, r = l[0][n];
if (r)
return r(...e);
const [c, s, ...i] = t, f = l[0][s];
const [c, s, ...i] = t, f = a[0][s];
return f ? f(c, ...i) : h(t);

@@ -158,0 +165,0 @@ }

@@ -1,1 +0,1 @@

{"version":3,"file":"jsonquery.js","sources":["../src/is.ts","../src/functions.ts","../src/operators.ts","../src/compile.ts","../src/jsonquery.ts"],"sourcesContent":["export const isArray = <T>(value: unknown): value is T[] => Array.isArray(value)\n\nexport const isObject = (value: unknown): value is object =>\n value && typeof value === 'object' && !isArray(value)\n\nexport const isString = (value: unknown): value is string => typeof value === 'string'\n","import { Getter, JSONPath, JSONProperty, JSONQuery, JSONQueryObject } from './types'\nimport { compile } from './compile'\nimport { isArray, isString } from './is'\n\nexport const get = (path: JSONPath | JSONProperty) =>\n isArray(path)\n ? (data: unknown) => {\n let value = data\n\n for (const prop of path) {\n value = value?.[prop]\n }\n\n return value\n }\n : (data: unknown) => data?.[path]\n\nexport const string = (text: string) => () => text\n\nexport const pipe = (entries: JSONQuery[]) => {\n const _entries = entries.map((entry) => compile(entry))\n return (data: unknown) => _entries.reduce((data, evaluator) => evaluator(data), data)\n}\n\nexport const object = (query: JSONQueryObject) => {\n const getters: Getter[] = Object.keys(query).map((key) => [key, compile(query[key])])\n\n return (data: unknown) => {\n const obj = {}\n getters.forEach(([key, getter]) => (obj[key] = getter(data)))\n return obj\n }\n}\n\nexport const map = <T>(callback: JSONQuery) => {\n const _callback = compile(callback)\n return (data: T[]) => data.map(_callback)\n}\n\nexport const filter = <T>(predicate: JSONQuery) => {\n const _predicate = compile(predicate)\n return (data: T[]) => data.filter(_predicate)\n}\n\nexport const sort = <T>(path: JSONPath | JSONProperty = [], direction?: 'asc' | 'desc') => {\n const getter = get(path)\n const sign = direction === 'desc' ? -1 : 1\n\n function compare(itemA: unknown, itemB: unknown) {\n const a = getter(itemA)\n const b = getter(itemB)\n return a > b ? sign : a < b ? -sign : 0\n }\n\n return (data: T[]) => data.slice().sort(compare)\n}\n\nexport const pick = (...paths: (JSONPath | JSONProperty)[]) => {\n const getters: Getter[] = paths.map((path) => [\n isString(path) ? path : path[path.length - 1],\n get(path)\n ])\n\n return (data: Record<string, unknown>): unknown => {\n if (isArray(data)) {\n return data.map((item: Record<string, unknown>) => _pick(item, getters))\n }\n\n return _pick(data, getters)\n }\n}\n\nconst _pick = (object: Record<string, unknown>, getters: Getter[]): unknown => {\n const out = {}\n\n getters.forEach(([key, getter]) => {\n out[key] = getter(object)\n })\n\n return out\n}\n\nexport const groupBy = <T>(path: JSONPath | JSONProperty) => {\n const getter = get(path)\n\n return (data: T[]) => {\n const res = {}\n\n for (const item of data) {\n const value = getter(item) as string\n if (res[value]) {\n res[value].push(item)\n } else {\n res[value] = [item]\n }\n }\n\n return res\n }\n}\n\nexport const keyBy = <T>(path: JSONPath | JSONProperty) => {\n const getter = get(path)\n\n return (data: T[]) => {\n const res = {}\n\n data.forEach((item) => {\n const value = getter(item) as string\n res[value] = res[value] ?? item\n })\n\n return res\n }\n}\n\nexport const flatten = () => (data: unknown[]) => data.flat()\n\nexport const uniq =\n () =>\n <T>(data: T[]) => [...new Set(data)]\n\nexport const uniqBy =\n <T>(path: JSONPath | JSONProperty) =>\n (data: T[]): T[] =>\n Object.values(groupBy(path)(data)).map((groups) => groups[0])\n\n// operator not (looks like a function because it has no left operand)\nexport const not = (query: JSONQuery) => {\n const getter = compile(query)\n return (data: unknown) => !getter(data)\n}\n\n// operator exists (looks like a function because it has no left operand)\nexport const exists = (path: JSONPath) => {\n const getter = get(path)\n return (data: unknown) => getter(data) !== undefined\n}\n\nexport const limit =\n (count: number) =>\n <T>(data: T[]) =>\n data.slice(0, count)\n\nexport const keys = () => Object.keys\n\nexport const values = () => Object.values\n\nexport const prod = () => (data: number[]) => data.reduce((a, b) => a * b)\n\nexport const sum = () => (data: number[]) => data.reduce((a, b) => a + b)\n\nexport const average = () => (data: number[]) => sum()(data) / data.length\n\nexport const min = () => (data: number[]) => Math.min(...data)\n\nexport const max = () => (data: number[]) => Math.max(...data)\n\nexport const abs = () => Math.abs\n\nexport const round =\n (digits = 0) =>\n (data: number) => {\n const num = Math.round(Number(data + 'e' + digits))\n return Number(num + 'e' + -digits)\n }\n\nexport const size =\n () =>\n <T>(data: T[]) =>\n data.length\n","import { JSONQuery, Operator, OperatorMap } from './types'\nimport { get } from './functions'\nimport { isString } from './is'\nimport { compile } from './compile'\n\nexport const createOperatorCompiler =\n (op: Operator, textRule = false) =>\n (left: JSONQuery, right: JSONQuery) => {\n // textRule is a special rule: relational operators interpret a string\n // on the right side as a text and not a path\n const a = compile(left)\n const b = textRule && isString(right) ? () => right : compile(right)\n return (data: unknown) => op(a(data), b(data))\n }\n\nconst mapValues = <T, U>(object: Record<string, T>, callback: (value: T) => U) =>\n Object.keys(object).reduce((res, key) => {\n res[key] = callback(object[key])\n\n return res\n }, {})\n\nexport const arithmeticOperators: Record<string, Operator> = {\n '+': (a: number, b: number) => a + b,\n '-': (a: number, b: number) => a - b,\n '*': (a: number, b: number) => a * b,\n '/': (a: number, b: number) => a / b,\n '^': (a: number, b: number) => a ** b,\n '%': (a: number, b: number) => a % b\n}\n\nexport const logicalOperators: Record<string, Operator> = {\n and: (a, b) => a && b,\n or: (a, b) => a || b\n}\n\nexport const relationalOperators: Record<string, Operator> = {\n '==': (a, b) => a === b, // we use strict comparison\n '>': (a, b) => a > b,\n '>=': (a, b) => a >= b,\n '<': (a, b) => a < b,\n '<=': (a, b) => a <= b,\n '!=': (a, b) => a !== b // we use strict comparison\n}\n\nexport const coreOperators: OperatorMap = {\n ...mapValues(arithmeticOperators, createOperatorCompiler),\n ...mapValues(logicalOperators, createOperatorCompiler),\n ...mapValues(relationalOperators, (value) => createOperatorCompiler(value, true)),\n\n in: (path: string, values: string[]) => {\n const getter = get(path)\n return (data: unknown) => values.includes(getter(data))\n },\n\n 'not in': (path: string, values: string[]) => {\n const getter = get(path)\n return (data: unknown) => !values.includes(getter(data))\n },\n\n regex: (path: string, expression: string, options?: string) => {\n const regex = new RegExp(expression, options)\n const getter = get(path)\n return (data: unknown) => regex.test(getter(data) as string)\n }\n}\n","import {\n Evaluator,\n FunctionsMap,\n JSONQuery,\n JSONQueryFunction,\n JSONQueryObject,\n JSONQueryOperator,\n JSONQueryOptions,\n JSONQueryPipe,\n OperatorMap\n} from './types'\nimport { isArray, isObject, isString } from './is'\nimport * as coreFunctions from './functions'\nimport { get, object, pipe } from './functions'\nimport { coreOperators } from './operators'\n\nconst functionsStack: FunctionsMap[] = [coreFunctions]\nconst operatorsStack: OperatorMap[] = [coreOperators]\n\nexport function compile(query: JSONQuery, options?: JSONQueryOptions): Evaluator {\n functionsStack.unshift({ ...functionsStack[0], ...options?.functions })\n operatorsStack.unshift({ ...operatorsStack[0], ...options?.operators })\n\n try {\n return _compile(query)\n } finally {\n functionsStack.shift()\n operatorsStack.shift()\n }\n}\n\nfunction _compile(query: JSONQuery): Evaluator {\n // object\n if (isObject(query)) {\n return object(query as JSONQueryObject)\n }\n\n if (isArray(query)) {\n // function\n const [fnName, ...args] = query as unknown as JSONQueryFunction\n const fn = functionsStack[0][fnName]\n if (fn) {\n return fn(...args)\n }\n\n // operator\n const [left, opName, ...right] = query as unknown as JSONQueryOperator\n const op = operatorsStack[0][opName]\n if (op) {\n return op(left, ...right)\n }\n\n // pipe\n return pipe(query as JSONQueryPipe)\n }\n\n // property\n if (isString(query)) {\n return get(query)\n }\n\n // value\n return () => query\n}\n","import { JSONQuery, JSONQueryOptions } from './types'\nimport { compile } from './compile'\n\nexport function jsonquery(data: unknown, query: JSONQuery, options?: JSONQueryOptions): unknown {\n return compile(query, options)(data)\n}\n"],"names":["isArray","value","isObject","isString","get","path","data","prop","string","text","pipe","entries","_entries","entry","compile","evaluator","object","query","getters","key","obj","getter","map","callback","_callback","filter","predicate","_predicate","sort","direction","sign","compare","itemA","itemB","a","b","pick","paths","item","_pick","out","groupBy","res","keyBy","flatten","uniq","uniqBy","groups","not","exists","limit","count","keys","values","prod","sum","average","min","max","abs","round","digits","size","createOperatorCompiler","op","textRule","left","right","mapValues","arithmeticOperators","logicalOperators","relationalOperators","coreOperators","expression","options","regex","functionsStack","coreFunctions","operatorsStack","_compile","fnName","args","fn","opName","jsonquery"],"mappings":"AAAO,MAAMA,IAAU,CAAIC,MAAiC,MAAM,QAAQA,CAAK,GAElEC,IAAW,CAACD,MACvBA,KAAS,OAAOA,KAAU,YAAY,CAACD,EAAQC,CAAK,GAEzCE,IAAW,CAACF,MAAoC,OAAOA,KAAU,UCDjEG,IAAM,CAACC,MAClBL,EAAQK,CAAI,IACR,CAACC,MAAkB;AACjB,MAAIL,IAAQK;AAEZ,aAAWC,KAAQF;AACjB,IAAAJ,IAAQA,KAAA,gBAAAA,EAAQM;AAGX,SAAAN;AACT,IACA,CAACK,MAAkBA,KAAA,gBAAAA,EAAOD,IAEnBG,IAAS,CAACC,MAAiB,MAAMA,GAEjCC,IAAO,CAACC,MAAyB;AAC5C,QAAMC,IAAWD,EAAQ,IAAI,CAACE,MAAUC,EAAQD,CAAK,CAAC;AAC/C,SAAA,CAACP,MAAkBM,EAAS,OAAO,CAACN,GAAMS,MAAcA,EAAUT,CAAI,GAAGA,CAAI;AACtF,GAEaU,IAAS,CAACC,MAA2B;AAChD,QAAMC,IAAoB,OAAO,KAAKD,CAAK,EAAE,IAAI,CAACE,MAAQ,CAACA,GAAKL,EAAQG,EAAME,CAAG,CAAC,CAAC,CAAC;AAEpF,SAAO,CAACb,MAAkB;AACxB,UAAMc,IAAM,CAAA;AACJ,WAAAF,EAAA,QAAQ,CAAC,CAACC,GAAKE,CAAM,MAAOD,EAAID,CAAG,IAAIE,EAAOf,CAAI,CAAE,GACrDc;AAAA,EAAA;AAEX,GAEaE,IAAM,CAAIC,MAAwB;AACvC,QAAAC,IAAYV,EAAQS,CAAQ;AAClC,SAAO,CAACjB,MAAcA,EAAK,IAAIkB,CAAS;AAC1C,GAEaC,IAAS,CAAIC,MAAyB;AAC3C,QAAAC,IAAab,EAAQY,CAAS;AACpC,SAAO,CAACpB,MAAcA,EAAK,OAAOqB,CAAU;AAC9C,GAEaC,IAAO,CAAIvB,IAAgC,IAAIwB,MAA+B;AACnF,QAAAR,IAASjB,EAAIC,CAAI,GACjByB,IAAOD,MAAc,SAAS,KAAK;AAEhC,WAAAE,EAAQC,GAAgBC,GAAgB;AACzC,UAAAC,IAAIb,EAAOW,CAAK,GAChBG,IAAId,EAAOY,CAAK;AACtB,WAAOC,IAAIC,IAAIL,IAAOI,IAAIC,IAAI,CAACL,IAAO;AAAA,EACxC;AAEA,SAAO,CAACxB,MAAcA,EAAK,MAAM,EAAE,KAAKyB,CAAO;AACjD,GAEaK,IAAO,IAAIC,MAAuC;AAC7D,QAAMnB,IAAoBmB,EAAM,IAAI,CAAChC,MAAS;AAAA,IAC5CF,EAASE,CAAI,IAAIA,IAAOA,EAAKA,EAAK,SAAS,CAAC;AAAA,IAC5CD,EAAIC,CAAI;AAAA,EAAA,CACT;AAED,SAAO,CAACC,MACFN,EAAQM,CAAI,IACPA,EAAK,IAAI,CAACgC,MAAkCC,EAAMD,GAAMpB,CAAO,CAAC,IAGlEqB,EAAMjC,GAAMY,CAAO;AAE9B,GAEMqB,IAAQ,CAACvB,GAAiCE,MAA+B;AAC7E,QAAMsB,IAAM,CAAA;AAEZ,SAAAtB,EAAQ,QAAQ,CAAC,CAACC,GAAKE,CAAM,MAAM;AAC7B,IAAAmB,EAAArB,CAAG,IAAIE,EAAOL,CAAM;AAAA,EAAA,CACzB,GAEMwB;AACT,GAEaC,IAAU,CAAIpC,MAAkC;AACrD,QAAAgB,IAASjB,EAAIC,CAAI;AAEvB,SAAO,CAACC,MAAc;AACpB,UAAMoC,IAAM,CAAA;AAEZ,eAAWJ,KAAQhC,GAAM;AACjB,YAAAL,IAAQoB,EAAOiB,CAAI;AACrB,MAAAI,EAAIzC,CAAK,IACPyC,EAAAzC,CAAK,EAAE,KAAKqC,CAAI,IAEhBI,EAAAzC,CAAK,IAAI,CAACqC,CAAI;AAAA,IAEtB;AAEO,WAAAI;AAAA,EAAA;AAEX,GAEaC,IAAQ,CAAItC,MAAkC;AACnD,QAAAgB,IAASjB,EAAIC,CAAI;AAEvB,SAAO,CAACC,MAAc;AACpB,UAAMoC,IAAM,CAAA;AAEP,WAAApC,EAAA,QAAQ,CAACgC,MAAS;AACf,YAAArC,IAAQoB,EAAOiB,CAAI;AACzB,MAAAI,EAAIzC,CAAK,IAAIyC,EAAIzC,CAAK,KAAKqC;AAAA,IAAA,CAC5B,GAEMI;AAAA,EAAA;AAEX,GAEaE,IAAU,MAAM,CAACtC,MAAoBA,EAAK,KAAK,GAE/CuC,IACX,MACA,CAAIvC,MAAc,CAAC,GAAG,IAAI,IAAIA,CAAI,CAAC,GAExBwC,IACX,CAAIzC,MACJ,CAACC,MACC,OAAO,OAAOmC,EAAQpC,CAAI,EAAEC,CAAI,CAAC,EAAE,IAAI,CAACyC,MAAWA,EAAO,CAAC,CAAC,GAGnDC,IAAM,CAAC/B,MAAqB;AACjC,QAAAI,IAASP,EAAQG,CAAK;AAC5B,SAAO,CAACX,MAAkB,CAACe,EAAOf,CAAI;AACxC,GAGa2C,IAAS,CAAC5C,MAAmB;AAClC,QAAAgB,IAASjB,EAAIC,CAAI;AACvB,SAAO,CAACC,MAAkBe,EAAOf,CAAI,MAAM;AAC7C,GAEa4C,IACX,CAACC,MACD,CAAI7C,MACFA,EAAK,MAAM,GAAG6C,CAAK,GAEVC,IAAO,MAAM,OAAO,MAEpBC,IAAS,MAAM,OAAO,QAEtBC,IAAO,MAAM,CAAChD,MAAmBA,EAAK,OAAO,CAAC4B,GAAGC,MAAMD,IAAIC,CAAC,GAE5DoB,IAAM,MAAM,CAACjD,MAAmBA,EAAK,OAAO,CAAC4B,GAAGC,MAAMD,IAAIC,CAAC,GAE3DqB,IAAU,MAAM,CAAClD,MAAmBiD,EAAM,EAAAjD,CAAI,IAAIA,EAAK,QAEvDmD,IAAM,MAAM,CAACnD,MAAmB,KAAK,IAAI,GAAGA,CAAI,GAEhDoD,IAAM,MAAM,CAACpD,MAAmB,KAAK,IAAI,GAAGA,CAAI,GAEhDqD,IAAM,MAAM,KAAK,KAEjBC,IACX,CAACC,IAAS,MACV,CAACvD,MAEQ,EADK,KAAK,MAAM,EAAOA,IAAO,MAAMuD,EAAO,IAC9B,MAAM,CAACA,IAGlBC,IACX,MACA,CAAIxD,MACFA,EAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;8CCrKIyD,IACX,CAACC,GAAcC,IAAW,OAC1B,CAACC,GAAiBC,MAAqB;AAG/B,QAAAjC,IAAIpB,EAAQoD,CAAI,GAChB/B,IAAI8B,KAAY9D,EAASgE,CAAK,IAAI,MAAMA,IAAQrD,EAAQqD,CAAK;AAC5D,SAAA,CAAC7D,MAAkB0D,EAAG9B,EAAE5B,CAAI,GAAG6B,EAAE7B,CAAI,CAAC;AAC/C,GAEI8D,IAAY,CAAOpD,GAA2BO,MAClD,OAAO,KAAKP,CAAM,EAAE,OAAO,CAAC0B,GAAKvB,OAC/BuB,EAAIvB,CAAG,IAAII,EAASP,EAAOG,CAAG,CAAC,GAExBuB,IACN,CAAE,CAAA,GAEM2B,IAAgD;AAAA,EAC3D,KAAK,CAACnC,GAAWC,MAAcD,IAAIC;AAAA,EACnC,KAAK,CAACD,GAAWC,MAAcD,IAAIC;AAAA,EACnC,KAAK,CAACD,GAAWC,MAAcD,IAAIC;AAAA,EACnC,KAAK,CAACD,GAAWC,MAAcD,IAAIC;AAAA,EACnC,KAAK,CAACD,GAAWC,MAAcD,KAAKC;AAAA,EACpC,KAAK,CAACD,GAAWC,MAAcD,IAAIC;AACrC,GAEamC,IAA6C;AAAA,EACxD,KAAK,CAACpC,GAAGC,MAAMD,KAAKC;AAAA,EACpB,IAAI,CAACD,GAAGC,MAAMD,KAAKC;AACrB,GAEaoC,IAAgD;AAAA,EAC3D,MAAM,CAACrC,GAAGC,MAAMD,MAAMC;AAAA;AAAA,EACtB,KAAK,CAACD,GAAGC,MAAMD,IAAIC;AAAA,EACnB,MAAM,CAACD,GAAGC,MAAMD,KAAKC;AAAA,EACrB,KAAK,CAACD,GAAGC,MAAMD,IAAIC;AAAA,EACnB,MAAM,CAACD,GAAGC,MAAMD,KAAKC;AAAA,EACrB,MAAM,CAACD,GAAGC,MAAMD,MAAMC;AAAA;AACxB,GAEaqC,IAA6B;AAAA,EACxC,GAAGJ,EAAUC,GAAqBN,CAAsB;AAAA,EACxD,GAAGK,EAAUE,GAAkBP,CAAsB;AAAA,EACrD,GAAGK,EAAUG,GAAqB,CAACtE,MAAU8D,EAAuB9D,GAAO,EAAI,CAAC;AAAA,EAEhF,IAAI,CAACI,GAAcgD,MAAqB;AAChC,UAAAhC,IAASjB,EAAIC,CAAI;AACvB,WAAO,CAACC,MAAkB+C,EAAO,SAAShC,EAAOf,CAAI,CAAC;AAAA,EACxD;AAAA,EAEA,UAAU,CAACD,GAAcgD,MAAqB;AACtC,UAAAhC,IAASjB,EAAIC,CAAI;AACvB,WAAO,CAACC,MAAkB,CAAC+C,EAAO,SAAShC,EAAOf,CAAI,CAAC;AAAA,EACzD;AAAA,EAEA,OAAO,CAACD,GAAcoE,GAAoBC,MAAqB;AAC7D,UAAMC,IAAQ,IAAI,OAAOF,GAAYC,CAAO,GACtCrD,IAASjB,EAAIC,CAAI;AACvB,WAAO,CAACC,MAAkBqE,EAAM,KAAKtD,EAAOf,CAAI,CAAW;AAAA,EAC7D;AACF,GCjDMsE,IAAiC,CAACC,CAAa,GAC/CC,IAAgC,CAACN,CAAa;AAEpC,SAAA1D,EAAQG,GAAkByD,GAAuC;AAChE,EAAAE,EAAA,QAAQ,EAAE,GAAGA,EAAe,CAAC,GAAG,GAAGF,KAAA,gBAAAA,EAAS,UAAA,CAAW,GACvDI,EAAA,QAAQ,EAAE,GAAGA,EAAe,CAAC,GAAG,GAAGJ,KAAA,gBAAAA,EAAS,UAAA,CAAW;AAElE,MAAA;AACF,WAAOK,EAAS9D,CAAK;AAAA,EAAA,UACrB;AACA,IAAA2D,EAAe,MAAM,GACrBE,EAAe,MAAM;AAAA,EACvB;AACF;AAEA,SAASC,EAAS9D,GAA6B;AAEzC,MAAAf,EAASe,CAAK;AAChB,WAAOD,EAAOC,CAAwB;AAGpC,MAAAjB,EAAQiB,CAAK,GAAG;AAElB,UAAM,CAAC+D,GAAQ,GAAGC,CAAI,IAAIhE,GACpBiE,IAAKN,EAAe,CAAC,EAAEI,CAAM;AACnC,QAAIE;AACK,aAAAA,EAAG,GAAGD,CAAI;AAInB,UAAM,CAACf,GAAMiB,GAAQ,GAAGhB,CAAK,IAAIlD,GAC3B+C,IAAKc,EAAe,CAAC,EAAEK,CAAM;AACnC,WAAInB,IACKA,EAAGE,GAAM,GAAGC,CAAK,IAInBzD,EAAKO,CAAsB;AAAA,EACpC;AAGI,SAAAd,EAASc,CAAK,IACTb,EAAIa,CAAK,IAIX,MAAMA;AACf;AC5DgB,SAAAmE,EAAU9E,GAAeW,GAAkByD,GAAqC;AAC9F,SAAO5D,EAAQG,GAAOyD,CAAO,EAAEpE,CAAI;AACrC;"}
{"version":3,"file":"jsonquery.js","sources":["../src/is.ts","../src/functions.ts","../src/operators.ts","../src/compile.ts","../src/jsonquery.ts"],"sourcesContent":["export const isArray = <T>(value: unknown): value is T[] => Array.isArray(value)\n\nexport const isObject = (value: unknown): value is object =>\n value && typeof value === 'object' && !isArray(value)\n\nexport const isString = (value: unknown): value is string => typeof value === 'string'\n","import { Getter, JSONPath, JSONProperty, JSONQuery, JSONQueryObject } from './types'\nimport { compile } from './compile'\nimport { isArray, isString } from './is'\n\nexport const get = (path: JSONPath | JSONProperty) =>\n isArray(path)\n ? (data: unknown) => {\n let value = data\n\n for (const prop of path) {\n value = value?.[prop]\n }\n\n return value\n }\n : (data: unknown) => data?.[path]\n\nexport const string = (text: string) => () => text\n\nexport const pipe = (entries: JSONQuery[]) => {\n const _entries = entries.map((entry) => compile(entry))\n return (data: unknown) => _entries.reduce((data, evaluator) => evaluator(data), data)\n}\n\nexport const object = (query: JSONQueryObject) => {\n const getters: Getter[] = Object.keys(query).map((key) => [key, compile(query[key])])\n\n return (data: unknown) => {\n const obj = {}\n getters.forEach(([key, getter]) => (obj[key] = getter(data)))\n return obj\n }\n}\n\nexport const map = <T>(callback: JSONQuery) => {\n const _callback = compile(callback)\n return (data: T[]) => data.map(_callback)\n}\n\nexport const filter = <T>(predicate: JSONQuery) => {\n const _predicate = compile(predicate)\n return (data: T[]) => data.filter(_predicate)\n}\n\nexport const sort = <T>(path: JSONPath | JSONProperty = [], direction?: 'asc' | 'desc') => {\n const getter = get(path)\n const sign = direction === 'desc' ? -1 : 1\n\n function compare(itemA: unknown, itemB: unknown) {\n const a = getter(itemA)\n const b = getter(itemB)\n return a > b ? sign : a < b ? -sign : 0\n }\n\n return (data: T[]) => data.slice().sort(compare)\n}\n\nexport const pick = (...paths: (JSONPath | JSONProperty)[]) => {\n const getters: Getter[] = paths.map((path) => [\n isString(path) ? path : path[path.length - 1],\n get(path)\n ])\n\n return (data: Record<string, unknown>): unknown => {\n if (isArray(data)) {\n return data.map((item: Record<string, unknown>) => _pick(item, getters))\n }\n\n return _pick(data, getters)\n }\n}\n\nconst _pick = (object: Record<string, unknown>, getters: Getter[]): unknown => {\n const out = {}\n\n getters.forEach(([key, getter]) => {\n out[key] = getter(object)\n })\n\n return out\n}\n\nexport const groupBy = <T>(path: JSONPath | JSONProperty) => {\n const getter = get(path)\n\n return (data: T[]) => {\n const res = {}\n\n for (const item of data) {\n const value = getter(item) as string\n if (res[value]) {\n res[value].push(item)\n } else {\n res[value] = [item]\n }\n }\n\n return res\n }\n}\n\nexport const keyBy = <T>(path: JSONPath | JSONProperty) => {\n const getter = get(path)\n\n return (data: T[]) => {\n const res = {}\n\n data.forEach((item) => {\n const value = getter(item) as string\n res[value] = res[value] ?? item\n })\n\n return res\n }\n}\n\nexport const flatten = () => (data: unknown[]) => data.flat()\n\nexport const uniq =\n () =>\n <T>(data: T[]) => [...new Set(data)]\n\nexport const uniqBy =\n <T>(path: JSONPath | JSONProperty) =>\n (data: T[]): T[] =>\n Object.values(groupBy(path)(data)).map((groups) => groups[0])\n\n// operator not (looks like a function because it has no left operand)\nexport const not = (query: JSONQuery) => {\n const getter = compile(query)\n return (data: unknown) => !getter(data)\n}\n\n// operator exists (looks like a function because it has no left operand)\nexport const exists = (path: JSONPath) => {\n const getter = get(path)\n return (data: unknown) => getter(data) !== undefined\n}\n\nexport const limit =\n (count: number) =>\n <T>(data: T[]) =>\n data.slice(0, count)\n\nexport const keys = () => Object.keys\n\nexport const values = () => Object.values\n\nexport const prod = () => (data: number[]) => data.reduce((a, b) => a * b)\n\nexport const sum = () => (data: number[]) => data.reduce((a, b) => a + b)\n\nexport const average = () => (data: number[]) => sum()(data) / data.length\n\nexport const min = () => (data: number[]) => Math.min(...data)\n\nexport const max = () => (data: number[]) => Math.max(...data)\n\nexport const abs = () => Math.abs\n\nexport const round =\n (digits = 0) =>\n (data: number) => {\n const num = Math.round(Number(data + 'e' + digits))\n return Number(num + 'e' + -digits)\n }\n\nexport const size =\n () =>\n <T>(data: T[]) =>\n data.length\n","import { JSONQuery, Operator, OperatorMap } from './types'\nimport { get } from './functions'\nimport { isString } from './is'\nimport { compile } from './compile'\n\nexport const createOperatorCompiler =\n (op: Operator, textRule = false) =>\n (left: JSONQuery, right: JSONQuery) => {\n // textRule is a special rule: relational operators interpret a string\n // on the right side as a text and not a path\n const a = compile(left)\n const b = textRule && isString(right) ? () => right : compile(right)\n return (data: unknown) => op(a(data), b(data))\n }\n\nconst mapValues = <T, U>(object: Record<string, T>, callback: (value: T) => U) =>\n Object.keys(object).reduce((res, key) => {\n res[key] = callback(object[key])\n\n return res\n }, {})\n\nexport const arithmeticOperators: Record<string, Operator> = {\n '+': (a: number, b: number) => a + b,\n '-': (a: number, b: number) => a - b,\n '*': (a: number, b: number) => a * b,\n '/': (a: number, b: number) => a / b,\n '^': (a: number, b: number) => a ** b,\n '%': (a: number, b: number) => a % b\n}\n\nexport const logicalOperators: Record<string, Operator> = {\n and: (a, b) => a && b,\n or: (a, b) => a || b\n}\n\nexport const relationalOperators: Record<string, Operator> = {\n '==': (a, b) => a === b, // we use strict comparison\n '>': (a, b) => a > b,\n '>=': (a, b) => a >= b,\n '<': (a, b) => a < b,\n '<=': (a, b) => a <= b,\n '!=': (a, b) => a !== b // we use strict comparison\n}\n\nexport const coreOperators: OperatorMap = {\n ...mapValues(arithmeticOperators, createOperatorCompiler),\n ...mapValues(logicalOperators, createOperatorCompiler),\n ...mapValues(relationalOperators, (value) => createOperatorCompiler(value, true)),\n\n in: (path: string, values: string[]) => {\n const getter = get(path)\n return (data: unknown) => values.includes(getter(data))\n },\n\n 'not in': (path: string, values: string[]) => {\n const getter = get(path)\n return (data: unknown) => !values.includes(getter(data))\n },\n\n regex: (path: string, expression: string, options?: string) => {\n const regex = new RegExp(expression, options)\n const getter = get(path)\n return (data: unknown) => regex.test(getter(data) as string)\n }\n}\n","import {\n Evaluator,\n FunctionsMap,\n JSONQuery,\n JSONQueryFunction,\n JSONQueryObject,\n JSONQueryOperator,\n JSONQueryOptions,\n JSONQueryPipe,\n OperatorMap\n} from './types'\nimport { isArray, isObject, isString } from './is'\nimport * as coreFunctions from './functions'\nimport { get, object, pipe } from './functions'\nimport { coreOperators } from './operators'\n\nconst functionsStack: FunctionsMap[] = [coreFunctions]\nconst operatorsStack: OperatorMap[] = [coreOperators]\n\nexport function compile(query: JSONQuery, options?: JSONQueryOptions): Evaluator {\n functionsStack.unshift({ ...functionsStack[0], ...options?.functions })\n operatorsStack.unshift({ ...operatorsStack[0], ...options?.operators })\n\n try {\n const exec = _compile(query)\n\n return (data) => {\n try {\n return exec(data)\n } catch (err) {\n // attach a stack to the error\n err.jsonquery = [{ data, query }, ...(err.jsonquery ?? [])]\n\n throw err\n }\n }\n } finally {\n functionsStack.shift()\n operatorsStack.shift()\n }\n}\n\nfunction _compile(query: JSONQuery): Evaluator {\n // object\n if (isObject(query)) {\n return object(query as JSONQueryObject)\n }\n\n if (isArray(query)) {\n // function\n const [fnName, ...args] = query as unknown as JSONQueryFunction\n const fn = functionsStack[0][fnName]\n if (fn) {\n return fn(...args)\n }\n\n // operator\n const [left, opName, ...right] = query as unknown as JSONQueryOperator\n const op = operatorsStack[0][opName]\n if (op) {\n return op(left, ...right)\n }\n\n // pipe\n return pipe(query as JSONQueryPipe)\n }\n\n // property\n if (isString(query)) {\n return get(query)\n }\n\n // value\n return () => query\n}\n","import { JSONQuery, JSONQueryOptions } from './types'\nimport { compile } from './compile'\n\nexport function jsonquery(data: unknown, query: JSONQuery, options?: JSONQueryOptions): unknown {\n return compile(query, options)(data)\n}\n"],"names":["isArray","value","isObject","isString","get","path","data","prop","string","text","pipe","entries","_entries","entry","compile","evaluator","object","query","getters","key","obj","getter","map","callback","_callback","filter","predicate","_predicate","sort","direction","sign","compare","itemA","itemB","a","b","pick","paths","item","_pick","out","groupBy","res","keyBy","flatten","uniq","uniqBy","groups","not","exists","limit","count","keys","values","prod","sum","average","min","max","abs","round","digits","size","createOperatorCompiler","op","textRule","left","right","mapValues","arithmeticOperators","logicalOperators","relationalOperators","coreOperators","expression","options","regex","functionsStack","coreFunctions","operatorsStack","exec","_compile","err","fnName","args","fn","opName","jsonquery"],"mappings":"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"}
{
"name": "@josdejong/jsonquery",
"version": "1.1.6",
"version": "1.2.0",
"description": "A small, flexible, and expandable JSON query language",

@@ -5,0 +5,0 @@ "keywords": [

+172
-25

@@ -117,30 +117,49 @@ # JSON Query

- `options` is an optional object that can contain the following properties:
- `functions` is an optional map with extra function creators. A function creator has optional arguments as input and must return a function that can be used to process the query data. For example:
```js
const options = {
functions: {
// usage example: ["times", 3]
times: (value) => (data) => data.map((item) => item * value)
}
}
```
- `operators` is an optional map with extra operator creators. An operator creator receives the left and right side queries as input, and must return a function that implements the operator. Example:
- `functions` is an optional map with custom function creators. A function creator has optional arguments as input and must return a function that can be used to process the query data. For example:
```js
const options = {
operators: {
// a loosely equal operator
// usage example: ["value", "~=", 2]
'~=': (left, right) => {
const a = compile(left)
const b = compile(right)
return (data) => a(data) == b(data)
}
}
}
```
```js
const options = {
functions: {
// usage example: ["times", 3]
times: (value) => (data) => data.map((item) => item * value)
}
}
```
Example:
If the parameters are not a primitive value but can be a query themselves, the function `compile` can be used to compile them. For example, the actual implementation of the function `filter` is the following:
```js
const options = {
functions: {
// usage example: ["filter", ["age", ">", 20 ]]
filter: (predicate) => {
const _predicate = compile(predicate)
return (data) => data.filter(_predicate)
}
}
}
```
You can have a look at the source code of the functions in `/src/functions.ts` for more examples.
- `operators` is an optional map with custom operator creators. An operator creator receives the left and right side queries as input, and must return a function that implements the operator. Example:
```js
const options = {
operators: {
// a loosely equal operator
// usage example: ["value", "~=", 2]
'~=': (left, right) => {
const a = compile(left)
const b = compile(right)
return (data) => a(data) == b(data)
}
}
}
```
You can have a look at the source code of the functions in `/src/operators.ts` for more examples.
Here an example of using the function `jsonquery`:
```js

@@ -190,2 +209,53 @@ import { jsonquery } from '@josdejong/jsonquery'

## error handling
When executing a query throws an error, the library attaches a stack to the error message which can give insight in what went wrong. The stack can be found at the property `error.jsonquery` and has type `Array<{ data: unknown, query: JSONQuery }>`.
```js
const data = [
{ "name": "Chris", "age": 23, "scores": [7.2, 5, 8.0] },
{ "name": "Emily", "age": 19 }, // scores is missing here!
{ "name": "Joe", "age": 32, "scores": [6.1, 8.1] }
]
try {
jsonquery(data, [
["pick", "age", "scores"],
["map", ["scores", ["sum"]]]
])
} catch (err) {
console.log(err.jsonquery)
// error stack:
// [
// {
// "data": [
// { "name": "Chris", "age": 23, "scores": [7.2, 5, 8.0] },
// { "name": "Emily", "age": 19 },
// { "name": "Joe", "age": 32, "scores": [6.1, 8.1] }
// ],
// "query": [
// ["pick", "age", "scores"],
// ["map", ["scores", ["sum"]]]
// ]
// },
// {
// "data": [
// { "age": 23, "scores": [7.2, 5, 8.0] },
// { "age": 19 },
// { "age": 32, "scores": [6.1, 8.1] }
// ],
// "query": ["map", ["scores", ["sum"]]]
// },
// {
// "data": {"age": 19},
// "query": ["scores", ["sum"]]
// },
// {
// "data" : undefined,
// "query": ["sum"]
// }
// ]
}
```
## Syntax

@@ -305,2 +375,3 @@

```
There is one special case regarding paths:

@@ -310,2 +381,3 @@

f
```js

@@ -1326,2 +1398,77 @@ const data = { sort: 42 }

## Limitations
The JSON Query language has some limitations, pitfalls, and gotchas.
Though the language is easy to learn and understand, it is relatively verbose due to the need for quotes around all keys, and the need for a lot of arrays in square brackets `[...]`. This is a consequence of expressing a query using JSON whilst wanting to keep the language concise.
The use of arrays `[...]` is quite overloaded. An array can hold a function call, operator, pipe, or path with properties. Given a query being an array containing three strings `[string, string, string]` for example, it's meaning can only be determined by looking up whether the first string matches a known function, then looking up whether the second string matches a known operator, and lastly conclude that it is a path with properties. When making a mistake, the error message you get is mostly unhelpful, and the best way to debug is to build your query step by step, validating that it works after every step.
What can also be confusing at first is to understand how data is piped through the query. A traditional function call is for example `abs(myValue)`, so you may expect to have to write this in JSON Query like `["abs", "myValue"]`. However, JSON Query has a functional approach where we create a pipeline like: `data -> abs -> result`. So, to get the absolute value of a property `myValue`, you will have to write a pipe first getting this property and then calling abs: `[["get", "myValue"], ["abs"]]"`.
### Gotchas
Here some gotchas.
1. Having an problem halfway the query, resulting in a vague error. In the following example, the first part of the query results in `undefined`, and then we try to filter that, resulting in an error:
```js
const data = {
"friends": [
{"name": "Chris", "age": 23, "city": "New York"},
{"name": "Emily", "age": 19, "city": "Atlanta"},
{"name": "Joe", "age": 16, "city": "New York"}
]
}
const result = jsonquery(data, [
["get", "friiends"],
["filter", ["city", "==", "New York"]]
])
// result: "Error: e is undefined"
// expected: an array with two items
```
2. Making a typo in a function name, which then is interpreted as getting a property. This results in vague output or in an error. In the following example, the property `"filte"` is read from the data, resulting in `undefined`. After that, the property `"city"` is read from `undefined`, resulting in `undefined`, and lastly, we check whether `undefined` is equal to the string `"New York"`, which is not the case, so, the query returns `false`.
```js
const data = [
{"name": "Chris", "age": 23, "city": "New York"},
{"name": "Emily", "age": 19, "city": "Atlanta"},
{"name": "Joe", "age": 16, "city": "New York"}
]
const result = jsonquery(data, ["filte", ["city", "==", "New York"]])
// result: the boolean value false
// expected: an array with two items
```
3. Making a typo in a property name, resulting in unexpected results.
```js
const data = [
{"name": "Chris", "age": 23, "city": "New York"},
{"name": "Emily", "age": 19, "city": "Atlanta"},
{"name": "Joe", "age": 16, "city": "New York"}
]
const result = jsonquery(data, ["filter", ["cities", "==", "New York"]])
// result: an empty array
// expected: an array with two items
```
4. Forgetting brackets around a nested query. In the following example, the filter condition has no brackets. Therefore, the property `"city"` is used as condition and the arguments `"=="` and `"New York"` are ignored.
```js
const data = [
{"name": "Chris", "age": 23, "city": "New York"},
{"name": "Emily", "age": 19, "city": "Atlanta"},
{"name": "Joe", "age": 16, "city": "New York"}
]
const result = jsonquery(data, ["filter", "age", ">", 18])
// result: the original data
// expected: an array with two items
```
## Development

@@ -1328,0 +1475,0 @@