json-p3 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/json-p3.cjs.js +312 -72
- package/dist/json-p3.esm.js +312 -73
- package/dist/json-p3.iife.js +312 -72
- package/dist/json-p3.iife.min.js +1 -1
- package/dist/json-p3.iife.min.js.map +1 -1
- package/dist/path/environment.d.ts +35 -10
- package/dist/path/expression.d.ts +1 -0
- package/dist/path/index.d.ts +18 -0
- package/dist/path/node.d.ts +1 -4
- package/dist/path/parse.d.ts +5 -2
- package/dist/path/path.d.ts +6 -0
- package/dist/path/selectors.d.ts +25 -9
- package/dist/path/types.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +27 -27
package/dist/json-p3.iife.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* json-p3 version 0.
|
|
2
|
+
* json-p3 version 0.3.1
|
|
3
3
|
* https://github.com/jg-rp/json-p3
|
|
4
4
|
*
|
|
5
5
|
* MIT License
|
|
@@ -646,10 +646,6 @@ var json_p3 = (function (exports) {
|
|
|
646
646
|
* The pair of a JSON value and its location found in the target JSON value.
|
|
647
647
|
*/
|
|
648
648
|
class JSONPathNode {
|
|
649
|
-
/**
|
|
650
|
-
* The normalized path to this node in the target JSON value.
|
|
651
|
-
*/
|
|
652
|
-
|
|
653
649
|
/**
|
|
654
650
|
* @param value - The JSON value found at _location_.
|
|
655
651
|
* @param location - The parts of a normalized path to _value_.
|
|
@@ -659,9 +655,12 @@ var json_p3 = (function (exports) {
|
|
|
659
655
|
this.value = value;
|
|
660
656
|
this.location = location;
|
|
661
657
|
this.root = root;
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
658
|
+
}
|
|
659
|
+
get path() {
|
|
660
|
+
return (
|
|
661
|
+
// eslint-disable-next-line prefer-template
|
|
662
|
+
"$" + this.location.map(s => isString(s) ? `['${s}']` : `[${s}]`).join("")
|
|
663
|
+
);
|
|
665
664
|
}
|
|
666
665
|
|
|
667
666
|
/**
|
|
@@ -913,7 +912,7 @@ var json_p3 = (function (exports) {
|
|
|
913
912
|
}
|
|
914
913
|
class RelativeQuery extends JSONPathQuery {
|
|
915
914
|
evaluate(context) {
|
|
916
|
-
return this.path.query(context.currentValue);
|
|
915
|
+
return context.lazy ? new JSONPathNodeList(Array.from(this.path.lazyQuery(context.currentValue))) : this.path.query(context.currentValue);
|
|
917
916
|
}
|
|
918
917
|
toString() {
|
|
919
918
|
return `@${this.path.toString().slice(1)}`;
|
|
@@ -921,7 +920,7 @@ var json_p3 = (function (exports) {
|
|
|
921
920
|
}
|
|
922
921
|
class RootQuery extends JSONPathQuery {
|
|
923
922
|
evaluate(context) {
|
|
924
|
-
return this.path.query(context.rootValue);
|
|
923
|
+
return context.lazy ? new JSONPathNodeList(Array.from(this.path.lazyQuery(context.rootValue))) : this.path.query(context.rootValue);
|
|
925
924
|
}
|
|
926
925
|
toString() {
|
|
927
926
|
return this.path.toString();
|
|
@@ -939,12 +938,26 @@ var json_p3 = (function (exports) {
|
|
|
939
938
|
if (!func) {
|
|
940
939
|
throw new UndefinedFilterFunctionError(`filter function '${this.name}' is undefined`, this.token);
|
|
941
940
|
}
|
|
942
|
-
const args = this.args.map(arg => arg.evaluate(context)).map((arg, idx) => func.argTypes[idx] !== FunctionExpressionType.NodesType && arg instanceof JSONPathNodeList ?
|
|
941
|
+
const args = this.args.map(arg => arg.evaluate(context)).map((arg, idx) => func.argTypes[idx] !== FunctionExpressionType.NodesType && arg instanceof JSONPathNodeList ? this.unpack_node_list(arg) : arg);
|
|
943
942
|
return func.call(...args);
|
|
944
943
|
}
|
|
945
944
|
toString() {
|
|
946
945
|
return `${this.name}(${this.args.map(e => e.toString()).join(", ")})`;
|
|
947
946
|
}
|
|
947
|
+
unpack_node_list(arg) {
|
|
948
|
+
switch (arg.length) {
|
|
949
|
+
case 0:
|
|
950
|
+
// If the query results in an empty node list, the argument
|
|
951
|
+
// is the special result Nothing.
|
|
952
|
+
return Nothing;
|
|
953
|
+
case 1:
|
|
954
|
+
// If the query results in a node list consisting of a single
|
|
955
|
+
// node, the argument is the value of the node
|
|
956
|
+
return arg.nodes[0].value;
|
|
957
|
+
default:
|
|
958
|
+
return arg;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
948
961
|
}
|
|
949
962
|
|
|
950
963
|
/**
|
|
@@ -1723,6 +1736,10 @@ var json_p3 = (function (exports) {
|
|
|
1723
1736
|
this.token = token;
|
|
1724
1737
|
}
|
|
1725
1738
|
|
|
1739
|
+
/**
|
|
1740
|
+
* @param nodes - Nodes matched by preceding selectors.
|
|
1741
|
+
*/
|
|
1742
|
+
|
|
1726
1743
|
/**
|
|
1727
1744
|
* @param nodes - Nodes matched by preceding selectors.
|
|
1728
1745
|
*/
|
|
@@ -1750,7 +1767,14 @@ var json_p3 = (function (exports) {
|
|
|
1750
1767
|
rv.push(new JSONPathNode(node.value[this.name], node.location.concat(this.name), node.root));
|
|
1751
1768
|
}
|
|
1752
1769
|
}
|
|
1753
|
-
return
|
|
1770
|
+
return rv;
|
|
1771
|
+
}
|
|
1772
|
+
*lazyResolve(nodes) {
|
|
1773
|
+
for (const node of nodes) {
|
|
1774
|
+
if (hasStringKey(node.value, this.name)) {
|
|
1775
|
+
yield new JSONPathNode(node.value[this.name], node.location.concat(this.name), node.root);
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1754
1778
|
}
|
|
1755
1779
|
toString() {
|
|
1756
1780
|
return this.shorthand ? `['${this.name}']` : `'${this.name}'`;
|
|
@@ -1780,7 +1804,17 @@ var json_p3 = (function (exports) {
|
|
|
1780
1804
|
}
|
|
1781
1805
|
}
|
|
1782
1806
|
}
|
|
1783
|
-
return
|
|
1807
|
+
return rv;
|
|
1808
|
+
}
|
|
1809
|
+
*lazyResolve(nodes) {
|
|
1810
|
+
for (const node of nodes) {
|
|
1811
|
+
if (isArray(node.value)) {
|
|
1812
|
+
const normIndex = this.normalizedIndex(node.value.length);
|
|
1813
|
+
if (normIndex in node.value) {
|
|
1814
|
+
yield new JSONPathNode(node.value[normIndex], node.location.concat(normIndex), node.root);
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1784
1818
|
}
|
|
1785
1819
|
toString() {
|
|
1786
1820
|
return String(this.index);
|
|
@@ -1808,7 +1842,15 @@ var json_p3 = (function (exports) {
|
|
|
1808
1842
|
rv.push(new JSONPathNode(value, node.location.concat(i), node.root));
|
|
1809
1843
|
}
|
|
1810
1844
|
}
|
|
1811
|
-
return
|
|
1845
|
+
return rv;
|
|
1846
|
+
}
|
|
1847
|
+
*lazyResolve(nodes) {
|
|
1848
|
+
for (const node of nodes) {
|
|
1849
|
+
if (!isArray(node.value)) continue;
|
|
1850
|
+
for (const [i, value] of this.slice(node.value, this.start, this.stop, this.step)) {
|
|
1851
|
+
yield new JSONPathNode(value, node.location.concat(i), node.root);
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1812
1854
|
}
|
|
1813
1855
|
toString() {
|
|
1814
1856
|
const start = this.start ? this.start : "";
|
|
@@ -1891,22 +1933,92 @@ var json_p3 = (function (exports) {
|
|
|
1891
1933
|
}
|
|
1892
1934
|
}
|
|
1893
1935
|
}
|
|
1894
|
-
return
|
|
1936
|
+
return rv;
|
|
1937
|
+
}
|
|
1938
|
+
*lazyResolve(nodes) {
|
|
1939
|
+
for (const node of nodes) {
|
|
1940
|
+
if (node.value instanceof String) continue;
|
|
1941
|
+
if (isArray(node.value)) {
|
|
1942
|
+
for (let i = 0; i < node.value.length; i++) {
|
|
1943
|
+
yield new JSONPathNode(node.value[i], node.location.concat(i), node.root);
|
|
1944
|
+
}
|
|
1945
|
+
} else if (isObject(node.value)) {
|
|
1946
|
+
for (const [key, value] of Object.entries(node.value)) {
|
|
1947
|
+
yield new JSONPathNode(value, node.location.concat(key), node.root);
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1895
1951
|
}
|
|
1896
1952
|
toString() {
|
|
1897
1953
|
return this.shorthand ? "[*]" : "*";
|
|
1898
1954
|
}
|
|
1899
1955
|
}
|
|
1900
1956
|
class RecursiveDescentSegment extends JSONPathSelector {
|
|
1957
|
+
constructor(environment, token, selector) {
|
|
1958
|
+
super(environment, token);
|
|
1959
|
+
this.environment = environment;
|
|
1960
|
+
this.token = token;
|
|
1961
|
+
this.selector = selector;
|
|
1962
|
+
}
|
|
1901
1963
|
resolve(nodes) {
|
|
1902
1964
|
const rv = [];
|
|
1903
1965
|
for (const node of nodes) {
|
|
1904
|
-
rv.push(node
|
|
1966
|
+
rv.push(node);
|
|
1967
|
+
for (const _node of this.visit(node)) {
|
|
1968
|
+
rv.push(_node);
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
return this.selector.resolve(rv);
|
|
1972
|
+
}
|
|
1973
|
+
*lazyResolve(nodes) {
|
|
1974
|
+
yield* this.selector.lazyResolve(this._lazyResolve(nodes));
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
1978
|
+
*_lazyResolve(nodes) {
|
|
1979
|
+
for (const _node of nodes) {
|
|
1980
|
+
const stack = [{
|
|
1981
|
+
node: _node,
|
|
1982
|
+
depth: 0
|
|
1983
|
+
}];
|
|
1984
|
+
yield _node;
|
|
1985
|
+
while (stack.length) {
|
|
1986
|
+
const {
|
|
1987
|
+
node: currentNode,
|
|
1988
|
+
depth
|
|
1989
|
+
} = stack.pop();
|
|
1990
|
+
if (depth >= this.environment.maxRecursionDepth) {
|
|
1991
|
+
throw new JSONPathRecursionLimitError("recursion limit reached", this.token);
|
|
1992
|
+
}
|
|
1993
|
+
if (currentNode.value instanceof String) continue;
|
|
1994
|
+
if (isArray(currentNode.value)) {
|
|
1995
|
+
for (let i = 0; i < currentNode.value.length; i++) {
|
|
1996
|
+
const __node = new JSONPathNode(currentNode.value[i], currentNode.location.concat(i), currentNode.root);
|
|
1997
|
+
yield __node;
|
|
1998
|
+
if (isObject(__node.value)) {
|
|
1999
|
+
stack.push({
|
|
2000
|
+
node: __node,
|
|
2001
|
+
depth: depth + 1
|
|
2002
|
+
});
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
} else if (isObject(currentNode.value)) {
|
|
2006
|
+
for (const [key, value] of Object.entries(currentNode.value)) {
|
|
2007
|
+
const __node = new JSONPathNode(value, currentNode.location.concat(key), currentNode.root);
|
|
2008
|
+
yield __node;
|
|
2009
|
+
if (isObject(__node.value)) {
|
|
2010
|
+
stack.push({
|
|
2011
|
+
node: __node,
|
|
2012
|
+
depth: depth + 1
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
1905
2018
|
}
|
|
1906
|
-
return new JSONPathNodeList(rv);
|
|
1907
2019
|
}
|
|
1908
2020
|
toString() {
|
|
1909
|
-
return
|
|
2021
|
+
return `..${this.selector.toString()}`;
|
|
1910
2022
|
}
|
|
1911
2023
|
visit(node) {
|
|
1912
2024
|
let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
@@ -1914,19 +2026,25 @@ var json_p3 = (function (exports) {
|
|
|
1914
2026
|
throw new JSONPathRecursionLimitError("recursion limit reached", this.token);
|
|
1915
2027
|
}
|
|
1916
2028
|
const rv = [];
|
|
1917
|
-
if (node.value instanceof String) return
|
|
2029
|
+
if (node.value instanceof String) return rv;
|
|
1918
2030
|
if (isArray(node.value)) {
|
|
1919
2031
|
for (let i = 0; i < node.value.length; i++) {
|
|
1920
2032
|
const _node = new JSONPathNode(node.value[i], node.location.concat(i), node.root);
|
|
1921
|
-
rv.push(_node
|
|
2033
|
+
rv.push(_node);
|
|
2034
|
+
for (const __node of this.visit(_node, depth + 1)) {
|
|
2035
|
+
rv.push(__node);
|
|
2036
|
+
}
|
|
1922
2037
|
}
|
|
1923
2038
|
} else if (isObject(node.value)) {
|
|
1924
2039
|
for (const [key, value] of Object.entries(node.value)) {
|
|
1925
2040
|
const _node = new JSONPathNode(value, node.location.concat(key), node.root);
|
|
1926
|
-
rv.push(_node
|
|
2041
|
+
rv.push(_node);
|
|
2042
|
+
for (const __node of this.visit(_node, depth + 1)) {
|
|
2043
|
+
rv.push(__node);
|
|
2044
|
+
}
|
|
1927
2045
|
}
|
|
1928
2046
|
}
|
|
1929
|
-
return
|
|
2047
|
+
return rv;
|
|
1930
2048
|
}
|
|
1931
2049
|
}
|
|
1932
2050
|
class FilterSelector extends JSONPathSelector {
|
|
@@ -1967,7 +2085,40 @@ var json_p3 = (function (exports) {
|
|
|
1967
2085
|
}
|
|
1968
2086
|
}
|
|
1969
2087
|
}
|
|
1970
|
-
return
|
|
2088
|
+
return rv;
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
2092
|
+
*lazyResolve(nodes) {
|
|
2093
|
+
for (const node of nodes) {
|
|
2094
|
+
if (node.value instanceof String) continue;
|
|
2095
|
+
if (isArray(node.value)) {
|
|
2096
|
+
for (let i = 0; i < node.value.length; i++) {
|
|
2097
|
+
const value = node.value[i];
|
|
2098
|
+
const filterContext = {
|
|
2099
|
+
environment: this.environment,
|
|
2100
|
+
currentValue: value,
|
|
2101
|
+
rootValue: node.root,
|
|
2102
|
+
lazy: true
|
|
2103
|
+
};
|
|
2104
|
+
if (this.expression.evaluate(filterContext)) {
|
|
2105
|
+
yield new JSONPathNode(value, node.location.concat(i), node.root);
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
} else if (isObject(node.value)) {
|
|
2109
|
+
for (const [key, value] of Object.entries(node.value)) {
|
|
2110
|
+
const filterContext = {
|
|
2111
|
+
environment: this.environment,
|
|
2112
|
+
currentValue: value,
|
|
2113
|
+
rootValue: node.root,
|
|
2114
|
+
lazy: true
|
|
2115
|
+
};
|
|
2116
|
+
if (this.expression.evaluate(filterContext)) {
|
|
2117
|
+
yield new JSONPathNode(value, node.location.concat(key), node.root);
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
1971
2122
|
}
|
|
1972
2123
|
toString() {
|
|
1973
2124
|
return `?${this.expression.toString()}`;
|
|
@@ -1984,10 +2135,19 @@ var json_p3 = (function (exports) {
|
|
|
1984
2135
|
const rv = [];
|
|
1985
2136
|
for (const node of nodes) {
|
|
1986
2137
|
for (const item of this.items) {
|
|
1987
|
-
|
|
2138
|
+
for (const _node of item.resolve([node])) {
|
|
2139
|
+
rv.push(_node);
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
return rv;
|
|
2144
|
+
}
|
|
2145
|
+
*lazyResolve(nodes) {
|
|
2146
|
+
for (const node of nodes) {
|
|
2147
|
+
for (const item of this.items) {
|
|
2148
|
+
yield* item.lazyResolve([node]);
|
|
1988
2149
|
}
|
|
1989
2150
|
}
|
|
1990
|
-
return new JSONPathNodeList(rv);
|
|
1991
2151
|
}
|
|
1992
2152
|
toString() {
|
|
1993
2153
|
return `[${this.items.map(itm => itm.toString()).join(", ")}]`;
|
|
@@ -2026,10 +2186,23 @@ var json_p3 = (function (exports) {
|
|
|
2026
2186
|
* @returns
|
|
2027
2187
|
*/
|
|
2028
2188
|
query(value) {
|
|
2029
|
-
let nodes =
|
|
2189
|
+
let nodes = [new JSONPathNode(value, [], value)];
|
|
2030
2190
|
for (const selector of this.selectors) {
|
|
2031
2191
|
nodes = selector.resolve(nodes);
|
|
2032
2192
|
}
|
|
2193
|
+
return new JSONPathNodeList(nodes);
|
|
2194
|
+
}
|
|
2195
|
+
|
|
2196
|
+
/**
|
|
2197
|
+
*
|
|
2198
|
+
* @param value -
|
|
2199
|
+
* @returns
|
|
2200
|
+
*/
|
|
2201
|
+
lazyQuery(value) {
|
|
2202
|
+
let nodes = [new JSONPathNode(value, [], value)][Symbol.iterator]();
|
|
2203
|
+
for (const selector of this.selectors) {
|
|
2204
|
+
nodes = selector.lazyResolve(nodes);
|
|
2205
|
+
}
|
|
2033
2206
|
return nodes;
|
|
2034
2207
|
}
|
|
2035
2208
|
|
|
@@ -2042,7 +2215,10 @@ var json_p3 = (function (exports) {
|
|
|
2042
2215
|
* there are no matches.
|
|
2043
2216
|
*/
|
|
2044
2217
|
match(value) {
|
|
2045
|
-
|
|
2218
|
+
const it = this.lazyQuery(value);
|
|
2219
|
+
const rv = it.next();
|
|
2220
|
+
if (rv.done) return undefined;
|
|
2221
|
+
return rv.value;
|
|
2046
2222
|
}
|
|
2047
2223
|
|
|
2048
2224
|
/**
|
|
@@ -2062,13 +2238,17 @@ var json_p3 = (function (exports) {
|
|
|
2062
2238
|
}
|
|
2063
2239
|
|
|
2064
2240
|
const PRECEDENCE_LOWEST = 1;
|
|
2065
|
-
const PRECEDENCE_LOGICALRIGHT = 3;
|
|
2066
2241
|
const PRECEDENCE_LOGICAL_AND = 4;
|
|
2067
2242
|
const PRECEDENCE_LOGICAL_OR = 5;
|
|
2068
2243
|
const PRECEDENCE_COMPARISON = 6;
|
|
2069
|
-
const
|
|
2244
|
+
const PRECEDENCE_PREFIX = 7;
|
|
2245
|
+
const PRECEDENCES = new Map([[TokenKind.AND, PRECEDENCE_LOGICAL_AND], [TokenKind.EQ, PRECEDENCE_COMPARISON], [TokenKind.GE, PRECEDENCE_COMPARISON], [TokenKind.GT, PRECEDENCE_COMPARISON], [TokenKind.LE, PRECEDENCE_COMPARISON], [TokenKind.LT, PRECEDENCE_COMPARISON], [TokenKind.NE, PRECEDENCE_COMPARISON], [TokenKind.NOT, PRECEDENCE_PREFIX], [TokenKind.OR, PRECEDENCE_LOGICAL_OR], [TokenKind.RPAREN, PRECEDENCE_LOWEST]]);
|
|
2070
2246
|
const BINARY_OPERATORS = new Map([[TokenKind.AND, "&&"], [TokenKind.EQ, "=="], [TokenKind.GE, ">="], [TokenKind.GT, ">"], [TokenKind.LE, "<="], [TokenKind.LT, "<"], [TokenKind.NE, "!="], [TokenKind.OR, "||"]]);
|
|
2071
2247
|
const COMPARISON_OPERATORS = new Set(["==", ">=", ">", "<=", "<", "!="]);
|
|
2248
|
+
|
|
2249
|
+
/**
|
|
2250
|
+
* JSONPath token stream parser.
|
|
2251
|
+
*/
|
|
2072
2252
|
class Parser {
|
|
2073
2253
|
constructor(environment) {
|
|
2074
2254
|
this.environment = environment;
|
|
@@ -2085,30 +2265,41 @@ var json_p3 = (function (exports) {
|
|
|
2085
2265
|
parsePath(stream) {
|
|
2086
2266
|
let inFilter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
2087
2267
|
const selectors = [];
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
break;
|
|
2096
|
-
case TokenKind.DDOT:
|
|
2097
|
-
selectors.push(new RecursiveDescentSegment(this.environment, stream.current));
|
|
2098
|
-
break;
|
|
2099
|
-
case TokenKind.LBRACKET:
|
|
2100
|
-
selectors.push(this.parseBracketedSelection(stream));
|
|
2101
|
-
break;
|
|
2102
|
-
default:
|
|
2103
|
-
if (inFilter) {
|
|
2104
|
-
stream.backup();
|
|
2105
|
-
}
|
|
2106
|
-
break loop;
|
|
2268
|
+
for (;;) {
|
|
2269
|
+
const selector = this.parseSegment(stream);
|
|
2270
|
+
if (!selector) {
|
|
2271
|
+
if (inFilter) {
|
|
2272
|
+
stream.backup();
|
|
2273
|
+
}
|
|
2274
|
+
break;
|
|
2107
2275
|
}
|
|
2276
|
+
selectors.push(selector);
|
|
2108
2277
|
stream.next();
|
|
2109
2278
|
}
|
|
2110
2279
|
return selectors;
|
|
2111
2280
|
}
|
|
2281
|
+
parseSegment(stream) {
|
|
2282
|
+
switch (stream.current.kind) {
|
|
2283
|
+
case TokenKind.NAME:
|
|
2284
|
+
return new NameSelector(this.environment, stream.current, stream.current.value, true);
|
|
2285
|
+
case TokenKind.WILD:
|
|
2286
|
+
return new WildcardSelector(this.environment, stream.current, true);
|
|
2287
|
+
case TokenKind.DDOT:
|
|
2288
|
+
{
|
|
2289
|
+
const segmentToken = stream.current;
|
|
2290
|
+
stream.next();
|
|
2291
|
+
const selector = this.parseSegment(stream);
|
|
2292
|
+
if (!selector) {
|
|
2293
|
+
throw new JSONPathSyntaxError("bald descendant segment", stream.current);
|
|
2294
|
+
}
|
|
2295
|
+
return new RecursiveDescentSegment(this.environment, segmentToken, selector);
|
|
2296
|
+
}
|
|
2297
|
+
case TokenKind.LBRACKET:
|
|
2298
|
+
return this.parseBracketedSelection(stream);
|
|
2299
|
+
default:
|
|
2300
|
+
return null;
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2112
2303
|
parseIndex(stream) {
|
|
2113
2304
|
if (stream.current.value.length > 1 && stream.current.value.startsWith("0") || stream.current.value.startsWith("-0")) {
|
|
2114
2305
|
throw new JSONPathSyntaxError("leading zero in index selector", stream.current);
|
|
@@ -2229,7 +2420,7 @@ var json_p3 = (function (exports) {
|
|
|
2229
2420
|
parsePrefixExpression(stream) {
|
|
2230
2421
|
stream.expect(TokenKind.NOT);
|
|
2231
2422
|
stream.next();
|
|
2232
|
-
return new PrefixExpression(stream.current, "!", this.parseFilterExpression(stream,
|
|
2423
|
+
return new PrefixExpression(stream.current, "!", this.parseFilterExpression(stream, PRECEDENCE_PREFIX));
|
|
2233
2424
|
}
|
|
2234
2425
|
parseInfixExpression(stream, left) {
|
|
2235
2426
|
const tok = stream.next();
|
|
@@ -2239,11 +2430,9 @@ var json_p3 = (function (exports) {
|
|
|
2239
2430
|
if (!operator) {
|
|
2240
2431
|
throw new JSONPathSyntaxError(`unknown operator '${tok.kind}'`, tok);
|
|
2241
2432
|
}
|
|
2242
|
-
this.throwForNonSingularQuery(left);
|
|
2243
|
-
this.throwForNonSingularQuery(right);
|
|
2244
2433
|
if (COMPARISON_OPERATORS.has(operator)) {
|
|
2245
|
-
this.
|
|
2246
|
-
this.
|
|
2434
|
+
this.throwForNonComparable(left);
|
|
2435
|
+
this.throwForNonComparable(right);
|
|
2247
2436
|
}
|
|
2248
2437
|
return new InfixExpression(tok, left, operator, right);
|
|
2249
2438
|
}
|
|
@@ -2331,16 +2520,15 @@ var json_p3 = (function (exports) {
|
|
|
2331
2520
|
throw new JSONPathSyntaxError(`invalid ${isName ? "name selector" : "string literal"} '${token.value}'`, token);
|
|
2332
2521
|
}
|
|
2333
2522
|
}
|
|
2334
|
-
|
|
2523
|
+
throwForNonComparable(expr) {
|
|
2335
2524
|
if ((expr instanceof RootQuery || expr instanceof RelativeQuery) && !expr.path.singularQuery()) {
|
|
2336
|
-
throw new
|
|
2525
|
+
throw new JSONPathTypeError("non-singular query is not comparable", expr.token);
|
|
2337
2526
|
}
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
throw new JSONPathTypeError(`result of ${expr.name}() is not comparable`, expr.token);
|
|
2527
|
+
if (expr instanceof FunctionExtension) {
|
|
2528
|
+
const func = this.environment.functionRegister.get(expr.name);
|
|
2529
|
+
if (func && func.returnType !== FunctionExpressionType.ValueType) {
|
|
2530
|
+
throw new JSONPathTypeError(`result of ${expr.name}() is not comparable`, expr.token);
|
|
2531
|
+
}
|
|
2344
2532
|
}
|
|
2345
2533
|
}
|
|
2346
2534
|
}
|
|
@@ -2351,7 +2539,10 @@ var json_p3 = (function (exports) {
|
|
|
2351
2539
|
*/
|
|
2352
2540
|
|
|
2353
2541
|
/**
|
|
2542
|
+
* A configuration object from which JSONPath queries can be evaluated.
|
|
2354
2543
|
*
|
|
2544
|
+
* An environment is where you'd register custom function extensions or set
|
|
2545
|
+
* the maximum recursion depth limit, for example.
|
|
2355
2546
|
*/
|
|
2356
2547
|
class JSONPathEnvironment {
|
|
2357
2548
|
/**
|
|
@@ -2384,8 +2575,7 @@ var json_p3 = (function (exports) {
|
|
|
2384
2575
|
*/
|
|
2385
2576
|
functionRegister = new Map();
|
|
2386
2577
|
/**
|
|
2387
|
-
*
|
|
2388
|
-
* @param options -
|
|
2578
|
+
* @param options - Environment configuration options.
|
|
2389
2579
|
*/
|
|
2390
2580
|
constructor() {
|
|
2391
2581
|
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -2398,9 +2588,8 @@ var json_p3 = (function (exports) {
|
|
|
2398
2588
|
}
|
|
2399
2589
|
|
|
2400
2590
|
/**
|
|
2401
|
-
*
|
|
2402
|
-
* @
|
|
2403
|
-
* @returns
|
|
2591
|
+
* @param path - A JSONPath query to parse.
|
|
2592
|
+
* @returns A new {@link JSONPath} object, bound to this environment.
|
|
2404
2593
|
*/
|
|
2405
2594
|
compile(path) {
|
|
2406
2595
|
return new JSONPath(this, this.parser.parse(new TokenStream(tokenize(path))));
|
|
@@ -2408,14 +2597,28 @@ var json_p3 = (function (exports) {
|
|
|
2408
2597
|
|
|
2409
2598
|
/**
|
|
2410
2599
|
*
|
|
2411
|
-
* @param path -
|
|
2412
|
-
* @param value -
|
|
2413
|
-
* @returns
|
|
2600
|
+
* @param path - A JSONPath query to parse and evaluate against _value_.
|
|
2601
|
+
* @param value - Data to which _path_ will be applied.
|
|
2602
|
+
* @returns The {@link JSONPathNodeList} resulting from applying _path_
|
|
2603
|
+
* to _value_.
|
|
2414
2604
|
*/
|
|
2415
2605
|
query(path, value) {
|
|
2416
2606
|
return this.compile(path).query(value);
|
|
2417
2607
|
}
|
|
2418
2608
|
|
|
2609
|
+
/**
|
|
2610
|
+
* A lazy version of {@link query} which is faster and more memory
|
|
2611
|
+
* efficient when querying some large datasets.
|
|
2612
|
+
*
|
|
2613
|
+
* @param path - A JSONPath query to parse and evaluate against _value_.
|
|
2614
|
+
* @param value - Data to which _path_ will be applied.
|
|
2615
|
+
* @returns A sequence of {@link JSONPathNode} objects resulting from
|
|
2616
|
+
* applying _path_ to _value_.
|
|
2617
|
+
*/
|
|
2618
|
+
lazyQuery(path, value) {
|
|
2619
|
+
return this.compile(path).lazyQuery(value);
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2419
2622
|
/**
|
|
2420
2623
|
* Return a {@link JSONPathNode} instance for the first object found in
|
|
2421
2624
|
* _value_ matching _path_.
|
|
@@ -2428,6 +2631,11 @@ var json_p3 = (function (exports) {
|
|
|
2428
2631
|
match(path, value) {
|
|
2429
2632
|
return this.compile(path).match(value);
|
|
2430
2633
|
}
|
|
2634
|
+
|
|
2635
|
+
/**
|
|
2636
|
+
* A hook for setting up the function register. You are encouraged to
|
|
2637
|
+
* override this method in classes extending `JSONPathEnvironment`.
|
|
2638
|
+
*/
|
|
2431
2639
|
setupFilterFunctions() {
|
|
2432
2640
|
this.functionRegister.set("count", new Count());
|
|
2433
2641
|
this.functionRegister.set("length", new Length());
|
|
@@ -2437,9 +2645,18 @@ var json_p3 = (function (exports) {
|
|
|
2437
2645
|
}
|
|
2438
2646
|
|
|
2439
2647
|
/**
|
|
2648
|
+
* Check the well-typedness of a function's arguments at compile-time.
|
|
2649
|
+
*
|
|
2650
|
+
* This method is called by the {@link Parser} when parsing function calls.
|
|
2651
|
+
* It is expected to throw a {@link JSONPathTypeError} if the function's
|
|
2652
|
+
* parameters are not well-typed.
|
|
2653
|
+
*
|
|
2654
|
+
* Override this if you want to deviate from the JSONPath Spec's function
|
|
2655
|
+
* extension type system.
|
|
2440
2656
|
*
|
|
2441
|
-
* @param token -
|
|
2442
|
-
*
|
|
2657
|
+
* @param token - The {@link Token} starting the function call. `Token.value`
|
|
2658
|
+
* will contain the name of the function.
|
|
2659
|
+
* @param args - One {@link FilterExpression} for each argument.
|
|
2443
2660
|
*/
|
|
2444
2661
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
2445
2662
|
checkWellTypedness(token, args) {
|
|
@@ -2506,6 +2723,27 @@ var json_p3 = (function (exports) {
|
|
|
2506
2723
|
return DEFAULT_ENVIRONMENT.query(path, value);
|
|
2507
2724
|
}
|
|
2508
2725
|
|
|
2726
|
+
/**
|
|
2727
|
+
* Lazily query JSON value _value_ with JSONPath expression _path_.
|
|
2728
|
+
* Lazy queries can be faster and more memory efficient when querying
|
|
2729
|
+
* large datasets, especially when using recursive decent selectors.
|
|
2730
|
+
*
|
|
2731
|
+
* @param path - A JSONPath expression/query.
|
|
2732
|
+
* @param value - The JSON-like value the JSONPath query is applied to.
|
|
2733
|
+
* @returns A sequence of {@link JSONPathNode} objects resulting from
|
|
2734
|
+
* applying _path_ to _value_.
|
|
2735
|
+
*
|
|
2736
|
+
* @throws {@link JSONPathSyntaxError}
|
|
2737
|
+
* If the path does not conform to standard syntax.
|
|
2738
|
+
*
|
|
2739
|
+
* @throws {@link JSONPathTypeError}
|
|
2740
|
+
* If filter function arguments are invalid, or filter expression are
|
|
2741
|
+
* used in an invalid way.
|
|
2742
|
+
*/
|
|
2743
|
+
function lazyQuery(path, value) {
|
|
2744
|
+
return DEFAULT_ENVIRONMENT.lazyQuery(path, value);
|
|
2745
|
+
}
|
|
2746
|
+
|
|
2509
2747
|
/**
|
|
2510
2748
|
* Compile JSONPath _path_ for later use.
|
|
2511
2749
|
* @param path - A JSONPath expression/query.
|
|
@@ -2555,6 +2793,7 @@ var json_p3 = (function (exports) {
|
|
|
2555
2793
|
compile: compile,
|
|
2556
2794
|
expressions: expression,
|
|
2557
2795
|
functions: index$2,
|
|
2796
|
+
lazyQuery: lazyQuery,
|
|
2558
2797
|
match: match,
|
|
2559
2798
|
query: query,
|
|
2560
2799
|
selectors: selectors
|
|
@@ -3040,7 +3279,7 @@ var json_p3 = (function (exports) {
|
|
|
3040
3279
|
apply: apply
|
|
3041
3280
|
});
|
|
3042
3281
|
|
|
3043
|
-
const version = "0.
|
|
3282
|
+
const version = "0.3.1";
|
|
3044
3283
|
|
|
3045
3284
|
exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
|
|
3046
3285
|
exports.FunctionExpressionType = FunctionExpressionType;
|
|
@@ -3068,6 +3307,7 @@ var json_p3 = (function (exports) {
|
|
|
3068
3307
|
exports.jsonpatch = index;
|
|
3069
3308
|
exports.jsonpath = index$1;
|
|
3070
3309
|
exports.jsonpointer = index$3;
|
|
3310
|
+
exports.lazyQuery = lazyQuery;
|
|
3071
3311
|
exports.query = query;
|
|
3072
3312
|
exports.resolve = resolve;
|
|
3073
3313
|
exports.version = version;
|