json-p3 0.1.1 → 0.2.0
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 +21 -288
- package/dist/index.d.ts +2 -2
- package/dist/json-p3.cjs.js +276 -44
- package/dist/json-p3.esm.js +274 -45
- package/dist/json-p3.iife.js +276 -44
- package/dist/json-p3.iife.min.js +1 -1
- package/dist/json-p3.iife.min.js.map +1 -1
- package/dist/patch/patch.d.ts +4 -0
- package/dist/path/environment.d.ts +56 -10
- package/dist/path/errors.d.ts +8 -0
- package/dist/path/expression.d.ts +1 -0
- package/dist/path/index.d.ts +12 -2
- package/dist/path/path.d.ts +10 -1
- package/dist/path/selectors.d.ts +0 -1
- package/dist/pointer/errors.d.ts +15 -0
- package/dist/pointer/index.d.ts +1 -1
- package/dist/pointer/pointer.d.ts +29 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
package/dist/json-p3.iife.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* json-p3 version 0.
|
|
2
|
+
* json-p3 version 0.2.0
|
|
3
3
|
* https://github.com/jg-rp/json-p3
|
|
4
4
|
*
|
|
5
5
|
* MIT License
|
|
@@ -125,6 +125,20 @@ var json_p3 = (function (exports) {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Error thrown when the maximum recursion depth is reached.
|
|
130
|
+
*/
|
|
131
|
+
class JSONPathRecursionLimitError extends JSONPathError {
|
|
132
|
+
constructor(message, token) {
|
|
133
|
+
super(message, token);
|
|
134
|
+
this.message = message;
|
|
135
|
+
this.token = token;
|
|
136
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
137
|
+
this.name = "JSONPathRecursionLimitError";
|
|
138
|
+
this.message = withErrorContext(message, token);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
128
142
|
/**
|
|
129
143
|
* Common types and type predicates.
|
|
130
144
|
*/
|
|
@@ -233,6 +247,10 @@ var json_p3 = (function (exports) {
|
|
|
233
247
|
this.name = "JSONPointerError";
|
|
234
248
|
}
|
|
235
249
|
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Base class for JSON Pointer resolution errors.
|
|
253
|
+
*/
|
|
236
254
|
class JSONPointerResolutionError extends JSONPointerError {
|
|
237
255
|
constructor(message) {
|
|
238
256
|
super(message);
|
|
@@ -241,6 +259,10 @@ var json_p3 = (function (exports) {
|
|
|
241
259
|
this.name = "JSONPointerResolutionError";
|
|
242
260
|
}
|
|
243
261
|
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Error thrown due to an out of range index when resolving a JSON Pointer.
|
|
265
|
+
*/
|
|
244
266
|
class JSONPointerIndexError extends JSONPointerResolutionError {
|
|
245
267
|
constructor(message) {
|
|
246
268
|
super(message);
|
|
@@ -249,6 +271,10 @@ var json_p3 = (function (exports) {
|
|
|
249
271
|
this.name = "JSONPointerIndexError";
|
|
250
272
|
}
|
|
251
273
|
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Error thrown due to a missing property when resolving a JSON Pointer.
|
|
277
|
+
*/
|
|
252
278
|
class JSONPointerKeyError extends JSONPointerResolutionError {
|
|
253
279
|
constructor(message) {
|
|
254
280
|
super(message);
|
|
@@ -257,6 +283,10 @@ var json_p3 = (function (exports) {
|
|
|
257
283
|
this.name = "JSONPointerKeyError";
|
|
258
284
|
}
|
|
259
285
|
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Error thrown due to invalid JSON Pointer syntax.
|
|
289
|
+
*/
|
|
260
290
|
class JSONPointerSyntaxError extends JSONPointerError {
|
|
261
291
|
constructor(message) {
|
|
262
292
|
super(message);
|
|
@@ -265,6 +295,10 @@ var json_p3 = (function (exports) {
|
|
|
265
295
|
this.name = "JSONPointerSyntaxError";
|
|
266
296
|
}
|
|
267
297
|
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Error thrown when trying to resolve a property or index against a primitive value.
|
|
301
|
+
*/
|
|
268
302
|
class JSONPointerTypeError extends JSONPointerResolutionError {
|
|
269
303
|
constructor(message) {
|
|
270
304
|
super(message);
|
|
@@ -324,8 +358,6 @@ var json_p3 = (function (exports) {
|
|
|
324
358
|
}
|
|
325
359
|
}
|
|
326
360
|
|
|
327
|
-
// TODO: add `resolveWithFallback` to handle explicit `undefined`
|
|
328
|
-
|
|
329
361
|
/**
|
|
330
362
|
*
|
|
331
363
|
* @param value -
|
|
@@ -364,6 +396,8 @@ var json_p3 = (function (exports) {
|
|
|
364
396
|
}
|
|
365
397
|
return pointer.split("/").map(token => token.replaceAll("~1", "/").replaceAll("~0", "~")).slice(1);
|
|
366
398
|
}
|
|
399
|
+
|
|
400
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
367
401
|
getItem(val, token, idx) {
|
|
368
402
|
// NOTE:
|
|
369
403
|
// - string primitives "have own" indices and `length`.
|
|
@@ -373,12 +407,23 @@ var json_p3 = (function (exports) {
|
|
|
373
407
|
if (isArray(val)) {
|
|
374
408
|
if (token !== "length" && Object.hasOwn(val, token)) {
|
|
375
409
|
return val[Number(token)];
|
|
410
|
+
} else if (token.startsWith("#")) {
|
|
411
|
+
// handle non-standard '#' from relative json pointer
|
|
412
|
+
const maybeIndex = token.slice(1);
|
|
413
|
+
if (RE_INT.test(maybeIndex) && Object.hasOwn(val, maybeIndex)) {
|
|
414
|
+
return Number(maybeIndex);
|
|
415
|
+
} else {
|
|
416
|
+
throw new JSONPointerIndexError(`index out of range '${JSONPointer.encode(this.tokens.slice(0, idx + 1))}'`);
|
|
417
|
+
}
|
|
376
418
|
} else {
|
|
377
419
|
throw new JSONPointerIndexError(`index out of range '${JSONPointer.encode(this.tokens.slice(0, idx + 1))}'`);
|
|
378
420
|
}
|
|
379
421
|
} else if (isObject(val)) {
|
|
380
422
|
if (Object.hasOwn(val, token)) {
|
|
381
423
|
return val[token];
|
|
424
|
+
} else if (token.startsWith("#") && Object.hasOwn(val, token.slice(1))) {
|
|
425
|
+
// handle non-standard '#' from relative json pointer
|
|
426
|
+
return token.slice(1);
|
|
382
427
|
} else {
|
|
383
428
|
throw new JSONPointerKeyError(`no such property '${JSONPointer.encode(this.tokens.slice(0, idx + 1))}'`);
|
|
384
429
|
}
|
|
@@ -453,8 +498,111 @@ var json_p3 = (function (exports) {
|
|
|
453
498
|
}
|
|
454
499
|
return new JSONPointer(JSONPointer.encode(this.tokens.slice(0, this.tokens.length - 1)));
|
|
455
500
|
}
|
|
501
|
+
to(rel) {
|
|
502
|
+
const relativePointer = isString(rel) ? new RelativeJSONPointer(rel) : rel;
|
|
503
|
+
return relativePointer.to(this);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const RE_RELATIVE_POINTER = /(?<ORIGIN>\d+)(?<INDEX_G>(?<SIGN>[+-])(?<INDEX>\d))?(?<POINTER>.*)/s;
|
|
507
|
+
const RE_INT = /(0|[1-9][0-9]*)/;
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* A relative JSON Pointer.
|
|
511
|
+
*
|
|
512
|
+
* See https://www.ietf.org/id/draft-hha-relative-json-pointer-00.html
|
|
513
|
+
*/
|
|
514
|
+
class RelativeJSONPointer {
|
|
515
|
+
/**
|
|
516
|
+
*
|
|
517
|
+
* @param rel -
|
|
518
|
+
*/
|
|
519
|
+
constructor(rel) {
|
|
520
|
+
[this.origin, this.index, this.pointer] = this.parse(rel);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
*
|
|
525
|
+
* @returns
|
|
526
|
+
*/
|
|
527
|
+
toString() {
|
|
528
|
+
const sign = this.index > 0 ? "+" : "";
|
|
529
|
+
const index = this.index === 0 ? "" : `${sign}${this.index}`;
|
|
530
|
+
return `${this.origin}${index}${this.pointer}`;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
*
|
|
535
|
+
* @param pointer -
|
|
536
|
+
*/
|
|
537
|
+
to(pointer) {
|
|
538
|
+
const p = isString(pointer) ? new JSONPointer(pointer) : pointer;
|
|
539
|
+
|
|
540
|
+
// move to origin
|
|
541
|
+
if (this.origin > p.tokens.length) {
|
|
542
|
+
throw new JSONPointerIndexError(`origin (${this.origin}) exceeds root (${p.tokens.length})`);
|
|
543
|
+
}
|
|
544
|
+
const tokens = this.origin < 1 ? p.tokens.slice() : p.tokens.slice(0, -this.origin);
|
|
545
|
+
|
|
546
|
+
// array index offset
|
|
547
|
+
if (this.index && tokens.length && this.isIntLike(tokens.at(-1))) {
|
|
548
|
+
const newIndex = Number(tokens.at(-1)) + this.index;
|
|
549
|
+
if (newIndex < 0) {
|
|
550
|
+
throw new JSONPointerIndexError(`index offset out of range (${newIndex})`);
|
|
551
|
+
}
|
|
552
|
+
tokens[tokens.length - 1] = String(newIndex);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// pointer or index/property
|
|
556
|
+
if (this.pointer instanceof JSONPointer) {
|
|
557
|
+
tokens.push(...this.pointer.tokens);
|
|
558
|
+
} else {
|
|
559
|
+
tokens[tokens.length - 1] = `#${tokens[tokens.length - 1]}`;
|
|
560
|
+
}
|
|
561
|
+
return new JSONPointer(JSONPointer.encode(tokens));
|
|
562
|
+
}
|
|
563
|
+
parse(rel) {
|
|
564
|
+
const match = RE_RELATIVE_POINTER.exec(rel);
|
|
565
|
+
if (!match || !match.groups) {
|
|
566
|
+
throw new JSONPointerSyntaxError("failed to parse relative pointer");
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// steps to move
|
|
570
|
+
const origin = this.parseInt(match.groups.ORIGIN);
|
|
456
571
|
|
|
457
|
-
|
|
572
|
+
// optional index manipulation
|
|
573
|
+
let index = 0;
|
|
574
|
+
if (match.groups["INDEX_G"]) {
|
|
575
|
+
index = this.parseInt(match.groups.INDEX);
|
|
576
|
+
if (index === 0) {
|
|
577
|
+
throw new JSONPointerSyntaxError("index offset can't be zero");
|
|
578
|
+
}
|
|
579
|
+
if (match.groups.SIGN === "-") {
|
|
580
|
+
index = -index;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// pointer or '#'. an empty string is OK.
|
|
585
|
+
if (match.groups.POINTER === "#") {
|
|
586
|
+
return [origin, index, "#"];
|
|
587
|
+
}
|
|
588
|
+
return [origin, index, new JSONPointer(match.groups.POINTER)];
|
|
589
|
+
}
|
|
590
|
+
parseInt(s) {
|
|
591
|
+
if (s.startsWith("0") && s.length > 1) {
|
|
592
|
+
throw new JSONPointerSyntaxError("unexpected leading zero");
|
|
593
|
+
}
|
|
594
|
+
if (RE_INT.test(s)) {
|
|
595
|
+
return Number(s);
|
|
596
|
+
}
|
|
597
|
+
throw new JSONPointerSyntaxError(`expected an integer, found '${s}'`);
|
|
598
|
+
}
|
|
599
|
+
isIntLike(value) {
|
|
600
|
+
if (value === undefined || isNumber(value)) {
|
|
601
|
+
return true;
|
|
602
|
+
} else {
|
|
603
|
+
return RE_INT.test(value);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
458
606
|
}
|
|
459
607
|
|
|
460
608
|
/**
|
|
@@ -489,6 +637,7 @@ var json_p3 = (function (exports) {
|
|
|
489
637
|
JSONPointerResolutionError: JSONPointerResolutionError,
|
|
490
638
|
JSONPointerSyntaxError: JSONPointerSyntaxError,
|
|
491
639
|
JSONPointerTypeError: JSONPointerTypeError,
|
|
640
|
+
RelativeJSONPointer: RelativeJSONPointer,
|
|
492
641
|
UNDEFINED: UNDEFINED,
|
|
493
642
|
resolve: resolve
|
|
494
643
|
});
|
|
@@ -786,7 +935,7 @@ var json_p3 = (function (exports) {
|
|
|
786
935
|
this.args = args;
|
|
787
936
|
}
|
|
788
937
|
evaluate(context) {
|
|
789
|
-
const func = context.environment.
|
|
938
|
+
const func = context.environment.functionRegister.get(this.name);
|
|
790
939
|
if (!func) {
|
|
791
940
|
throw new UndefinedFilterFunctionError(`filter function '${this.name}' is undefined`, this.token);
|
|
792
941
|
}
|
|
@@ -806,13 +955,6 @@ var json_p3 = (function (exports) {
|
|
|
806
955
|
if (value instanceof JSONPathNodeList && value.empty()) return false;
|
|
807
956
|
return !(typeof value === "boolean" && value === false);
|
|
808
957
|
}
|
|
809
|
-
|
|
810
|
-
/**
|
|
811
|
-
*
|
|
812
|
-
* @param left -
|
|
813
|
-
* @param operator -
|
|
814
|
-
* @param right -
|
|
815
|
-
*/
|
|
816
958
|
function compare(left, operator, right) {
|
|
817
959
|
switch (operator) {
|
|
818
960
|
case "==":
|
|
@@ -866,7 +1008,8 @@ var json_p3 = (function (exports) {
|
|
|
866
1008
|
PrefixExpression: PrefixExpression,
|
|
867
1009
|
RelativeQuery: RelativeQuery,
|
|
868
1010
|
RootQuery: RootQuery,
|
|
869
|
-
StringLiteral: StringLiteral
|
|
1011
|
+
StringLiteral: StringLiteral,
|
|
1012
|
+
compare: compare
|
|
870
1013
|
});
|
|
871
1014
|
|
|
872
1015
|
class Count {
|
|
@@ -1390,6 +1533,10 @@ var json_p3 = (function (exports) {
|
|
|
1390
1533
|
case "":
|
|
1391
1534
|
case "]":
|
|
1392
1535
|
l.filterLevel -= 1;
|
|
1536
|
+
if (l.parenStack.length === 1) {
|
|
1537
|
+
l.error("unbalanced parentheses");
|
|
1538
|
+
return null;
|
|
1539
|
+
}
|
|
1393
1540
|
l.backup();
|
|
1394
1541
|
return lexInsideBracketedSelection;
|
|
1395
1542
|
case ",":
|
|
@@ -1619,7 +1766,7 @@ var json_p3 = (function (exports) {
|
|
|
1619
1766
|
this.environment = environment;
|
|
1620
1767
|
this.token = token;
|
|
1621
1768
|
this.index = index;
|
|
1622
|
-
if (index < this.environment.
|
|
1769
|
+
if (index < this.environment.minIntIndex || index > this.environment.maxIntIndex) {
|
|
1623
1770
|
throw new JSONPathIndexError("index out of range", this.token);
|
|
1624
1771
|
}
|
|
1625
1772
|
}
|
|
@@ -1674,15 +1821,11 @@ var json_p3 = (function (exports) {
|
|
|
1674
1821
|
indices[_key] = arguments[_key];
|
|
1675
1822
|
}
|
|
1676
1823
|
for (const index of indices) {
|
|
1677
|
-
if (index !== undefined && (index < this.environment.
|
|
1824
|
+
if (index !== undefined && (index < this.environment.minIntIndex || index > this.environment.maxIntIndex)) {
|
|
1678
1825
|
throw new JSONPathIndexError("index out of range", this.token);
|
|
1679
1826
|
}
|
|
1680
1827
|
}
|
|
1681
1828
|
}
|
|
1682
|
-
normalizedIndex(length, index) {
|
|
1683
|
-
if (index < 0 && length >= Math.abs(index)) return Math.min(length + index, length - 1);
|
|
1684
|
-
return Math.min(index, length - 1);
|
|
1685
|
-
}
|
|
1686
1829
|
|
|
1687
1830
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
1688
1831
|
slice(arr, start, stop, step) {
|
|
@@ -1766,17 +1909,21 @@ var json_p3 = (function (exports) {
|
|
|
1766
1909
|
return "..";
|
|
1767
1910
|
}
|
|
1768
1911
|
visit(node) {
|
|
1912
|
+
let depth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
|
|
1913
|
+
if (depth >= this.environment.maxRecursionDepth) {
|
|
1914
|
+
throw new JSONPathRecursionLimitError("recursion limit reached", this.token);
|
|
1915
|
+
}
|
|
1769
1916
|
const rv = [];
|
|
1770
1917
|
if (node.value instanceof String) return new JSONPathNodeList(rv);
|
|
1771
1918
|
if (isArray(node.value)) {
|
|
1772
1919
|
for (let i = 0; i < node.value.length; i++) {
|
|
1773
1920
|
const _node = new JSONPathNode(node.value[i], node.location.concat(i), node.root);
|
|
1774
|
-
rv.push(_node, ...this.visit(_node));
|
|
1921
|
+
rv.push(_node, ...this.visit(_node, depth + 1));
|
|
1775
1922
|
}
|
|
1776
1923
|
} else if (isObject(node.value)) {
|
|
1777
1924
|
for (const [key, value] of Object.entries(node.value)) {
|
|
1778
1925
|
const _node = new JSONPathNode(value, node.location.concat(key), node.root);
|
|
1779
|
-
rv.push(_node, ...this.visit(_node));
|
|
1926
|
+
rv.push(_node, ...this.visit(_node, depth + 1));
|
|
1780
1927
|
}
|
|
1781
1928
|
}
|
|
1782
1929
|
return new JSONPathNodeList(rv);
|
|
@@ -1886,6 +2033,18 @@ var json_p3 = (function (exports) {
|
|
|
1886
2033
|
return nodes;
|
|
1887
2034
|
}
|
|
1888
2035
|
|
|
2036
|
+
/**
|
|
2037
|
+
* Return a {@link JSONPathNode} instance for the first object found in
|
|
2038
|
+
* _value_ matching this query.
|
|
2039
|
+
*
|
|
2040
|
+
* @param value - JSON-like data to which this query will be applied.
|
|
2041
|
+
* @returns The first node in _value_ matching this query, or `undefined` if
|
|
2042
|
+
* there are no matches.
|
|
2043
|
+
*/
|
|
2044
|
+
match(value) {
|
|
2045
|
+
return this.query(value).nodes.at(0);
|
|
2046
|
+
}
|
|
2047
|
+
|
|
1889
2048
|
/**
|
|
1890
2049
|
*
|
|
1891
2050
|
*/
|
|
@@ -2047,7 +2206,7 @@ var json_p3 = (function (exports) {
|
|
|
2047
2206
|
const tok = stream.next();
|
|
2048
2207
|
const expr = this.parseFilterExpression(stream);
|
|
2049
2208
|
if (expr instanceof FunctionExtension) {
|
|
2050
|
-
const func = this.environment.
|
|
2209
|
+
const func = this.environment.functionRegister.get(expr.name);
|
|
2051
2210
|
if (func && func.returnType === FunctionExpressionType.ValueType) {
|
|
2052
2211
|
throw new JSONPathTypeError(`result of ${expr.name}() must be compared`, expr.token);
|
|
2053
2212
|
}
|
|
@@ -2117,7 +2276,16 @@ var json_p3 = (function (exports) {
|
|
|
2117
2276
|
if (!func) {
|
|
2118
2277
|
throw new JSONPathSyntaxError(`unexpected '${stream.current.value}'`, stream.current);
|
|
2119
2278
|
}
|
|
2120
|
-
|
|
2279
|
+
let expr = func.bind(this)(stream);
|
|
2280
|
+
|
|
2281
|
+
// Could be a comparison/logical expression
|
|
2282
|
+
let peekKind = stream.peek.kind;
|
|
2283
|
+
while (BINARY_OPERATORS.has(peekKind)) {
|
|
2284
|
+
stream.next();
|
|
2285
|
+
expr = this.parseInfixExpression(stream, expr);
|
|
2286
|
+
peekKind = stream.peek.kind;
|
|
2287
|
+
}
|
|
2288
|
+
args.push(expr);
|
|
2121
2289
|
if (stream.peek.kind !== TokenKind.RPAREN) {
|
|
2122
2290
|
if (stream.peek.kind === TokenKind.RBRACKET) break;
|
|
2123
2291
|
stream.expectPeek(TokenKind.COMMA);
|
|
@@ -2125,6 +2293,7 @@ var json_p3 = (function (exports) {
|
|
|
2125
2293
|
}
|
|
2126
2294
|
stream.next();
|
|
2127
2295
|
}
|
|
2296
|
+
stream.expect(TokenKind.RPAREN);
|
|
2128
2297
|
return new FunctionExtension(tok, tok.value, this.environment.checkWellTypedness(tok, args));
|
|
2129
2298
|
}
|
|
2130
2299
|
parseFilterExpression(stream) {
|
|
@@ -2169,7 +2338,7 @@ var json_p3 = (function (exports) {
|
|
|
2169
2338
|
}
|
|
2170
2339
|
throwForNonComparableFunction(expr) {
|
|
2171
2340
|
if (!(expr instanceof FunctionExtension)) return;
|
|
2172
|
-
const func = this.environment.
|
|
2341
|
+
const func = this.environment.functionRegister.get(expr.name);
|
|
2173
2342
|
if (func && func.returnType !== FunctionExpressionType.ValueType) {
|
|
2174
2343
|
throw new JSONPathTypeError(`result of ${expr.name}() is not comparable`, expr.token);
|
|
2175
2344
|
}
|
|
@@ -2177,30 +2346,53 @@ var json_p3 = (function (exports) {
|
|
|
2177
2346
|
}
|
|
2178
2347
|
|
|
2179
2348
|
/**
|
|
2180
|
-
*
|
|
2349
|
+
* JSONPath environment options. The defaults are in compliance with JSONPath
|
|
2350
|
+
* standards.
|
|
2181
2351
|
*/
|
|
2182
2352
|
|
|
2183
|
-
const defaultOptions = {
|
|
2184
|
-
strict: true,
|
|
2185
|
-
maxIntIndex: Math.pow(2, 53) - 1,
|
|
2186
|
-
minIntIndex: -Math.pow(2, 53) - 1
|
|
2187
|
-
};
|
|
2188
|
-
|
|
2189
2353
|
/**
|
|
2190
2354
|
*
|
|
2191
2355
|
*/
|
|
2192
2356
|
class JSONPathEnvironment {
|
|
2193
2357
|
/**
|
|
2358
|
+
* Indicates if the environment should to be strict about its compliance with
|
|
2359
|
+
* JSONPath standards.
|
|
2194
2360
|
*
|
|
2361
|
+
* Defaults to `true`. Setting `strict` to `false` currently has no effect.
|
|
2362
|
+
* If/when we add non-standard features, the environment's strictness will
|
|
2363
|
+
* control their availability.
|
|
2195
2364
|
*/
|
|
2196
|
-
|
|
2365
|
+
|
|
2366
|
+
/**
|
|
2367
|
+
* The maximum number allowed when indexing or slicing an array. Defaults to
|
|
2368
|
+
* 2**53 -1.
|
|
2369
|
+
*/
|
|
2370
|
+
|
|
2371
|
+
/**
|
|
2372
|
+
* The minimum number allowed when indexing or slicing an array. Defaults to
|
|
2373
|
+
* -(2**53) -1.
|
|
2374
|
+
*/
|
|
2375
|
+
|
|
2376
|
+
/**
|
|
2377
|
+
* The maximum number of objects and/or arrays the recursive descent selector
|
|
2378
|
+
* can visit before a `JSONPathRecursionLimitError` is thrown.
|
|
2379
|
+
*/
|
|
2380
|
+
|
|
2381
|
+
/**
|
|
2382
|
+
* A map of function names to objects implementing the {@link FilterFunction}
|
|
2383
|
+
* interface. You are free to set or delete custom filter functions directly.
|
|
2384
|
+
*/
|
|
2385
|
+
functionRegister = new Map();
|
|
2197
2386
|
/**
|
|
2198
2387
|
*
|
|
2199
2388
|
* @param options -
|
|
2200
2389
|
*/
|
|
2201
2390
|
constructor() {
|
|
2202
|
-
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] :
|
|
2203
|
-
this.
|
|
2391
|
+
let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
2392
|
+
this.strict = options.strict ?? true;
|
|
2393
|
+
this.maxIntIndex = options.maxIntIndex ?? Math.pow(2, 53) - 1;
|
|
2394
|
+
this.minIntIndex = options.maxIntIndex ?? -Math.pow(2, 53) - 1;
|
|
2395
|
+
this.maxRecursionDepth = options.maxRecursionDepth ?? 50;
|
|
2204
2396
|
this.parser = new Parser(this);
|
|
2205
2397
|
this.setupFilterFunctions();
|
|
2206
2398
|
}
|
|
@@ -2223,12 +2415,25 @@ var json_p3 = (function (exports) {
|
|
|
2223
2415
|
query(path, value) {
|
|
2224
2416
|
return this.compile(path).query(value);
|
|
2225
2417
|
}
|
|
2418
|
+
|
|
2419
|
+
/**
|
|
2420
|
+
* Return a {@link JSONPathNode} instance for the first object found in
|
|
2421
|
+
* _value_ matching _path_.
|
|
2422
|
+
*
|
|
2423
|
+
* @param path - A JSONPath query.
|
|
2424
|
+
* @param value - JSON-like data to which the query _path_ will be applied.
|
|
2425
|
+
* @returns The first node in _value_ matching _path_, or `undefined` if
|
|
2426
|
+
* there are no matches.
|
|
2427
|
+
*/
|
|
2428
|
+
match(path, value) {
|
|
2429
|
+
return this.compile(path).match(value);
|
|
2430
|
+
}
|
|
2226
2431
|
setupFilterFunctions() {
|
|
2227
|
-
this.
|
|
2228
|
-
this.
|
|
2229
|
-
this.
|
|
2230
|
-
this.
|
|
2231
|
-
this.
|
|
2432
|
+
this.functionRegister.set("count", new Count());
|
|
2433
|
+
this.functionRegister.set("length", new Length());
|
|
2434
|
+
this.functionRegister.set("search", new Search());
|
|
2435
|
+
this.functionRegister.set("match", new Match());
|
|
2436
|
+
this.functionRegister.set("value", new Value());
|
|
2232
2437
|
}
|
|
2233
2438
|
|
|
2234
2439
|
/**
|
|
@@ -2238,7 +2443,7 @@ var json_p3 = (function (exports) {
|
|
|
2238
2443
|
*/
|
|
2239
2444
|
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
2240
2445
|
checkWellTypedness(token, args) {
|
|
2241
|
-
const func = this.
|
|
2446
|
+
const func = this.functionRegister.get(token.value);
|
|
2242
2447
|
if (!func) {
|
|
2243
2448
|
throw new UndefinedFilterFunctionError(`no such function '${token.value}'`, token);
|
|
2244
2449
|
}
|
|
@@ -2252,17 +2457,17 @@ var json_p3 = (function (exports) {
|
|
|
2252
2457
|
for (const [typ, arg, idx] of func.argTypes.map((t, i) => [t, args[i], i])) {
|
|
2253
2458
|
switch (typ) {
|
|
2254
2459
|
case FunctionExpressionType.ValueType:
|
|
2255
|
-
if (!(arg instanceof FilterExpressionLiteral || arg instanceof JSONPathQuery && arg.path.singularQuery())) {
|
|
2460
|
+
if (!(arg instanceof FilterExpressionLiteral || arg instanceof JSONPathQuery && arg.path.singularQuery() || arg instanceof FunctionExtension && this.functionRegister.get(arg.name)?.returnType === FunctionExpressionType.ValueType)) {
|
|
2256
2461
|
throw new JSONPathTypeError(`${token.value}() argument ${idx} must be of ValueType`, arg.token);
|
|
2257
2462
|
}
|
|
2258
2463
|
break;
|
|
2259
2464
|
case FunctionExpressionType.LogicalType:
|
|
2260
|
-
if (!(arg instanceof
|
|
2465
|
+
if (!(arg instanceof JSONPathQuery || arg instanceof InfixExpression)) {
|
|
2261
2466
|
throw new JSONPathTypeError(`${token.value}() argument ${idx} must be of LogicalType`, arg.token);
|
|
2262
2467
|
}
|
|
2263
2468
|
break;
|
|
2264
2469
|
case FunctionExpressionType.NodesType:
|
|
2265
|
-
if (!(arg instanceof JSONPathQuery)) {
|
|
2470
|
+
if (!(arg instanceof JSONPathQuery || arg instanceof FunctionExtension && this.functionRegister.get(arg.name)?.returnType === FunctionExpressionType.NodesType)) {
|
|
2266
2471
|
throw new JSONPathTypeError(`${token.value}() argument ${idx} must be of NodesType`, arg.token);
|
|
2267
2472
|
}
|
|
2268
2473
|
}
|
|
@@ -2317,6 +2522,19 @@ var json_p3 = (function (exports) {
|
|
|
2317
2522
|
return DEFAULT_ENVIRONMENT.compile(path);
|
|
2318
2523
|
}
|
|
2319
2524
|
|
|
2525
|
+
/**
|
|
2526
|
+
* Return a {@link JSONPathNode} instance for the first object found in
|
|
2527
|
+
* _value_ matching _path_.
|
|
2528
|
+
*
|
|
2529
|
+
* @param path - A JSONPath query.
|
|
2530
|
+
* @param value - JSON-like data to which the query _path_ will be applied.
|
|
2531
|
+
* @returns The first node in _value_ matching _path_, or `undefined` if
|
|
2532
|
+
* there are no matches.
|
|
2533
|
+
*/
|
|
2534
|
+
function match(path, value) {
|
|
2535
|
+
return DEFAULT_ENVIRONMENT.match(path, value);
|
|
2536
|
+
}
|
|
2537
|
+
|
|
2320
2538
|
var index$1 = /*#__PURE__*/Object.freeze({
|
|
2321
2539
|
__proto__: null,
|
|
2322
2540
|
DEFAULT_ENVIRONMENT: DEFAULT_ENVIRONMENT,
|
|
@@ -2328,6 +2546,7 @@ var json_p3 = (function (exports) {
|
|
|
2328
2546
|
JSONPathLexerError: JSONPathLexerError,
|
|
2329
2547
|
JSONPathNode: JSONPathNode,
|
|
2330
2548
|
JSONPathNodeList: JSONPathNodeList,
|
|
2549
|
+
JSONPathRecursionLimitError: JSONPathRecursionLimitError,
|
|
2331
2550
|
JSONPathSyntaxError: JSONPathSyntaxError,
|
|
2332
2551
|
JSONPathTypeError: JSONPathTypeError,
|
|
2333
2552
|
Nothing: Nothing,
|
|
@@ -2336,6 +2555,7 @@ var json_p3 = (function (exports) {
|
|
|
2336
2555
|
compile: compile,
|
|
2337
2556
|
expressions: expression,
|
|
2338
2557
|
functions: index$2,
|
|
2558
|
+
match: match,
|
|
2339
2559
|
query: query,
|
|
2340
2560
|
selectors: selectors
|
|
2341
2561
|
});
|
|
@@ -2636,6 +2856,15 @@ var json_p3 = (function (exports) {
|
|
|
2636
2856
|
}
|
|
2637
2857
|
}
|
|
2638
2858
|
|
|
2859
|
+
/**
|
|
2860
|
+
* @returns an iterator over ops in this patch.
|
|
2861
|
+
*/
|
|
2862
|
+
*[Symbol.iterator]() {
|
|
2863
|
+
for (const op of this.ops) {
|
|
2864
|
+
yield op.toObject();
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2639
2868
|
/**
|
|
2640
2869
|
*
|
|
2641
2870
|
* @param path -
|
|
@@ -2811,8 +3040,9 @@ var json_p3 = (function (exports) {
|
|
|
2811
3040
|
apply: apply
|
|
2812
3041
|
});
|
|
2813
3042
|
|
|
2814
|
-
const version = "0.
|
|
3043
|
+
const version = "0.2.0";
|
|
2815
3044
|
|
|
3045
|
+
exports.DEFAULT_ENVIRONMENT = DEFAULT_ENVIRONMENT;
|
|
2816
3046
|
exports.FunctionExpressionType = FunctionExpressionType;
|
|
2817
3047
|
exports.JSONPatch = JSONPatch;
|
|
2818
3048
|
exports.JSONPatchError = JSONPatchError;
|
|
@@ -2824,10 +3054,12 @@ var json_p3 = (function (exports) {
|
|
|
2824
3054
|
exports.JSONPathLexerError = JSONPathLexerError;
|
|
2825
3055
|
exports.JSONPathNode = JSONPathNode;
|
|
2826
3056
|
exports.JSONPathNodeList = JSONPathNodeList;
|
|
3057
|
+
exports.JSONPathRecursionLimitError = JSONPathRecursionLimitError;
|
|
2827
3058
|
exports.JSONPathSyntaxError = JSONPathSyntaxError;
|
|
2828
3059
|
exports.JSONPathTypeError = JSONPathTypeError;
|
|
2829
3060
|
exports.JSONPointer = JSONPointer;
|
|
2830
3061
|
exports.Nothing = Nothing;
|
|
3062
|
+
exports.RelativeJSONPointer = RelativeJSONPointer;
|
|
2831
3063
|
exports.Token = Token;
|
|
2832
3064
|
exports.TokenKind = TokenKind;
|
|
2833
3065
|
exports.UNDEFINED = UNDEFINED;
|