@swaggerexpert/jsonpath 3.2.4 → 4.0.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 +225 -18
- package/cjs/errors/JSONNormalizedPathError.cjs +8 -0
- package/cjs/errors/JSONPathError.cjs +1 -1
- package/cjs/errors/{JSONPathCompileError.cjs → JSONPathEvaluateError.cjs} +2 -2
- package/cjs/evaluate/evaluators/comparable.cjs +44 -0
- package/cjs/evaluate/evaluators/comparison-expr.cjs +37 -0
- package/cjs/evaluate/evaluators/filter-query.cjs +182 -0
- package/cjs/evaluate/evaluators/function-expr.cjs +106 -0
- package/cjs/evaluate/evaluators/literal.cjs +25 -0
- package/cjs/evaluate/evaluators/logical-expr.cjs +96 -0
- package/cjs/evaluate/evaluators/singular-query.cjs +103 -0
- package/cjs/evaluate/functions/count.cjs +35 -0
- package/cjs/evaluate/functions/index.cjs +15 -0
- package/cjs/evaluate/functions/length.cjs +42 -0
- package/cjs/evaluate/functions/match.cjs +49 -0
- package/cjs/evaluate/functions/search.cjs +49 -0
- package/cjs/evaluate/functions/value.cjs +36 -0
- package/cjs/evaluate/index.cjs +182 -0
- package/cjs/evaluate/realms/EvaluationRealm.cjs +154 -0
- package/cjs/evaluate/realms/json/index.cjs +246 -0
- package/cjs/evaluate/utils/guards.cjs +129 -0
- package/cjs/evaluate/utils/i-regexp.cjs +118 -0
- package/cjs/evaluate/visitors/bracketed-selection.cjs +35 -0
- package/cjs/evaluate/visitors/filter-selector.cjs +43 -0
- package/cjs/evaluate/visitors/index-selector.cjs +55 -0
- package/cjs/evaluate/visitors/name-selector.cjs +38 -0
- package/cjs/evaluate/visitors/segment.cjs +99 -0
- package/cjs/evaluate/visitors/selector.cjs +47 -0
- package/cjs/evaluate/visitors/slice-selector.cjs +115 -0
- package/cjs/evaluate/visitors/wildcard-selector.cjs +32 -0
- package/cjs/index.cjs +16 -7
- package/cjs/normalized-path.cjs +145 -0
- package/cjs/parse/callbacks/cst.cjs +2 -4
- package/cjs/parse/index.cjs +3 -1
- package/cjs/parse/translators/ASTTranslator/index.cjs +1 -1
- package/cjs/parse/translators/ASTTranslator/transformers.cjs +246 -5
- package/cjs/parse/translators/CSTOptimizedTranslator.cjs +1 -3
- package/cjs/parse/translators/CSTTranslator.cjs +1 -2
- package/cjs/test/index.cjs +4 -2
- package/es/errors/JSONNormalizedPathError.mjs +3 -0
- package/es/errors/JSONPathError.mjs +1 -1
- package/es/errors/JSONPathEvaluateError.mjs +3 -0
- package/es/evaluate/evaluators/comparable.mjs +38 -0
- package/es/evaluate/evaluators/comparison-expr.mjs +31 -0
- package/es/evaluate/evaluators/filter-query.mjs +175 -0
- package/es/evaluate/evaluators/function-expr.mjs +99 -0
- package/es/evaluate/evaluators/literal.mjs +21 -0
- package/es/evaluate/evaluators/logical-expr.mjs +89 -0
- package/es/evaluate/evaluators/singular-query.mjs +97 -0
- package/es/evaluate/functions/count.mjs +30 -0
- package/es/evaluate/functions/index.mjs +13 -0
- package/es/evaluate/functions/length.mjs +37 -0
- package/es/evaluate/functions/match.mjs +44 -0
- package/es/evaluate/functions/search.mjs +44 -0
- package/es/evaluate/functions/value.mjs +31 -0
- package/es/evaluate/index.mjs +174 -0
- package/es/evaluate/realms/EvaluationRealm.mjs +148 -0
- package/es/evaluate/realms/json/index.mjs +240 -0
- package/es/evaluate/utils/guards.mjs +114 -0
- package/es/evaluate/utils/i-regexp.mjs +113 -0
- package/es/evaluate/visitors/bracketed-selection.mjs +29 -0
- package/es/evaluate/visitors/filter-selector.mjs +37 -0
- package/es/evaluate/visitors/index-selector.mjs +51 -0
- package/es/evaluate/visitors/name-selector.mjs +34 -0
- package/es/evaluate/visitors/segment.mjs +91 -0
- package/es/evaluate/visitors/selector.mjs +41 -0
- package/es/evaluate/visitors/slice-selector.mjs +111 -0
- package/es/evaluate/visitors/wildcard-selector.mjs +28 -0
- package/es/index.mjs +7 -3
- package/es/normalized-path.mjs +136 -0
- package/es/parse/callbacks/cst.mjs +2 -4
- package/es/parse/index.mjs +3 -1
- package/es/parse/translators/ASTTranslator/index.mjs +1 -1
- package/es/parse/translators/ASTTranslator/transformers.mjs +246 -5
- package/es/parse/translators/CSTOptimizedTranslator.mjs +1 -3
- package/es/parse/translators/CSTTranslator.mjs +1 -2
- package/es/test/index.mjs +4 -2
- package/package.json +4 -2
- package/types/index.d.ts +135 -8
- package/cjs/compile.cjs +0 -50
- package/cjs/escape.cjs +0 -59
- package/es/compile.mjs +0 -45
- package/es/errors/JSONPathCompileError.mjs +0 -3
- package/es/escape.mjs +0 -55
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.constructRegex = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* I-Regexp (RFC 9485) utilities for JSONPath match() and search() functions.
|
|
7
|
+
*
|
|
8
|
+
* @see https://www.rfc-editor.org/rfc/rfc9485 - I-Regexp specification
|
|
9
|
+
* @see https://www.rfc-editor.org/rfc/rfc9535#section-2.4.1 - match() function
|
|
10
|
+
* @see https://www.rfc-editor.org/rfc/rfc9535#section-2.4.2 - search() function
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const regexpCache = new Map();
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Validate and transform I-Regexp pattern to ECMAScript regex pattern.
|
|
17
|
+
* Returns null if pattern contains non-I-Regexp features:
|
|
18
|
+
* - Backreferences (\1, \2, etc.)
|
|
19
|
+
* - Lookahead/lookbehind assertions
|
|
20
|
+
* - Named capture groups
|
|
21
|
+
* - Word boundaries outside character classes
|
|
22
|
+
*
|
|
23
|
+
* Transforms `.` to `[^\n\r]` outside character classes (I-Regexp semantics).
|
|
24
|
+
*
|
|
25
|
+
* @param {string} pattern
|
|
26
|
+
* @returns {string | null} - Transformed pattern or null if invalid
|
|
27
|
+
*/
|
|
28
|
+
const transformIRegexp = pattern => {
|
|
29
|
+
let result = '';
|
|
30
|
+
let inCharClass = false;
|
|
31
|
+
let i = 0;
|
|
32
|
+
while (i < pattern.length) {
|
|
33
|
+
const ch = pattern[i];
|
|
34
|
+
|
|
35
|
+
// Handle escape sequences
|
|
36
|
+
if (ch === '\\' && i + 1 < pattern.length) {
|
|
37
|
+
const next = pattern[i + 1];
|
|
38
|
+
|
|
39
|
+
// Reject backreferences (\1-\9)
|
|
40
|
+
if (next >= '1' && next <= '9') return null;
|
|
41
|
+
|
|
42
|
+
// Reject word boundaries outside character classes
|
|
43
|
+
if (!inCharClass && (next === 'b' || next === 'B')) return null;
|
|
44
|
+
result += ch + next;
|
|
45
|
+
i += 2;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Track character class boundaries
|
|
50
|
+
if (ch === '[' && !inCharClass) {
|
|
51
|
+
inCharClass = true;
|
|
52
|
+
result += ch;
|
|
53
|
+
i += 1;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (ch === ']' && inCharClass) {
|
|
57
|
+
inCharClass = false;
|
|
58
|
+
result += ch;
|
|
59
|
+
i += 1;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Check for lookahead/lookbehind/named groups: (?=, (?!, (?<=, (?<!, (?<name>
|
|
64
|
+
if (ch === '(' && i + 2 < pattern.length && pattern[i + 1] === '?') {
|
|
65
|
+
const next2 = pattern[i + 2];
|
|
66
|
+
// Reject lookahead (?= (?!
|
|
67
|
+
if (next2 === '=' || next2 === '!') return null;
|
|
68
|
+
// Check for lookbehind or named groups
|
|
69
|
+
if (next2 === '<' && i + 3 < pattern.length) {
|
|
70
|
+
const next3 = pattern[i + 3];
|
|
71
|
+
// Reject lookbehind (?<= (?<!
|
|
72
|
+
if (next3 === '=' || next3 === '!') return null;
|
|
73
|
+
// Reject named capture groups (?<name>
|
|
74
|
+
if (/[a-zA-Z]/.test(next3)) return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Transform `.` to `[^\n\r]` outside character classes
|
|
79
|
+
if (ch === '.' && !inCharClass) {
|
|
80
|
+
result += '[^\\n\\r]';
|
|
81
|
+
i += 1;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
result += ch;
|
|
85
|
+
i += 1;
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Construct a RegExp from I-Regexp pattern.
|
|
92
|
+
* Validates the pattern, transforms it, and caches the result.
|
|
93
|
+
*
|
|
94
|
+
* @param {string} pattern - I-Regexp pattern
|
|
95
|
+
* @param {boolean} [anchor=false] - If true, anchor pattern with ^(?:...)$
|
|
96
|
+
* @returns {RegExp | null} - Compiled regex or null if invalid
|
|
97
|
+
*/
|
|
98
|
+
const constructRegex = (pattern, anchor = false) => {
|
|
99
|
+
const cacheKey = anchor ? `anchored:${pattern}` : `unanchored:${pattern}`;
|
|
100
|
+
if (regexpCache.has(cacheKey)) {
|
|
101
|
+
return regexpCache.get(cacheKey);
|
|
102
|
+
}
|
|
103
|
+
const transformed = transformIRegexp(pattern);
|
|
104
|
+
if (transformed === null) {
|
|
105
|
+
regexpCache.set(cacheKey, null);
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
const finalPattern = anchor ? `^(?:${transformed})$` : transformed;
|
|
110
|
+
const regex = new RegExp(finalPattern, 'u');
|
|
111
|
+
regexpCache.set(cacheKey, regex);
|
|
112
|
+
return regex;
|
|
113
|
+
} catch {
|
|
114
|
+
regexpCache.set(cacheKey, null);
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
exports.constructRegex = constructRegex;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _selector = _interopRequireDefault(require("./selector.cjs"));
|
|
6
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
/**
|
|
8
|
+
* Bracketed selection visitor.
|
|
9
|
+
*
|
|
10
|
+
* @see https://www.rfc-editor.org/rfc/rfc9535#section-2.5.1
|
|
11
|
+
*
|
|
12
|
+
* A bracketed selection contains one or more selectors.
|
|
13
|
+
* Each selector's results are concatenated.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Visit a bracketed selection.
|
|
18
|
+
*
|
|
19
|
+
* @param {object} ctx - Evaluation context
|
|
20
|
+
* @param {unknown} value - Current value
|
|
21
|
+
* @param {object} node - AST node
|
|
22
|
+
* @param {object[]} node.selectors - Array of selector AST nodes
|
|
23
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
24
|
+
*/
|
|
25
|
+
const visitBracketedSelection = (ctx, value, node, emit) => {
|
|
26
|
+
const {
|
|
27
|
+
selectors
|
|
28
|
+
} = node;
|
|
29
|
+
|
|
30
|
+
// Visit each selector and emit its results
|
|
31
|
+
for (const selector of selectors) {
|
|
32
|
+
(0, _selector.default)(ctx, value, selector, emit);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var _default = exports.default = visitBracketedSelection;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _logicalExpr = _interopRequireDefault(require("../evaluators/logical-expr.cjs"));
|
|
6
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
|
+
/**
|
|
8
|
+
* Filter selector visitor.
|
|
9
|
+
*
|
|
10
|
+
* @see https://www.rfc-editor.org/rfc/rfc9535#section-2.3.5
|
|
11
|
+
*
|
|
12
|
+
* A filter selector [?expr] selects all children where the expression is true.
|
|
13
|
+
* For arrays: tests each element
|
|
14
|
+
* For objects: tests each member value
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Visit a filter selector.
|
|
19
|
+
*
|
|
20
|
+
* @param {object} ctx - Evaluation context
|
|
21
|
+
* @param {object} ctx.realm - Data realm
|
|
22
|
+
* @param {object} ctx.root - Root value ($)
|
|
23
|
+
* @param {unknown} value - Current value
|
|
24
|
+
* @param {object} node - AST node
|
|
25
|
+
* @param {object} node.expression - Logical expression to evaluate
|
|
26
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
27
|
+
*/
|
|
28
|
+
const visitFilterSelector = (ctx, value, node, emit) => {
|
|
29
|
+
const {
|
|
30
|
+
realm,
|
|
31
|
+
root
|
|
32
|
+
} = ctx;
|
|
33
|
+
const {
|
|
34
|
+
expression
|
|
35
|
+
} = node;
|
|
36
|
+
for (const [key, child] of realm.entries(value)) {
|
|
37
|
+
const result = (0, _logicalExpr.default)(ctx, root, child, expression);
|
|
38
|
+
if (result) {
|
|
39
|
+
emit(child, key);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var _default = exports.default = visitFilterSelector;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* Index selector visitor.
|
|
7
|
+
*
|
|
8
|
+
* @see https://www.rfc-editor.org/rfc/rfc9535#section-2.3.3
|
|
9
|
+
*
|
|
10
|
+
* An index selector selects at most one element from an array.
|
|
11
|
+
* Supports negative indices (count from end).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Normalize an array index.
|
|
16
|
+
* Negative indices count from the end.
|
|
17
|
+
*
|
|
18
|
+
* @param {number} index - The index (may be negative)
|
|
19
|
+
* @param {number} length - Array length
|
|
20
|
+
* @returns {number} - Normalized index (non-negative or out of bounds)
|
|
21
|
+
*/
|
|
22
|
+
const normalizeIndex = (index, length) => {
|
|
23
|
+
if (index >= 0) return index;
|
|
24
|
+
return length + index;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Visit an index selector.
|
|
29
|
+
*
|
|
30
|
+
* @param {object} ctx - Evaluation context
|
|
31
|
+
* @param {object} ctx.realm - Data realm
|
|
32
|
+
* @param {unknown} value - Current value
|
|
33
|
+
* @param {object} node - AST node
|
|
34
|
+
* @param {number} node.value - Index to select
|
|
35
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
36
|
+
*/
|
|
37
|
+
const visitIndexSelector = (ctx, value, node, emit) => {
|
|
38
|
+
const {
|
|
39
|
+
realm
|
|
40
|
+
} = ctx;
|
|
41
|
+
const {
|
|
42
|
+
value: index
|
|
43
|
+
} = node;
|
|
44
|
+
if (!realm.isArray(value)) return;
|
|
45
|
+
const length = realm.getLength(value);
|
|
46
|
+
const normalizedIndex = normalizeIndex(index, length);
|
|
47
|
+
|
|
48
|
+
// Check bounds
|
|
49
|
+
if (normalizedIndex >= 0 && normalizedIndex < length) {
|
|
50
|
+
const selected = realm.getElement(value, normalizedIndex);
|
|
51
|
+
emit(selected, normalizedIndex);
|
|
52
|
+
}
|
|
53
|
+
// If out of bounds, yield nothing
|
|
54
|
+
};
|
|
55
|
+
var _default = exports.default = visitIndexSelector;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* Name selector visitor.
|
|
7
|
+
*
|
|
8
|
+
* @see https://www.rfc-editor.org/rfc/rfc9535#section-2.3.1
|
|
9
|
+
*
|
|
10
|
+
* A name selector selects at most one member value from an object.
|
|
11
|
+
* If the object has the specified member, yield its value.
|
|
12
|
+
* If not, yield nothing.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Visit a name selector.
|
|
17
|
+
*
|
|
18
|
+
* @param {object} ctx - Evaluation context
|
|
19
|
+
* @param {object} ctx.realm - Data realm
|
|
20
|
+
* @param {unknown} value - Current value
|
|
21
|
+
* @param {object} node - AST node
|
|
22
|
+
* @param {string} node.value - Property name to select
|
|
23
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
24
|
+
*/
|
|
25
|
+
const visitNameSelector = (ctx, value, node, emit) => {
|
|
26
|
+
const {
|
|
27
|
+
realm
|
|
28
|
+
} = ctx;
|
|
29
|
+
const {
|
|
30
|
+
value: name
|
|
31
|
+
} = node;
|
|
32
|
+
if (realm.isObject(value) && realm.hasProperty(value, name)) {
|
|
33
|
+
const selected = realm.getProperty(value, name);
|
|
34
|
+
emit(selected, name);
|
|
35
|
+
}
|
|
36
|
+
// If not an object or property doesn't exist, yield nothing
|
|
37
|
+
};
|
|
38
|
+
var _default = exports.default = visitNameSelector;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.visitDescendantSegment = exports.visitChildSegment = exports.default = void 0;
|
|
5
|
+
var _selector = _interopRequireDefault(require("./selector.cjs"));
|
|
6
|
+
var _bracketedSelection = _interopRequireDefault(require("./bracketed-selection.cjs"));
|
|
7
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
/**
|
|
9
|
+
* Segment visitor dispatcher.
|
|
10
|
+
*
|
|
11
|
+
* Handles ChildSegment and DescendantSegment types.
|
|
12
|
+
*
|
|
13
|
+
* @see https://www.rfc-editor.org/rfc/rfc9535#section-2.5
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Visit a segment's selector.
|
|
18
|
+
*
|
|
19
|
+
* @param {object} ctx - Evaluation context
|
|
20
|
+
* @param {unknown} value - Current value
|
|
21
|
+
* @param {object} selector - Selector AST node
|
|
22
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
23
|
+
*/
|
|
24
|
+
const visitSegmentSelector = (ctx, value, selector, emit) => {
|
|
25
|
+
switch (selector.type) {
|
|
26
|
+
case 'BracketedSelection':
|
|
27
|
+
(0, _bracketedSelection.default)(ctx, value, selector, emit);
|
|
28
|
+
break;
|
|
29
|
+
case 'NameSelector':
|
|
30
|
+
case 'WildcardSelector':
|
|
31
|
+
case 'IndexSelector':
|
|
32
|
+
case 'SliceSelector':
|
|
33
|
+
case 'FilterSelector':
|
|
34
|
+
(0, _selector.default)(ctx, value, selector, emit);
|
|
35
|
+
break;
|
|
36
|
+
default:
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Visit a child segment.
|
|
43
|
+
* Applies selector to current value.
|
|
44
|
+
*
|
|
45
|
+
* @param {object} ctx - Evaluation context
|
|
46
|
+
* @param {unknown} value - Current value
|
|
47
|
+
* @param {object} node - ChildSegment AST node
|
|
48
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
49
|
+
*/
|
|
50
|
+
const visitChildSegment = (ctx, value, node, emit) => {
|
|
51
|
+
const {
|
|
52
|
+
selector
|
|
53
|
+
} = node;
|
|
54
|
+
visitSegmentSelector(ctx, value, selector, emit);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Visit a descendant segment.
|
|
59
|
+
* Applies selector to current value and all descendants.
|
|
60
|
+
*
|
|
61
|
+
* Note: This is used by exec.js which handles the recursive descent
|
|
62
|
+
* by pushing descendants onto the stack. This function only applies
|
|
63
|
+
* the selector at the current level.
|
|
64
|
+
*
|
|
65
|
+
* @param {object} ctx - Evaluation context
|
|
66
|
+
* @param {unknown} value - Current value
|
|
67
|
+
* @param {object} node - DescendantSegment AST node
|
|
68
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
69
|
+
*/
|
|
70
|
+
exports.visitChildSegment = visitChildSegment;
|
|
71
|
+
const visitDescendantSegment = (ctx, value, node, emit) => {
|
|
72
|
+
const {
|
|
73
|
+
selector
|
|
74
|
+
} = node;
|
|
75
|
+
visitSegmentSelector(ctx, value, selector, emit);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Visit a segment and emit selected values.
|
|
80
|
+
*
|
|
81
|
+
* @param {object} ctx - Evaluation context
|
|
82
|
+
* @param {unknown} value - Current value
|
|
83
|
+
* @param {object} node - Segment AST node
|
|
84
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
85
|
+
*/
|
|
86
|
+
exports.visitDescendantSegment = visitDescendantSegment;
|
|
87
|
+
const visitSegment = (ctx, value, node, emit) => {
|
|
88
|
+
switch (node.type) {
|
|
89
|
+
case 'ChildSegment':
|
|
90
|
+
visitChildSegment(ctx, value, node, emit);
|
|
91
|
+
break;
|
|
92
|
+
case 'DescendantSegment':
|
|
93
|
+
visitDescendantSegment(ctx, value, node, emit);
|
|
94
|
+
break;
|
|
95
|
+
default:
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
var _default = exports.default = visitSegment;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _nameSelector = _interopRequireDefault(require("./name-selector.cjs"));
|
|
6
|
+
var _indexSelector = _interopRequireDefault(require("./index-selector.cjs"));
|
|
7
|
+
var _wildcardSelector = _interopRequireDefault(require("./wildcard-selector.cjs"));
|
|
8
|
+
var _sliceSelector = _interopRequireDefault(require("./slice-selector.cjs"));
|
|
9
|
+
var _filterSelector = _interopRequireDefault(require("./filter-selector.cjs"));
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
/**
|
|
12
|
+
* Selector visitor dispatcher.
|
|
13
|
+
*
|
|
14
|
+
* Routes to the appropriate selector visitor based on AST node type.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Visit a selector and emit selected values.
|
|
19
|
+
*
|
|
20
|
+
* @param {object} ctx - Evaluation context
|
|
21
|
+
* @param {unknown} value - Current value
|
|
22
|
+
* @param {object} node - Selector AST node
|
|
23
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
24
|
+
*/
|
|
25
|
+
const visitSelector = (ctx, value, node, emit) => {
|
|
26
|
+
switch (node.type) {
|
|
27
|
+
case 'NameSelector':
|
|
28
|
+
(0, _nameSelector.default)(ctx, value, node, emit);
|
|
29
|
+
break;
|
|
30
|
+
case 'IndexSelector':
|
|
31
|
+
(0, _indexSelector.default)(ctx, value, node, emit);
|
|
32
|
+
break;
|
|
33
|
+
case 'WildcardSelector':
|
|
34
|
+
(0, _wildcardSelector.default)(ctx, value, node, emit);
|
|
35
|
+
break;
|
|
36
|
+
case 'SliceSelector':
|
|
37
|
+
(0, _sliceSelector.default)(ctx, value, node, emit);
|
|
38
|
+
break;
|
|
39
|
+
case 'FilterSelector':
|
|
40
|
+
(0, _filterSelector.default)(ctx, value, node, emit);
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
// Unknown selector type, yield nothing
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
var _default = exports.default = visitSelector;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* Slice selector visitor.
|
|
7
|
+
*
|
|
8
|
+
* @see https://www.rfc-editor.org/rfc/rfc9535#section-2.3.4
|
|
9
|
+
*
|
|
10
|
+
* A slice selector [start:end:step] selects elements from an array.
|
|
11
|
+
* - start: first index (default 0 for positive step, len-1 for negative)
|
|
12
|
+
* - end: upper bound (default len for positive step, -len-1 for negative)
|
|
13
|
+
* - step: step size (default 1, must not be 0)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Normalize a slice bound according to RFC 9535.
|
|
18
|
+
* @param {number} index - The bound value
|
|
19
|
+
* @param {number} length - Array length
|
|
20
|
+
* @returns {number} - Normalized bound
|
|
21
|
+
*/
|
|
22
|
+
const normalizeBound = (index, length) => {
|
|
23
|
+
if (index >= 0) {
|
|
24
|
+
return Math.min(index, length);
|
|
25
|
+
}
|
|
26
|
+
return Math.max(length + index, 0);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get slice bounds and step according to RFC 9535 Section 2.3.4.2.
|
|
31
|
+
*
|
|
32
|
+
* @param {number | null} start
|
|
33
|
+
* @param {number | null} end
|
|
34
|
+
* @param {number | null} step
|
|
35
|
+
* @param {number} length - Array length
|
|
36
|
+
* @returns {{ lower: number, upper: number, step: number } | null}
|
|
37
|
+
*/
|
|
38
|
+
const getSliceBounds = (start, end, step, length) => {
|
|
39
|
+
// Default step is 1
|
|
40
|
+
const actualStep = step ?? 1;
|
|
41
|
+
|
|
42
|
+
// Step of 0 is not allowed
|
|
43
|
+
if (actualStep === 0) return null;
|
|
44
|
+
let lower;
|
|
45
|
+
let upper;
|
|
46
|
+
if (actualStep > 0) {
|
|
47
|
+
// Forward iteration
|
|
48
|
+
const defaultStart = 0;
|
|
49
|
+
const defaultEnd = length;
|
|
50
|
+
const normalizedStart = start !== null ? normalizeBound(start, length) : defaultStart;
|
|
51
|
+
const normalizedEnd = end !== null ? normalizeBound(end, length) : defaultEnd;
|
|
52
|
+
lower = Math.max(normalizedStart, 0);
|
|
53
|
+
upper = Math.min(normalizedEnd, length);
|
|
54
|
+
} else {
|
|
55
|
+
// Backward iteration
|
|
56
|
+
const defaultStart = length - 1;
|
|
57
|
+
const defaultEnd = -length - 1;
|
|
58
|
+
const normalizedStart = start !== null ? start >= 0 ? Math.min(start, length - 1) : Math.max(length + start, -1) : defaultStart;
|
|
59
|
+
const normalizedEnd = end !== null ? end >= 0 ? Math.min(end, length - 1) : Math.max(length + end, -1) : defaultEnd;
|
|
60
|
+
upper = Math.min(normalizedStart, length - 1);
|
|
61
|
+
lower = Math.max(normalizedEnd, -1);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
lower,
|
|
65
|
+
upper,
|
|
66
|
+
step: actualStep
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Visit a slice selector.
|
|
72
|
+
*
|
|
73
|
+
* @param {object} ctx - Evaluation context
|
|
74
|
+
* @param {object} ctx.realm - Data realm
|
|
75
|
+
* @param {unknown} value - Current value
|
|
76
|
+
* @param {object} node - AST node
|
|
77
|
+
* @param {number | null} node.start - Start index
|
|
78
|
+
* @param {number | null} node.end - End index
|
|
79
|
+
* @param {number | null} node.step - Step
|
|
80
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
81
|
+
*/
|
|
82
|
+
const visitSliceSelector = (ctx, value, node, emit) => {
|
|
83
|
+
const {
|
|
84
|
+
realm
|
|
85
|
+
} = ctx;
|
|
86
|
+
const {
|
|
87
|
+
start,
|
|
88
|
+
end,
|
|
89
|
+
step
|
|
90
|
+
} = node;
|
|
91
|
+
if (!realm.isArray(value)) return;
|
|
92
|
+
const length = realm.getLength(value);
|
|
93
|
+
const bounds = getSliceBounds(start, end, step, length);
|
|
94
|
+
if (bounds === null) return; // step was 0
|
|
95
|
+
|
|
96
|
+
const {
|
|
97
|
+
lower,
|
|
98
|
+
upper,
|
|
99
|
+
step: actualStep
|
|
100
|
+
} = bounds;
|
|
101
|
+
if (actualStep > 0) {
|
|
102
|
+
// Forward iteration
|
|
103
|
+
for (let i = lower; i < upper; i += actualStep) {
|
|
104
|
+
const selected = realm.getElement(value, i);
|
|
105
|
+
emit(selected, i);
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
// Backward iteration
|
|
109
|
+
for (let i = upper; i > lower; i += actualStep) {
|
|
110
|
+
const selected = realm.getElement(value, i);
|
|
111
|
+
emit(selected, i);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
var _default = exports.default = visitSliceSelector;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
/**
|
|
6
|
+
* Wildcard selector visitor.
|
|
7
|
+
*
|
|
8
|
+
* @see https://www.rfc-editor.org/rfc/rfc9535#section-2.3.2
|
|
9
|
+
*
|
|
10
|
+
* A wildcard selector selects all children of a value:
|
|
11
|
+
* - For arrays: all elements
|
|
12
|
+
* - For objects: all member values
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Visit a wildcard selector.
|
|
17
|
+
*
|
|
18
|
+
* @param {object} ctx - Evaluation context
|
|
19
|
+
* @param {object} ctx.realm - Data realm
|
|
20
|
+
* @param {unknown} value - Current value
|
|
21
|
+
* @param {object} node - AST node (unused for wildcard)
|
|
22
|
+
* @param {(value: unknown, segment: string | number) => void} emit - Callback to emit selected value
|
|
23
|
+
*/
|
|
24
|
+
const visitWildcardSelector = (ctx, value, node, emit) => {
|
|
25
|
+
const {
|
|
26
|
+
realm
|
|
27
|
+
} = ctx;
|
|
28
|
+
for (const [key, child] of realm.entries(value)) {
|
|
29
|
+
emit(child, key);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
var _default = exports.default = visitWildcardSelector;
|
package/cjs/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.test = exports.parse = exports.
|
|
4
|
+
exports.test = exports.parse = exports.functions = exports.evaluate = exports.XMLTranslator = exports.Trace = exports.NormalizedPath = exports.JSONPathParseError = exports.JSONPathEvaluateError = exports.JSONPathError = exports.JSONNormalizedPathError = exports.JSONEvaluationRealm = exports.Grammar = exports.EvaluationRealm = exports.CSTTranslator = exports.CSTOptimizedTranslator = exports.ASTTranslator = void 0;
|
|
5
5
|
var _grammar = _interopRequireDefault(require("./grammar.cjs"));
|
|
6
6
|
exports.Grammar = _grammar.default;
|
|
7
7
|
var _index = _interopRequireDefault(require("./parse/index.cjs"));
|
|
@@ -18,14 +18,23 @@ var _Trace = _interopRequireDefault(require("./parse/trace/Trace.cjs"));
|
|
|
18
18
|
exports.Trace = _Trace.default;
|
|
19
19
|
var _index3 = _interopRequireDefault(require("./test/index.cjs"));
|
|
20
20
|
exports.test = _index3.default;
|
|
21
|
-
var
|
|
22
|
-
exports.
|
|
23
|
-
var
|
|
24
|
-
exports.
|
|
21
|
+
var _NormalizedPath = _interopRequireWildcard(require("./normalized-path.cjs"));
|
|
22
|
+
exports.NormalizedPath = _NormalizedPath;
|
|
23
|
+
var _index4 = _interopRequireDefault(require("./evaluate/index.cjs"));
|
|
24
|
+
exports.evaluate = _index4.default;
|
|
25
|
+
var _functions = _interopRequireWildcard(require("./evaluate/functions/index.cjs"));
|
|
26
|
+
exports.functions = _functions;
|
|
27
|
+
var _EvaluationRealm = _interopRequireDefault(require("./evaluate/realms/EvaluationRealm.cjs"));
|
|
28
|
+
exports.EvaluationRealm = _EvaluationRealm.default;
|
|
29
|
+
var _index6 = _interopRequireDefault(require("./evaluate/realms/json/index.cjs"));
|
|
30
|
+
exports.JSONEvaluationRealm = _index6.default;
|
|
25
31
|
var _JSONPathError = _interopRequireDefault(require("./errors/JSONPathError.cjs"));
|
|
26
32
|
exports.JSONPathError = _JSONPathError.default;
|
|
27
33
|
var _JSONPathParseError = _interopRequireDefault(require("./errors/JSONPathParseError.cjs"));
|
|
28
34
|
exports.JSONPathParseError = _JSONPathParseError.default;
|
|
29
|
-
var
|
|
30
|
-
exports.
|
|
35
|
+
var _JSONNormalizedPathError = _interopRequireDefault(require("./errors/JSONNormalizedPathError.cjs"));
|
|
36
|
+
exports.JSONNormalizedPathError = _JSONNormalizedPathError.default;
|
|
37
|
+
var _JSONPathEvaluateError = _interopRequireDefault(require("./errors/JSONPathEvaluateError.cjs"));
|
|
38
|
+
exports.JSONPathEvaluateError = _JSONPathEvaluateError.default;
|
|
39
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
31
40
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|