@jmespath-community/jmespath 1.3.0 → 1.4.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 +152 -8
- package/dist/cli.cjs +2816 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +2 -0
- package/dist/cli.mjs +857 -244
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +849 -268
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +86 -34
- package/dist/index.d.ts +86 -34
- package/dist/index.esm.js +850 -242
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +5 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/index.mjs +850 -242
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +852 -273
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +5 -1
- package/dist/index.umd.min.js.map +1 -1
- package/package.json +41 -6
package/dist/index.esm.js
CHANGED
|
@@ -2,6 +2,84 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
4
|
|
|
5
|
+
// src/utils/ast.ts
|
|
6
|
+
var CHILD_PROPS = ["left", "right", "condition", "child", "operand", "trueExpr", "falseExpr", "expression"];
|
|
7
|
+
function pushChildren(node, stack) {
|
|
8
|
+
const n = node;
|
|
9
|
+
for (const prop of CHILD_PROPS) {
|
|
10
|
+
const val = n[prop];
|
|
11
|
+
if (val && typeof val === "object" && "type" in val) {
|
|
12
|
+
stack.push(val);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (Array.isArray(n.children)) {
|
|
16
|
+
for (const item of n.children) {
|
|
17
|
+
if (!item) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
stack.push(item);
|
|
21
|
+
if (item.type === "KeyValuePair" && item.value) {
|
|
22
|
+
stack.push(item.value);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (Array.isArray(n.bindings)) {
|
|
27
|
+
for (const item of n.bindings) {
|
|
28
|
+
if (!item) {
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
stack.push(item);
|
|
32
|
+
if (item.reference) {
|
|
33
|
+
stack.push(item.reference);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function forEachNode(root, visitor) {
|
|
39
|
+
const stack = [root];
|
|
40
|
+
while (stack.length > 0) {
|
|
41
|
+
const current = stack.pop();
|
|
42
|
+
if (!current) {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
if (visitor(current) === false) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
pushChildren(current, stack);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function countNodes(root) {
|
|
52
|
+
let count = 0;
|
|
53
|
+
forEachNode(root, () => {
|
|
54
|
+
count += 1;
|
|
55
|
+
return true;
|
|
56
|
+
});
|
|
57
|
+
return count;
|
|
58
|
+
}
|
|
59
|
+
function findDisallowedFunction(root, options) {
|
|
60
|
+
const { allowedFunctions, disallowedFunctions } = options;
|
|
61
|
+
if (!allowedFunctions && !disallowedFunctions) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
let violation = null;
|
|
65
|
+
forEachNode(root, (node) => {
|
|
66
|
+
if (node.type !== "Function") {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
const name = node.name;
|
|
70
|
+
if (allowedFunctions && !allowedFunctions.includes(name)) {
|
|
71
|
+
violation = `Function '${name}' is not allowed`;
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
if (disallowedFunctions && disallowedFunctions.includes(name)) {
|
|
75
|
+
violation = `Function '${name}' is disallowed`;
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
});
|
|
80
|
+
return violation;
|
|
81
|
+
}
|
|
82
|
+
|
|
5
83
|
// src/utils/index.ts
|
|
6
84
|
var isObject = (obj) => {
|
|
7
85
|
return obj !== null && Object.prototype.toString.call(obj) === "[object Object]";
|
|
@@ -51,9 +129,6 @@ var isFalse = (obj) => {
|
|
|
51
129
|
if (Array.isArray(obj)) {
|
|
52
130
|
return obj.length === 0;
|
|
53
131
|
}
|
|
54
|
-
if (obj === null) {
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
132
|
return Object.keys(obj).length === 0;
|
|
58
133
|
}
|
|
59
134
|
return false;
|
|
@@ -98,111 +173,28 @@ var notZero = (n) => {
|
|
|
98
173
|
};
|
|
99
174
|
var add = (left, right) => {
|
|
100
175
|
ensureNumbers(left, right);
|
|
101
|
-
|
|
102
|
-
return result;
|
|
176
|
+
return left + right;
|
|
103
177
|
};
|
|
104
178
|
var sub = (left, right) => {
|
|
105
179
|
ensureNumbers(left, right);
|
|
106
|
-
|
|
107
|
-
return result;
|
|
180
|
+
return left - right;
|
|
108
181
|
};
|
|
109
182
|
var mul = (left, right) => {
|
|
110
183
|
ensureNumbers(left, right);
|
|
111
|
-
|
|
112
|
-
return result;
|
|
184
|
+
return left * right;
|
|
113
185
|
};
|
|
114
186
|
var divide = (left, right) => {
|
|
115
187
|
ensureNumbers(left, right);
|
|
116
|
-
|
|
117
|
-
return result;
|
|
188
|
+
return left / notZero(right);
|
|
118
189
|
};
|
|
119
190
|
var div = (left, right) => {
|
|
120
191
|
ensureNumbers(left, right);
|
|
121
|
-
|
|
122
|
-
return result;
|
|
192
|
+
return Math.floor(left / notZero(right));
|
|
123
193
|
};
|
|
124
194
|
var mod = (left, right) => {
|
|
125
195
|
ensureNumbers(left, right);
|
|
126
|
-
|
|
127
|
-
return result;
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
// src/utils/strings.ts
|
|
131
|
-
var findFirst = (subject, sub2, start, end) => {
|
|
132
|
-
if (!subject || !sub2) {
|
|
133
|
-
return null;
|
|
134
|
-
}
|
|
135
|
-
start = Math.max(ensureInteger(start = start || 0), 0);
|
|
136
|
-
end = Math.min(ensureInteger(end = end || subject.length), subject.length);
|
|
137
|
-
const offset = subject.slice(start, end).indexOf(sub2);
|
|
138
|
-
return offset === -1 ? null : offset + start;
|
|
139
|
-
};
|
|
140
|
-
var findLast = (subject, sub2, start, end) => {
|
|
141
|
-
if (!subject || !sub2) {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
start = Math.max(ensureInteger(start = start || 0), 0);
|
|
145
|
-
end = Math.min(ensureInteger(end = end || subject.length), subject.length);
|
|
146
|
-
const offset = subject.slice(start, end).lastIndexOf(sub2);
|
|
147
|
-
const result = offset === -1 ? null : offset + start;
|
|
148
|
-
return result;
|
|
149
|
-
};
|
|
150
|
-
var lower = (subject) => subject.toLowerCase();
|
|
151
|
-
var ensurePadFuncParams = (name, width, padding) => {
|
|
152
|
-
padding = padding || " ";
|
|
153
|
-
if (padding.length > 1) {
|
|
154
|
-
throw new Error(`invalid value, ${name} expects its 'pad' parameter to be a valid string with a single codepoint`);
|
|
155
|
-
}
|
|
156
|
-
ensurePositiveInteger(width);
|
|
157
|
-
return padding;
|
|
158
|
-
};
|
|
159
|
-
var padLeft = (subject, width, padding) => {
|
|
160
|
-
padding = ensurePadFuncParams("pad_left", width, padding);
|
|
161
|
-
return subject && subject.padStart(width, padding) || "";
|
|
162
|
-
};
|
|
163
|
-
var padRight = (subject, width, padding) => {
|
|
164
|
-
padding = ensurePadFuncParams("pad_right", width, padding);
|
|
165
|
-
return subject && subject.padEnd(width, padding) || "";
|
|
166
|
-
};
|
|
167
|
-
var replace = (subject, string, by, count) => {
|
|
168
|
-
if (count === 0) {
|
|
169
|
-
return subject;
|
|
170
|
-
}
|
|
171
|
-
if (!count) {
|
|
172
|
-
return subject.split(string).join(by);
|
|
173
|
-
}
|
|
174
|
-
ensurePositiveInteger(count);
|
|
175
|
-
[...Array(count).keys()].map(() => subject = subject.replace(string, by));
|
|
176
|
-
return subject;
|
|
177
|
-
};
|
|
178
|
-
var split = (subject, search2, count) => {
|
|
179
|
-
if (subject.length == 0 && search2.length === 0) {
|
|
180
|
-
return [];
|
|
181
|
-
}
|
|
182
|
-
if (count === null || count === void 0) {
|
|
183
|
-
return subject.split(search2);
|
|
184
|
-
}
|
|
185
|
-
ensurePositiveInteger(count);
|
|
186
|
-
if (count === 0) {
|
|
187
|
-
return [subject];
|
|
188
|
-
}
|
|
189
|
-
const split2 = subject.split(search2);
|
|
190
|
-
return [...split2.slice(0, count), split2.slice(count).join(search2)];
|
|
191
|
-
};
|
|
192
|
-
var trim = (subject, chars) => {
|
|
193
|
-
return trimLeft(trimRight(subject, chars), chars);
|
|
194
|
-
};
|
|
195
|
-
var trimLeft = (subject, chars) => {
|
|
196
|
-
return trimImpl(subject, (list) => new RegExp(`^[${list}]*(.*?)`), chars);
|
|
197
|
-
};
|
|
198
|
-
var trimRight = (subject, chars) => {
|
|
199
|
-
return trimImpl(subject, (list) => new RegExp(`(.*?)[${list}]*$`), chars);
|
|
200
|
-
};
|
|
201
|
-
var trimImpl = (subject, regExper, chars) => {
|
|
202
|
-
const pattern = chars ? chars.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&") : "\\s\x85";
|
|
203
|
-
return subject.replace(regExper(pattern), "$1");
|
|
196
|
+
return left % right;
|
|
204
197
|
};
|
|
205
|
-
var upper = (subject) => subject.toUpperCase();
|
|
206
198
|
|
|
207
199
|
// src/Lexer.ts
|
|
208
200
|
var basicTokens = {
|
|
@@ -385,7 +377,7 @@ var StreamLexer = class {
|
|
|
385
377
|
}
|
|
386
378
|
this._current += 1;
|
|
387
379
|
const literal = stream.slice(start + 1, this._current - 1);
|
|
388
|
-
return replace(
|
|
380
|
+
return literal.replace(/\\(['\\])/g, "$1");
|
|
389
381
|
}
|
|
390
382
|
consumeNumber(stream) {
|
|
391
383
|
const start = this._current;
|
|
@@ -551,15 +543,26 @@ var TokenParser = class _TokenParser {
|
|
|
551
543
|
constructor() {
|
|
552
544
|
__publicField(this, "index", 0);
|
|
553
545
|
__publicField(this, "tokens", []);
|
|
546
|
+
__publicField(this, "depth", 0);
|
|
547
|
+
__publicField(this, "maxDepth");
|
|
548
|
+
__publicField(this, "nodeCount", 0);
|
|
549
|
+
__publicField(this, "maxNodes");
|
|
554
550
|
}
|
|
555
551
|
parse(expression, options) {
|
|
556
552
|
this.loadTokens(expression, options || { enable_legacy_literals: false });
|
|
557
553
|
this.index = 0;
|
|
554
|
+
this.depth = 0;
|
|
555
|
+
this.nodeCount = 0;
|
|
556
|
+
this.maxDepth = options?.maxDepth;
|
|
557
|
+
this.maxNodes = options?.maxNodes;
|
|
558
558
|
const ast = this.expression(0);
|
|
559
559
|
if (this.lookahead(0) !== "EOF" /* TOK_EOF */) {
|
|
560
560
|
const token = this.lookaheadToken(0);
|
|
561
561
|
this.errorToken(token, `Syntax error: unexpected token type: ${token.type}, value: ${token.value}`);
|
|
562
562
|
}
|
|
563
|
+
if (this.maxNodes !== void 0 && countNodes(ast) > this.maxNodes) {
|
|
564
|
+
throw new Error(`Expression exceeds maximum allowed node count of ${this.maxNodes}`);
|
|
565
|
+
}
|
|
563
566
|
return ast;
|
|
564
567
|
}
|
|
565
568
|
loadTokens(expression, options) {
|
|
@@ -567,16 +570,32 @@ var TokenParser = class _TokenParser {
|
|
|
567
570
|
this.tokens.push({ type: "EOF" /* TOK_EOF */, value: "", start: expression.length });
|
|
568
571
|
}
|
|
569
572
|
expression(rbp) {
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
573
|
+
if (this.maxDepth !== void 0 && this.depth >= this.maxDepth) {
|
|
574
|
+
throw new Error(`Expression exceeds maximum allowed depth of ${this.maxDepth}`);
|
|
575
|
+
}
|
|
576
|
+
this.depth += 1;
|
|
577
|
+
this.trackNode();
|
|
578
|
+
try {
|
|
579
|
+
const leftToken = this.lookaheadToken(0);
|
|
575
580
|
this.advance();
|
|
576
|
-
left = this.
|
|
577
|
-
currentTokenType = this.lookahead(0);
|
|
581
|
+
let left = this.nud(leftToken);
|
|
582
|
+
let currentTokenType = this.lookahead(0);
|
|
583
|
+
while (rbp < bindingPower[currentTokenType]) {
|
|
584
|
+
this.trackNode();
|
|
585
|
+
this.advance();
|
|
586
|
+
left = this.led(currentTokenType, left);
|
|
587
|
+
currentTokenType = this.lookahead(0);
|
|
588
|
+
}
|
|
589
|
+
return left;
|
|
590
|
+
} finally {
|
|
591
|
+
this.depth -= 1;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
trackNode() {
|
|
595
|
+
this.nodeCount += 1;
|
|
596
|
+
if (this.maxNodes !== void 0 && this.nodeCount > this.maxNodes) {
|
|
597
|
+
throw new Error(`Expression exceeds maximum allowed node count of ${this.maxNodes}`);
|
|
578
598
|
}
|
|
579
|
-
return left;
|
|
580
599
|
}
|
|
581
600
|
lookahead(offset) {
|
|
582
601
|
return this.tokens[this.index + offset].type;
|
|
@@ -803,9 +822,13 @@ var TokenParser = class _TokenParser {
|
|
|
803
822
|
right
|
|
804
823
|
};
|
|
805
824
|
if (right.type === "Slice") {
|
|
825
|
+
const rhs = this.parseProjectionRHS(bindingPower.Star);
|
|
826
|
+
if (rhs.type === "Identity") {
|
|
827
|
+
return indexExpr;
|
|
828
|
+
}
|
|
806
829
|
return {
|
|
807
830
|
left: indexExpr,
|
|
808
|
-
right:
|
|
831
|
+
right: rhs,
|
|
809
832
|
type: "Projection"
|
|
810
833
|
};
|
|
811
834
|
}
|
|
@@ -965,6 +988,83 @@ var TokenParser = class _TokenParser {
|
|
|
965
988
|
var Parser = new TokenParser();
|
|
966
989
|
var Parser_default = Parser;
|
|
967
990
|
|
|
991
|
+
// src/utils/strings.ts
|
|
992
|
+
var findFirst = (subject, sub2, start, end) => {
|
|
993
|
+
if (!subject || !sub2) {
|
|
994
|
+
return null;
|
|
995
|
+
}
|
|
996
|
+
const s = Math.max(ensureInteger(start ?? 0), 0);
|
|
997
|
+
const e = Math.min(ensureInteger(end ?? subject.length), subject.length);
|
|
998
|
+
const offset = subject.slice(s, e).indexOf(sub2);
|
|
999
|
+
return offset === -1 ? null : offset + s;
|
|
1000
|
+
};
|
|
1001
|
+
var findLast = (subject, sub2, start, end) => {
|
|
1002
|
+
if (!subject || !sub2) {
|
|
1003
|
+
return null;
|
|
1004
|
+
}
|
|
1005
|
+
const s = Math.max(ensureInteger(start ?? 0), 0);
|
|
1006
|
+
const e = Math.min(ensureInteger(end ?? subject.length), subject.length);
|
|
1007
|
+
const offset = subject.slice(s, e).lastIndexOf(sub2);
|
|
1008
|
+
return offset === -1 ? null : offset + s;
|
|
1009
|
+
};
|
|
1010
|
+
var lower = (subject) => subject.toLowerCase();
|
|
1011
|
+
var ensurePadFuncParams = (name, width, padding = " ") => {
|
|
1012
|
+
if (padding.length > 1) {
|
|
1013
|
+
throw new Error(`invalid value, ${name} expects its 'pad' parameter to be a valid string with a single codepoint`);
|
|
1014
|
+
}
|
|
1015
|
+
ensurePositiveInteger(width);
|
|
1016
|
+
return padding;
|
|
1017
|
+
};
|
|
1018
|
+
var padLeft = (subject, width, padding) => {
|
|
1019
|
+
padding = ensurePadFuncParams("pad_left", width, padding);
|
|
1020
|
+
return subject && subject.padStart(width, padding) || "";
|
|
1021
|
+
};
|
|
1022
|
+
var padRight = (subject, width, padding) => {
|
|
1023
|
+
padding = ensurePadFuncParams("pad_right", width, padding);
|
|
1024
|
+
return subject && subject.padEnd(width, padding) || "";
|
|
1025
|
+
};
|
|
1026
|
+
var replace = (subject, string, by, count) => {
|
|
1027
|
+
if (count === 0) {
|
|
1028
|
+
return subject;
|
|
1029
|
+
}
|
|
1030
|
+
if (!count) {
|
|
1031
|
+
return subject.split(string).join(by);
|
|
1032
|
+
}
|
|
1033
|
+
ensurePositiveInteger(count);
|
|
1034
|
+
while (count-- > 0 && subject.includes(string)) {
|
|
1035
|
+
subject = subject.replace(string, by);
|
|
1036
|
+
}
|
|
1037
|
+
return subject;
|
|
1038
|
+
};
|
|
1039
|
+
var split = (subject, search2, count) => {
|
|
1040
|
+
if (subject.length == 0 && search2.length === 0) {
|
|
1041
|
+
return [];
|
|
1042
|
+
}
|
|
1043
|
+
if (count === null || count === void 0) {
|
|
1044
|
+
return subject.split(search2);
|
|
1045
|
+
}
|
|
1046
|
+
ensurePositiveInteger(count);
|
|
1047
|
+
if (count === 0) {
|
|
1048
|
+
return [subject];
|
|
1049
|
+
}
|
|
1050
|
+
const split2 = subject.split(search2);
|
|
1051
|
+
return [...split2.slice(0, count), split2.slice(count).join(search2)];
|
|
1052
|
+
};
|
|
1053
|
+
var trim = (subject, chars) => {
|
|
1054
|
+
return trimLeft(trimRight(subject, chars), chars);
|
|
1055
|
+
};
|
|
1056
|
+
var trimLeft = (subject, chars) => {
|
|
1057
|
+
return trimImpl(subject, (list) => new RegExp(`^[${list}]*(.*?)`), chars);
|
|
1058
|
+
};
|
|
1059
|
+
var trimRight = (subject, chars) => {
|
|
1060
|
+
return trimImpl(subject, (list) => new RegExp(`(.*?)[${list}]*$`), chars);
|
|
1061
|
+
};
|
|
1062
|
+
var trimImpl = (subject, regExper, chars) => {
|
|
1063
|
+
const pattern = chars ? chars.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&") : "\\s\x85";
|
|
1064
|
+
return subject.replace(regExper(pattern), "$1");
|
|
1065
|
+
};
|
|
1066
|
+
var upper = (subject) => subject.toUpperCase();
|
|
1067
|
+
|
|
968
1068
|
// src/utils/text.ts
|
|
969
1069
|
var Text = class _Text {
|
|
970
1070
|
constructor(text) {
|
|
@@ -975,7 +1075,11 @@ var Text = class _Text {
|
|
|
975
1075
|
return this._text;
|
|
976
1076
|
}
|
|
977
1077
|
get length() {
|
|
978
|
-
|
|
1078
|
+
let count = 0;
|
|
1079
|
+
for (const _ of this._text) {
|
|
1080
|
+
count += 1;
|
|
1081
|
+
}
|
|
1082
|
+
return count;
|
|
979
1083
|
}
|
|
980
1084
|
compareTo(other) {
|
|
981
1085
|
return _Text.compare(this, new _Text(other));
|
|
@@ -1010,6 +1114,12 @@ var Text = class _Text {
|
|
|
1010
1114
|
var createMathFunction = (mathFn) => ([value]) => mathFn(value);
|
|
1011
1115
|
var createStringFunction = (stringFn) => ([subject]) => stringFn(subject);
|
|
1012
1116
|
var createObjectFunction = (objFn) => ([obj]) => objFn(obj);
|
|
1117
|
+
var ARRAY_SUBTYPES = {
|
|
1118
|
+
[8 /* TYPE_ARRAY_NUMBER */]: 0 /* TYPE_NUMBER */,
|
|
1119
|
+
[10 /* TYPE_ARRAY_OBJECT */]: 4 /* TYPE_OBJECT */,
|
|
1120
|
+
[9 /* TYPE_ARRAY_STRING */]: 2 /* TYPE_STRING */,
|
|
1121
|
+
[11 /* TYPE_ARRAY_ARRAY */]: 3 /* TYPE_ARRAY */
|
|
1122
|
+
};
|
|
1013
1123
|
var Runtime = class {
|
|
1014
1124
|
constructor(interpreter) {
|
|
1015
1125
|
__publicField(this, "_interpreter");
|
|
@@ -1055,28 +1165,30 @@ var Runtime = class {
|
|
|
1055
1165
|
}
|
|
1056
1166
|
return null;
|
|
1057
1167
|
});
|
|
1058
|
-
__publicField(this, "functionEndsWith", (
|
|
1059
|
-
|
|
1060
|
-
return searchStr.includes(suffix, searchStr.length - suffix.length);
|
|
1168
|
+
__publicField(this, "functionEndsWith", ([searchStr, suffix]) => {
|
|
1169
|
+
return searchStr.endsWith(suffix);
|
|
1061
1170
|
});
|
|
1062
1171
|
__publicField(this, "functionFindFirst", this.createFindFunction(findFirst));
|
|
1063
1172
|
__publicField(this, "functionFindLast", this.createFindFunction(findLast));
|
|
1064
1173
|
__publicField(this, "functionFromItems", ([array]) => {
|
|
1065
|
-
|
|
1066
|
-
if (pair.length
|
|
1174
|
+
for (const pair of array) {
|
|
1175
|
+
if (pair.length !== 2 || typeof pair[0] !== "string") {
|
|
1067
1176
|
throw new Error("invalid value, each array must contain two elements, a pair of string and value");
|
|
1068
1177
|
}
|
|
1069
|
-
}
|
|
1178
|
+
}
|
|
1070
1179
|
return Object.fromEntries(array);
|
|
1071
1180
|
});
|
|
1072
1181
|
__publicField(this, "functionGroupBy", ([array, exprefNode]) => {
|
|
1073
1182
|
const keyFunction = this.createKeyFunction(exprefNode, [2 /* TYPE_STRING */]);
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
const
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1183
|
+
const groups = {};
|
|
1184
|
+
for (const item of array) {
|
|
1185
|
+
const key = keyFunction(item);
|
|
1186
|
+
if (!groups[key]) {
|
|
1187
|
+
groups[key] = [];
|
|
1188
|
+
}
|
|
1189
|
+
groups[key].push(item);
|
|
1190
|
+
}
|
|
1191
|
+
return groups;
|
|
1080
1192
|
});
|
|
1081
1193
|
__publicField(this, "functionItems", ([inputValue]) => {
|
|
1082
1194
|
return Object.entries(inputValue);
|
|
@@ -1139,12 +1251,7 @@ var Runtime = class {
|
|
|
1139
1251
|
return maxRecord || null;
|
|
1140
1252
|
});
|
|
1141
1253
|
__publicField(this, "functionMerge", (resolvedArgs) => {
|
|
1142
|
-
|
|
1143
|
-
for (let i = 0; i < resolvedArgs.length; i += 1) {
|
|
1144
|
-
const current = resolvedArgs[i];
|
|
1145
|
-
merged = Object.assign(merged, current);
|
|
1146
|
-
}
|
|
1147
|
-
return merged;
|
|
1254
|
+
return Object.assign({}, ...resolvedArgs);
|
|
1148
1255
|
});
|
|
1149
1256
|
__publicField(this, "functionMin", ([inputValue]) => {
|
|
1150
1257
|
if (!inputValue.length) {
|
|
@@ -1180,12 +1287,7 @@ var Runtime = class {
|
|
|
1180
1287
|
return minRecord || null;
|
|
1181
1288
|
});
|
|
1182
1289
|
__publicField(this, "functionNotNull", (resolvedArgs) => {
|
|
1183
|
-
|
|
1184
|
-
if (this.getTypeName(resolvedArgs[i]) !== 7 /* TYPE_NULL */) {
|
|
1185
|
-
return resolvedArgs[i];
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
return null;
|
|
1290
|
+
return resolvedArgs.find((arg) => arg !== null) ?? null;
|
|
1189
1291
|
});
|
|
1190
1292
|
__publicField(this, "functionPadLeft", this.createPadFunction(padLeft));
|
|
1191
1293
|
__publicField(this, "functionPadRight", this.createPadFunction(padRight));
|
|
@@ -1205,12 +1307,12 @@ var Runtime = class {
|
|
|
1205
1307
|
if (typeName === 2 /* TYPE_STRING */) {
|
|
1206
1308
|
return new Text(inputValue).reverse();
|
|
1207
1309
|
}
|
|
1208
|
-
const reversedArray = inputValue
|
|
1310
|
+
const reversedArray = [...inputValue];
|
|
1209
1311
|
reversedArray.reverse();
|
|
1210
1312
|
return reversedArray;
|
|
1211
1313
|
});
|
|
1212
1314
|
__publicField(this, "functionSort", ([inputValue]) => {
|
|
1213
|
-
if (inputValue.length
|
|
1315
|
+
if (inputValue.length <= 1) {
|
|
1214
1316
|
return inputValue;
|
|
1215
1317
|
}
|
|
1216
1318
|
if (typeof inputValue[0] === "string") {
|
|
@@ -1219,8 +1321,8 @@ var Runtime = class {
|
|
|
1219
1321
|
return [...inputValue].sort();
|
|
1220
1322
|
});
|
|
1221
1323
|
__publicField(this, "functionSortBy", (resolvedArgs) => {
|
|
1222
|
-
const sortedArray = resolvedArgs[0]
|
|
1223
|
-
if (sortedArray.length
|
|
1324
|
+
const sortedArray = [...resolvedArgs[0]];
|
|
1325
|
+
if (sortedArray.length <= 1) {
|
|
1224
1326
|
return sortedArray;
|
|
1225
1327
|
}
|
|
1226
1328
|
const interpreter = this._interpreter;
|
|
@@ -1255,10 +1357,7 @@ var Runtime = class {
|
|
|
1255
1357
|
return inputValue.reduce((x, y) => x + y, 0);
|
|
1256
1358
|
});
|
|
1257
1359
|
__publicField(this, "functionToArray", ([inputValue]) => {
|
|
1258
|
-
|
|
1259
|
-
return inputValue;
|
|
1260
|
-
}
|
|
1261
|
-
return [inputValue];
|
|
1360
|
+
return Array.isArray(inputValue) ? inputValue : [inputValue];
|
|
1262
1361
|
});
|
|
1263
1362
|
__publicField(this, "functionToNumber", ([inputValue]) => {
|
|
1264
1363
|
const typeName = this.getTypeName(inputValue);
|
|
@@ -1275,36 +1374,22 @@ var Runtime = class {
|
|
|
1275
1374
|
return null;
|
|
1276
1375
|
});
|
|
1277
1376
|
__publicField(this, "functionToString", ([inputValue]) => {
|
|
1278
|
-
|
|
1279
|
-
return inputValue;
|
|
1280
|
-
}
|
|
1281
|
-
return JSON.stringify(inputValue);
|
|
1377
|
+
return typeof inputValue === "string" ? inputValue : JSON.stringify(inputValue);
|
|
1282
1378
|
});
|
|
1283
1379
|
__publicField(this, "functionTrim", this.createTrimFunction(trim));
|
|
1284
1380
|
__publicField(this, "functionTrimLeft", this.createTrimFunction(trimLeft));
|
|
1285
1381
|
__publicField(this, "functionTrimRight", this.createTrimFunction(trimRight));
|
|
1286
1382
|
__publicField(this, "functionType", ([inputValue]) => {
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
return "string";
|
|
1292
|
-
case 3 /* TYPE_ARRAY */:
|
|
1293
|
-
return "array";
|
|
1294
|
-
case 4 /* TYPE_OBJECT */:
|
|
1295
|
-
return "object";
|
|
1296
|
-
case 5 /* TYPE_BOOLEAN */:
|
|
1297
|
-
return "boolean";
|
|
1298
|
-
case 7 /* TYPE_NULL */:
|
|
1299
|
-
return "null";
|
|
1300
|
-
default:
|
|
1301
|
-
throw new Error("invalid-type");
|
|
1383
|
+
const type = this.getTypeName(inputValue);
|
|
1384
|
+
const name = type !== void 0 ? this.TYPE_NAME_TABLE[type] : void 0;
|
|
1385
|
+
if (!name) {
|
|
1386
|
+
throw new Error("invalid-type");
|
|
1302
1387
|
}
|
|
1388
|
+
return name;
|
|
1303
1389
|
});
|
|
1304
1390
|
__publicField(this, "functionZip", (array) => {
|
|
1305
1391
|
const length = Math.min(...array.map((arr) => arr.length));
|
|
1306
|
-
|
|
1307
|
-
return result;
|
|
1392
|
+
return Array.from({ length }, (_, index) => array.map((arr) => arr[index]));
|
|
1308
1393
|
});
|
|
1309
1394
|
this._interpreter = interpreter;
|
|
1310
1395
|
this._functionTable = this.buildFunctionTable();
|
|
@@ -1604,34 +1689,18 @@ var Runtime = class {
|
|
|
1604
1689
|
if (expected === 1 /* TYPE_ANY */) {
|
|
1605
1690
|
return true;
|
|
1606
1691
|
}
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
if (actual === 3 /* TYPE_ARRAY */) {
|
|
1612
|
-
let subtype;
|
|
1613
|
-
if (expected === 8 /* TYPE_ARRAY_NUMBER */) {
|
|
1614
|
-
subtype = 0 /* TYPE_NUMBER */;
|
|
1615
|
-
} else if (expected === 10 /* TYPE_ARRAY_OBJECT */) {
|
|
1616
|
-
subtype = 4 /* TYPE_OBJECT */;
|
|
1617
|
-
} else if (expected === 9 /* TYPE_ARRAY_STRING */) {
|
|
1618
|
-
subtype = 2 /* TYPE_STRING */;
|
|
1619
|
-
} else if (expected === 11 /* TYPE_ARRAY_ARRAY */) {
|
|
1620
|
-
subtype = 3 /* TYPE_ARRAY */;
|
|
1621
|
-
}
|
|
1622
|
-
const array = argValue;
|
|
1623
|
-
for (let i = 0; i < array.length; i += 1) {
|
|
1624
|
-
const typeName = this.getTypeName(array[i]);
|
|
1625
|
-
if (typeName !== void 0 && subtype !== void 0 && !this.typeMatches(typeName, subtype, array[i])) {
|
|
1626
|
-
return false;
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
return true;
|
|
1692
|
+
const subtype = ARRAY_SUBTYPES[expected];
|
|
1693
|
+
if (subtype !== void 0) {
|
|
1694
|
+
if (actual !== 3 /* TYPE_ARRAY */) {
|
|
1695
|
+
return false;
|
|
1630
1696
|
}
|
|
1631
|
-
|
|
1632
|
-
return
|
|
1697
|
+
const array = argValue;
|
|
1698
|
+
return array.every((item) => {
|
|
1699
|
+
const typeName = this.getTypeName(item);
|
|
1700
|
+
return typeName === void 0 || this.typeMatches(typeName, subtype, item);
|
|
1701
|
+
});
|
|
1633
1702
|
}
|
|
1634
|
-
return
|
|
1703
|
+
return actual === expected;
|
|
1635
1704
|
}
|
|
1636
1705
|
getTypeName(obj) {
|
|
1637
1706
|
if (obj === null) {
|
|
@@ -1724,26 +1793,111 @@ var ScopeChain = class _ScopeChain {
|
|
|
1724
1793
|
// src/TreeInterpreter.ts
|
|
1725
1794
|
var emptyScopeChain = new ScopeChain();
|
|
1726
1795
|
var TreeInterpreter = class _TreeInterpreter {
|
|
1727
|
-
constructor() {
|
|
1796
|
+
constructor(options) {
|
|
1728
1797
|
__publicField(this, "runtime");
|
|
1729
1798
|
__publicField(this, "_rootValue", null);
|
|
1730
1799
|
__publicField(this, "_scope");
|
|
1800
|
+
__publicField(this, "_options");
|
|
1801
|
+
__publicField(this, "_depth", 0);
|
|
1802
|
+
__publicField(this, "_deadline", 0);
|
|
1731
1803
|
this.runtime = new Runtime(this);
|
|
1732
1804
|
this._scope = new ScopeChain();
|
|
1805
|
+
if (options) {
|
|
1806
|
+
this._options = options;
|
|
1807
|
+
this._deadline = options.timeoutMs !== void 0 ? Date.now() + options.timeoutMs : 0;
|
|
1808
|
+
}
|
|
1733
1809
|
}
|
|
1734
1810
|
withScope(scope) {
|
|
1735
|
-
const interpreter = new _TreeInterpreter();
|
|
1811
|
+
const interpreter = new _TreeInterpreter(this._options);
|
|
1736
1812
|
interpreter.runtime._functionTable = this.runtime._functionTable;
|
|
1737
1813
|
interpreter._rootValue = this._rootValue;
|
|
1738
1814
|
interpreter._scope = this._scope.withScope(scope);
|
|
1815
|
+
interpreter._depth = this._depth;
|
|
1816
|
+
interpreter._deadline = this._deadline;
|
|
1739
1817
|
return interpreter;
|
|
1740
1818
|
}
|
|
1741
|
-
search(node, value) {
|
|
1819
|
+
search(node, value, options) {
|
|
1820
|
+
if (options?.maxNodes !== void 0 && countNodes(node) > options.maxNodes) {
|
|
1821
|
+
throw new Error(`Expression exceeds maximum allowed node count of ${options.maxNodes}`);
|
|
1822
|
+
}
|
|
1742
1823
|
this._rootValue = value;
|
|
1743
1824
|
this._scope = emptyScopeChain;
|
|
1744
|
-
|
|
1825
|
+
this._options = options;
|
|
1826
|
+
this._depth = 0;
|
|
1827
|
+
this._deadline = options?.timeoutMs !== void 0 ? Date.now() + options.timeoutMs : 0;
|
|
1828
|
+
const result = this.visit(node, value);
|
|
1829
|
+
this.checkOutputSize(result);
|
|
1830
|
+
return result;
|
|
1831
|
+
}
|
|
1832
|
+
checkOutputSize(val) {
|
|
1833
|
+
const max = this._options?.maxOutputSize;
|
|
1834
|
+
if (max === void 0 || val == null) {
|
|
1835
|
+
return;
|
|
1836
|
+
}
|
|
1837
|
+
const size = Array.isArray(val) || typeof val === "string" ? val.length : typeof val === "object" ? Object.keys(val).length : 0;
|
|
1838
|
+
if (size > max) {
|
|
1839
|
+
throw new Error(`Output size exceeds maximum allowed size of ${max}`);
|
|
1840
|
+
}
|
|
1841
|
+
}
|
|
1842
|
+
collect(target, item) {
|
|
1843
|
+
target.push(item);
|
|
1844
|
+
if (this._options?.maxOutputSize !== void 0 && target.length > this._options.maxOutputSize) {
|
|
1845
|
+
throw new Error(`Output size exceeds maximum allowed size of ${this._options.maxOutputSize}`);
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
evaluateProjectionItems(items, right) {
|
|
1849
|
+
const collected = [];
|
|
1850
|
+
if (right.type === "Field") {
|
|
1851
|
+
const key = right.name;
|
|
1852
|
+
for (let i = 0; i < items.length; i++) {
|
|
1853
|
+
if (this._deadline > 0 && Date.now() >= this._deadline) {
|
|
1854
|
+
throw new Error(`Query execution timed out after ${this._options?.timeoutMs}ms`);
|
|
1855
|
+
}
|
|
1856
|
+
const elem = items[i];
|
|
1857
|
+
if (!elem || typeof elem !== "object" || Array.isArray(elem)) {
|
|
1858
|
+
continue;
|
|
1859
|
+
}
|
|
1860
|
+
const val = elem[key];
|
|
1861
|
+
if (val !== void 0 && val !== null) {
|
|
1862
|
+
this.collect(collected, val);
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
return collected;
|
|
1866
|
+
}
|
|
1867
|
+
if (right.type === "Identity") {
|
|
1868
|
+
for (let i = 0; i < items.length; i++) {
|
|
1869
|
+
const elem = items[i];
|
|
1870
|
+
if (elem !== null) {
|
|
1871
|
+
this.collect(collected, elem);
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
return collected;
|
|
1875
|
+
}
|
|
1876
|
+
for (const elem of items) {
|
|
1877
|
+
const current = this.visit(right, elem);
|
|
1878
|
+
if (current !== null) {
|
|
1879
|
+
this.collect(collected, current);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
return collected;
|
|
1745
1883
|
}
|
|
1746
1884
|
visit(node, value) {
|
|
1885
|
+
if (this._options) {
|
|
1886
|
+
if (this._options.maxDepth !== void 0 && this._depth >= this._options.maxDepth) {
|
|
1887
|
+
throw new Error(`Evaluation exceeds maximum allowed depth of ${this._options.maxDepth}`);
|
|
1888
|
+
}
|
|
1889
|
+
if (this._deadline > 0 && Date.now() >= this._deadline) {
|
|
1890
|
+
throw new Error(`Query execution timed out after ${this._options.timeoutMs}ms`);
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
this._depth += 1;
|
|
1894
|
+
try {
|
|
1895
|
+
return this.evaluateNode(node, value);
|
|
1896
|
+
} finally {
|
|
1897
|
+
this._depth -= 1;
|
|
1898
|
+
}
|
|
1899
|
+
}
|
|
1900
|
+
evaluateNode(node, value) {
|
|
1747
1901
|
switch (node.type) {
|
|
1748
1902
|
case "Ternary": {
|
|
1749
1903
|
const condition = this.visit(node.condition, value);
|
|
@@ -1759,16 +1913,11 @@ var TreeInterpreter = class _TreeInterpreter {
|
|
|
1759
1913
|
}
|
|
1760
1914
|
return value[identifier] ?? null;
|
|
1761
1915
|
case "LetExpression": {
|
|
1762
|
-
const
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
...scope,
|
|
1768
|
-
...reference
|
|
1769
|
-
};
|
|
1770
|
-
});
|
|
1771
|
-
return this.withScope(scope).visit(expression, value);
|
|
1916
|
+
const scope = {};
|
|
1917
|
+
for (const binding of node.bindings) {
|
|
1918
|
+
Object.assign(scope, this.visit(binding, value));
|
|
1919
|
+
}
|
|
1920
|
+
return this.withScope(scope).visit(node.expression, value);
|
|
1772
1921
|
}
|
|
1773
1922
|
case "Binding": {
|
|
1774
1923
|
const { variable, reference } = node;
|
|
@@ -1800,51 +1949,27 @@ var TreeInterpreter = class _TreeInterpreter {
|
|
|
1800
1949
|
return null;
|
|
1801
1950
|
}
|
|
1802
1951
|
const { start, stop, step } = this.computeSliceParams(value.length, node);
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
return this.slice(value, start, stop, step);
|
|
1809
|
-
}
|
|
1952
|
+
const target = typeof value === "string" ? [...value] : value;
|
|
1953
|
+
const sliced = this.slice(target, start, stop, step);
|
|
1954
|
+
const res = typeof value === "string" ? sliced.join("") : sliced;
|
|
1955
|
+
this.checkOutputSize(res);
|
|
1956
|
+
return res;
|
|
1810
1957
|
}
|
|
1811
1958
|
case "Projection": {
|
|
1812
1959
|
const { left, right } = node;
|
|
1813
|
-
|
|
1814
|
-
if (left.type === "IndexExpression" && left.right.type === "Slice") {
|
|
1815
|
-
allowString = true;
|
|
1816
|
-
}
|
|
1960
|
+
const allowString = left.type === "IndexExpression" && left.right.type === "Slice";
|
|
1817
1961
|
const base = this.visit(left, value);
|
|
1818
1962
|
if (allowString && typeof base === "string") {
|
|
1819
1963
|
return this.visit(right, base);
|
|
1820
1964
|
}
|
|
1821
|
-
|
|
1822
|
-
return null;
|
|
1823
|
-
}
|
|
1824
|
-
const collected = [];
|
|
1825
|
-
for (const elem of base) {
|
|
1826
|
-
const current = this.visit(right, elem);
|
|
1827
|
-
if (current !== null) {
|
|
1828
|
-
collected.push(current);
|
|
1829
|
-
}
|
|
1830
|
-
}
|
|
1831
|
-
return collected;
|
|
1965
|
+
return Array.isArray(base) ? this.evaluateProjectionItems(base, right) : null;
|
|
1832
1966
|
}
|
|
1833
1967
|
case "ValueProjection": {
|
|
1834
|
-
const
|
|
1835
|
-
const base = this.visit(left, value);
|
|
1968
|
+
const base = this.visit(node.left, value);
|
|
1836
1969
|
if (base === null || typeof base !== "object" || Array.isArray(base)) {
|
|
1837
1970
|
return null;
|
|
1838
1971
|
}
|
|
1839
|
-
|
|
1840
|
-
const values = Object.values(base);
|
|
1841
|
-
for (const elem of values) {
|
|
1842
|
-
const current = this.visit(right, elem);
|
|
1843
|
-
if (current !== null) {
|
|
1844
|
-
collected.push(current);
|
|
1845
|
-
}
|
|
1846
|
-
}
|
|
1847
|
-
return collected;
|
|
1972
|
+
return this.evaluateProjectionItems(Object.values(base), node.right);
|
|
1848
1973
|
}
|
|
1849
1974
|
case "FilterProjection": {
|
|
1850
1975
|
const { left, right, condition } = node;
|
|
@@ -1853,14 +1978,42 @@ var TreeInterpreter = class _TreeInterpreter {
|
|
|
1853
1978
|
return null;
|
|
1854
1979
|
}
|
|
1855
1980
|
const results = [];
|
|
1981
|
+
if (right.type === "Field") {
|
|
1982
|
+
const key = right.name;
|
|
1983
|
+
for (let i = 0; i < base.length; i++) {
|
|
1984
|
+
const elem = base[i];
|
|
1985
|
+
if (isFalse(this.visit(condition, elem))) {
|
|
1986
|
+
continue;
|
|
1987
|
+
}
|
|
1988
|
+
if (!elem || typeof elem !== "object" || Array.isArray(elem)) {
|
|
1989
|
+
continue;
|
|
1990
|
+
}
|
|
1991
|
+
const val = elem[key];
|
|
1992
|
+
if (val !== void 0 && val !== null) {
|
|
1993
|
+
this.collect(results, val);
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
return results;
|
|
1997
|
+
}
|
|
1998
|
+
if (right.type === "Identity") {
|
|
1999
|
+
for (let i = 0; i < base.length; i++) {
|
|
2000
|
+
const elem = base[i];
|
|
2001
|
+
if (isFalse(this.visit(condition, elem))) {
|
|
2002
|
+
continue;
|
|
2003
|
+
}
|
|
2004
|
+
if (elem !== null) {
|
|
2005
|
+
this.collect(results, elem);
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
return results;
|
|
2009
|
+
}
|
|
1856
2010
|
for (const elem of base) {
|
|
1857
|
-
|
|
1858
|
-
if (isFalse(matched)) {
|
|
2011
|
+
if (isFalse(this.visit(condition, elem))) {
|
|
1859
2012
|
continue;
|
|
1860
2013
|
}
|
|
1861
2014
|
const result = this.visit(right, elem);
|
|
1862
2015
|
if (result !== null) {
|
|
1863
|
-
|
|
2016
|
+
this.collect(results, result);
|
|
1864
2017
|
}
|
|
1865
2018
|
}
|
|
1866
2019
|
return results;
|
|
@@ -1924,7 +2077,9 @@ var TreeInterpreter = class _TreeInterpreter {
|
|
|
1924
2077
|
}
|
|
1925
2078
|
case "Flatten": {
|
|
1926
2079
|
const original = this.visit(node.child, value);
|
|
1927
|
-
|
|
2080
|
+
const res = Array.isArray(original) ? original.flat() : null;
|
|
2081
|
+
this.checkOutputSize(res);
|
|
2082
|
+
return res;
|
|
1928
2083
|
}
|
|
1929
2084
|
case "Root":
|
|
1930
2085
|
return this._rootValue;
|
|
@@ -1933,6 +2088,7 @@ var TreeInterpreter = class _TreeInterpreter {
|
|
|
1933
2088
|
for (const child of node.children) {
|
|
1934
2089
|
collected.push(this.visit(child, value));
|
|
1935
2090
|
}
|
|
2091
|
+
this.checkOutputSize(collected);
|
|
1936
2092
|
return collected;
|
|
1937
2093
|
}
|
|
1938
2094
|
case "MultiSelectHash": {
|
|
@@ -1940,6 +2096,7 @@ var TreeInterpreter = class _TreeInterpreter {
|
|
|
1940
2096
|
for (const child of node.children) {
|
|
1941
2097
|
collected[child.name] = this.visit(child.value, value);
|
|
1942
2098
|
}
|
|
2099
|
+
this.checkOutputSize(collected);
|
|
1943
2100
|
return collected;
|
|
1944
2101
|
}
|
|
1945
2102
|
case "OrExpression": {
|
|
@@ -1963,11 +2120,19 @@ var TreeInterpreter = class _TreeInterpreter {
|
|
|
1963
2120
|
case "Pipe":
|
|
1964
2121
|
return this.visit(node.right, this.visit(node.left, value));
|
|
1965
2122
|
case "Function": {
|
|
2123
|
+
if (this._options?.allowedFunctions && !this._options.allowedFunctions.includes(node.name)) {
|
|
2124
|
+
throw new Error(`Function '${node.name}' is not allowed`);
|
|
2125
|
+
}
|
|
2126
|
+
if (this._options?.disallowedFunctions && this._options.disallowedFunctions.includes(node.name)) {
|
|
2127
|
+
throw new Error(`Function '${node.name}' is disallowed`);
|
|
2128
|
+
}
|
|
1966
2129
|
const args = [];
|
|
1967
2130
|
for (const child of node.children) {
|
|
1968
2131
|
args.push(this.visit(child, value));
|
|
1969
2132
|
}
|
|
1970
|
-
|
|
2133
|
+
const res = this.runtime.callFunction(node.name, args);
|
|
2134
|
+
this.checkOutputSize(res);
|
|
2135
|
+
return res;
|
|
1971
2136
|
}
|
|
1972
2137
|
case "ExpressionReference":
|
|
1973
2138
|
return {
|
|
@@ -2005,14 +2170,19 @@ var TreeInterpreter = class _TreeInterpreter {
|
|
|
2005
2170
|
return nextActualValue;
|
|
2006
2171
|
}
|
|
2007
2172
|
slice(collection, start, end, step) {
|
|
2008
|
-
|
|
2173
|
+
if (step === 1) {
|
|
2174
|
+
return collection.slice(start, end);
|
|
2175
|
+
}
|
|
2176
|
+
const len = Math.ceil(Math.abs(start - end) / Math.abs(step));
|
|
2177
|
+
const result = new Array(len);
|
|
2178
|
+
let idx = 0;
|
|
2009
2179
|
if (step > 0) {
|
|
2010
2180
|
for (let i = start; i < end; i += step) {
|
|
2011
|
-
result
|
|
2181
|
+
result[idx++] = collection[i];
|
|
2012
2182
|
}
|
|
2013
2183
|
} else {
|
|
2014
2184
|
for (let i = start; i > end; i += step) {
|
|
2015
|
-
result
|
|
2185
|
+
result[idx++] = collection[i];
|
|
2016
2186
|
}
|
|
2017
2187
|
}
|
|
2018
2188
|
return result;
|
|
@@ -2021,6 +2191,391 @@ var TreeInterpreter = class _TreeInterpreter {
|
|
|
2021
2191
|
var TreeInterpreterInstance = new TreeInterpreter();
|
|
2022
2192
|
var TreeInterpreter_default = TreeInterpreterInstance;
|
|
2023
2193
|
|
|
2194
|
+
// src/Stream.ts
|
|
2195
|
+
async function* toAsyncIterable(source) {
|
|
2196
|
+
if (source == null) {
|
|
2197
|
+
return;
|
|
2198
|
+
}
|
|
2199
|
+
if (typeof source !== "object" && typeof source !== "function") {
|
|
2200
|
+
throw new TypeError("Invalid stream source: expected AsyncIterable, Iterable, or ReadableStream");
|
|
2201
|
+
}
|
|
2202
|
+
if (Symbol.asyncIterator in source) {
|
|
2203
|
+
for await (const chunk of source) {
|
|
2204
|
+
yield chunk;
|
|
2205
|
+
}
|
|
2206
|
+
return;
|
|
2207
|
+
}
|
|
2208
|
+
if (typeof source.getReader === "function") {
|
|
2209
|
+
const reader = source.getReader();
|
|
2210
|
+
try {
|
|
2211
|
+
while (true) {
|
|
2212
|
+
const { done, value } = await reader.read();
|
|
2213
|
+
if (done) {
|
|
2214
|
+
break;
|
|
2215
|
+
}
|
|
2216
|
+
yield value;
|
|
2217
|
+
}
|
|
2218
|
+
} finally {
|
|
2219
|
+
reader.releaseLock();
|
|
2220
|
+
}
|
|
2221
|
+
return;
|
|
2222
|
+
}
|
|
2223
|
+
if (Symbol.iterator in source) {
|
|
2224
|
+
for (const chunk of source) {
|
|
2225
|
+
yield chunk;
|
|
2226
|
+
}
|
|
2227
|
+
return;
|
|
2228
|
+
}
|
|
2229
|
+
throw new TypeError("Invalid stream source: expected AsyncIterable, Iterable, or ReadableStream");
|
|
2230
|
+
}
|
|
2231
|
+
function parseItem(str, parseJson) {
|
|
2232
|
+
if (parseJson === true) {
|
|
2233
|
+
return JSON.parse(str);
|
|
2234
|
+
}
|
|
2235
|
+
if (parseJson === "auto") {
|
|
2236
|
+
try {
|
|
2237
|
+
return JSON.parse(str);
|
|
2238
|
+
} catch {
|
|
2239
|
+
return str;
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
return str;
|
|
2243
|
+
}
|
|
2244
|
+
async function* normalizeSource(source, options) {
|
|
2245
|
+
const parseJson = options?.parseJson ?? "auto";
|
|
2246
|
+
const flatten = options?.flattenChunks ?? true;
|
|
2247
|
+
let buffer = "";
|
|
2248
|
+
const textDecoder = typeof TextDecoder !== "undefined" ? new TextDecoder() : null;
|
|
2249
|
+
for await (const chunk of toAsyncIterable(source)) {
|
|
2250
|
+
if (chunk instanceof Uint8Array && textDecoder) {
|
|
2251
|
+
buffer += textDecoder.decode(chunk, { stream: true });
|
|
2252
|
+
if (buffer.includes("\n")) {
|
|
2253
|
+
const lines = buffer.split("\n");
|
|
2254
|
+
buffer = lines.pop() ?? "";
|
|
2255
|
+
for (const line of lines) {
|
|
2256
|
+
const trimmed = line.trim();
|
|
2257
|
+
if (trimmed) {
|
|
2258
|
+
yield parseItem(trimmed, parseJson);
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
} else if (typeof chunk === "string") {
|
|
2263
|
+
if (parseJson === false) {
|
|
2264
|
+
yield chunk;
|
|
2265
|
+
} else {
|
|
2266
|
+
buffer += chunk;
|
|
2267
|
+
if (buffer.includes("\n")) {
|
|
2268
|
+
const lines = buffer.split("\n");
|
|
2269
|
+
buffer = lines.pop() ?? "";
|
|
2270
|
+
for (const line of lines) {
|
|
2271
|
+
const trimmed = line.trim();
|
|
2272
|
+
if (trimmed) {
|
|
2273
|
+
yield parseItem(trimmed, parseJson);
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
}
|
|
2278
|
+
} else if (flatten && Array.isArray(chunk)) {
|
|
2279
|
+
if (buffer.trim()) {
|
|
2280
|
+
yield parseItem(buffer.trim(), parseJson);
|
|
2281
|
+
buffer = "";
|
|
2282
|
+
}
|
|
2283
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
2284
|
+
yield chunk[i];
|
|
2285
|
+
}
|
|
2286
|
+
} else {
|
|
2287
|
+
if (buffer.trim()) {
|
|
2288
|
+
yield parseItem(buffer.trim(), parseJson);
|
|
2289
|
+
buffer = "";
|
|
2290
|
+
}
|
|
2291
|
+
yield chunk;
|
|
2292
|
+
}
|
|
2293
|
+
}
|
|
2294
|
+
if (textDecoder && buffer) {
|
|
2295
|
+
buffer += textDecoder.decode();
|
|
2296
|
+
}
|
|
2297
|
+
if (buffer.trim()) {
|
|
2298
|
+
yield parseItem(buffer.trim(), parseJson);
|
|
2299
|
+
}
|
|
2300
|
+
}
|
|
2301
|
+
function isStreamableNode(node) {
|
|
2302
|
+
switch (node.type) {
|
|
2303
|
+
case "Projection":
|
|
2304
|
+
if (node.left.type === "Identity" || node.left.type === "Current") {
|
|
2305
|
+
return true;
|
|
2306
|
+
}
|
|
2307
|
+
if (node.left.type === "IndexExpression" && node.left.right.type === "Slice") {
|
|
2308
|
+
const slice = node.left.right;
|
|
2309
|
+
return (slice.start === null || slice.start >= 0) && (slice.stop === null || slice.stop >= 0) && (slice.step === null || slice.step > 0);
|
|
2310
|
+
}
|
|
2311
|
+
return false;
|
|
2312
|
+
case "FilterProjection":
|
|
2313
|
+
return node.left.type === "Identity" || node.left.type === "Current";
|
|
2314
|
+
case "IndexExpression":
|
|
2315
|
+
if (node.right.type === "Slice" && (node.left.type === "Identity" || node.left.type === "Current")) {
|
|
2316
|
+
const slice = node.right;
|
|
2317
|
+
return (slice.start === null || slice.start >= 0) && (slice.stop === null || slice.stop >= 0) && (slice.step === null || slice.step > 0);
|
|
2318
|
+
}
|
|
2319
|
+
return true;
|
|
2320
|
+
case "Field":
|
|
2321
|
+
case "Identity":
|
|
2322
|
+
case "Current":
|
|
2323
|
+
case "Subexpression":
|
|
2324
|
+
case "MultiSelectHash":
|
|
2325
|
+
case "MultiSelectList":
|
|
2326
|
+
case "Ternary":
|
|
2327
|
+
case "Comparator":
|
|
2328
|
+
case "Arithmetic":
|
|
2329
|
+
case "NotExpression":
|
|
2330
|
+
return true;
|
|
2331
|
+
case "Pipe":
|
|
2332
|
+
return isStreamableNode(node.left) && isStreamableNode(node.right);
|
|
2333
|
+
default:
|
|
2334
|
+
return false;
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
async function* evaluateStreamNode(source, node, interpreter, options) {
|
|
2338
|
+
const deadline = options?.timeoutMs !== void 0 ? Date.now() + options.timeoutMs : 0;
|
|
2339
|
+
function checkDeadline() {
|
|
2340
|
+
if (deadline > 0 && Date.now() >= deadline) {
|
|
2341
|
+
throw new Error(`Query execution timed out after ${options?.timeoutMs}ms`);
|
|
2342
|
+
}
|
|
2343
|
+
}
|
|
2344
|
+
switch (node.type) {
|
|
2345
|
+
case "Projection": {
|
|
2346
|
+
const { left, right } = node;
|
|
2347
|
+
let streamSource = source;
|
|
2348
|
+
if (left.type === "IndexExpression" && left.right.type === "Slice") {
|
|
2349
|
+
streamSource = evaluateStreamNode(source, left, interpreter, options);
|
|
2350
|
+
}
|
|
2351
|
+
if (right.type === "Identity" || right.type === "Current") {
|
|
2352
|
+
for await (const item of streamSource) {
|
|
2353
|
+
checkDeadline();
|
|
2354
|
+
if (item !== null && item !== void 0) {
|
|
2355
|
+
yield item;
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
2358
|
+
return;
|
|
2359
|
+
}
|
|
2360
|
+
if (right.type === "Field") {
|
|
2361
|
+
const key = right.name;
|
|
2362
|
+
for await (const item of streamSource) {
|
|
2363
|
+
checkDeadline();
|
|
2364
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
2365
|
+
const val = item[key];
|
|
2366
|
+
if (val !== void 0 && val !== null) {
|
|
2367
|
+
yield val;
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
return;
|
|
2372
|
+
}
|
|
2373
|
+
for await (const item of streamSource) {
|
|
2374
|
+
checkDeadline();
|
|
2375
|
+
const res = interpreter.visit(right, item);
|
|
2376
|
+
if (res !== null && res !== void 0) {
|
|
2377
|
+
yield res;
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
return;
|
|
2381
|
+
}
|
|
2382
|
+
case "IndexExpression": {
|
|
2383
|
+
if (node.right.type === "Slice" && (node.left.type === "Identity" || node.left.type === "Current")) {
|
|
2384
|
+
const slice = node.right;
|
|
2385
|
+
const start = slice.start ?? 0;
|
|
2386
|
+
const stop = slice.stop ?? Infinity;
|
|
2387
|
+
const step = slice.step ?? 1;
|
|
2388
|
+
if (start >= 0 && stop >= 0 && step > 0) {
|
|
2389
|
+
let index = 0;
|
|
2390
|
+
for await (const item of source) {
|
|
2391
|
+
checkDeadline();
|
|
2392
|
+
if (index >= stop) {
|
|
2393
|
+
break;
|
|
2394
|
+
}
|
|
2395
|
+
if (index >= start && (index - start) % step === 0) {
|
|
2396
|
+
yield item;
|
|
2397
|
+
}
|
|
2398
|
+
index++;
|
|
2399
|
+
if (index >= stop) {
|
|
2400
|
+
break;
|
|
2401
|
+
}
|
|
2402
|
+
}
|
|
2403
|
+
return;
|
|
2404
|
+
}
|
|
2405
|
+
const collected = [];
|
|
2406
|
+
for await (const item of source) {
|
|
2407
|
+
checkDeadline();
|
|
2408
|
+
collected.push(item);
|
|
2409
|
+
if (options?.maxOutputSize !== void 0 && collected.length > options.maxOutputSize) {
|
|
2410
|
+
throw new Error(`Output size exceeds maximum allowed size of ${options.maxOutputSize}`);
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
const result = interpreter.search(node, collected, options);
|
|
2414
|
+
if (Array.isArray(result)) {
|
|
2415
|
+
for (const item of result) {
|
|
2416
|
+
yield item;
|
|
2417
|
+
}
|
|
2418
|
+
}
|
|
2419
|
+
return;
|
|
2420
|
+
}
|
|
2421
|
+
for await (const item of source) {
|
|
2422
|
+
checkDeadline();
|
|
2423
|
+
const res = interpreter.visit(node, item);
|
|
2424
|
+
if (res !== null && res !== void 0) {
|
|
2425
|
+
yield res;
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
return;
|
|
2429
|
+
}
|
|
2430
|
+
case "FilterProjection": {
|
|
2431
|
+
const { condition, right } = node;
|
|
2432
|
+
if (right.type === "Identity" || right.type === "Current") {
|
|
2433
|
+
for await (const item of source) {
|
|
2434
|
+
checkDeadline();
|
|
2435
|
+
if (!isFalse(interpreter.visit(condition, item))) {
|
|
2436
|
+
yield item;
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
return;
|
|
2440
|
+
}
|
|
2441
|
+
if (right.type === "Field") {
|
|
2442
|
+
const key = right.name;
|
|
2443
|
+
for await (const item of source) {
|
|
2444
|
+
checkDeadline();
|
|
2445
|
+
if (!isFalse(interpreter.visit(condition, item))) {
|
|
2446
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
2447
|
+
const val = item[key];
|
|
2448
|
+
if (val !== void 0 && val !== null) {
|
|
2449
|
+
yield val;
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
return;
|
|
2455
|
+
}
|
|
2456
|
+
for await (const item of source) {
|
|
2457
|
+
checkDeadline();
|
|
2458
|
+
if (!isFalse(interpreter.visit(condition, item))) {
|
|
2459
|
+
const res = interpreter.visit(right, item);
|
|
2460
|
+
if (res !== null && res !== void 0) {
|
|
2461
|
+
yield res;
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
return;
|
|
2466
|
+
}
|
|
2467
|
+
case "Pipe": {
|
|
2468
|
+
const leftStream = evaluateStreamNode(source, node.left, interpreter, options);
|
|
2469
|
+
if (isStreamableNode(node.right)) {
|
|
2470
|
+
for await (const res of evaluateStreamNode(leftStream, node.right, interpreter, options)) {
|
|
2471
|
+
yield res;
|
|
2472
|
+
}
|
|
2473
|
+
} else {
|
|
2474
|
+
const collected = [];
|
|
2475
|
+
for await (const item of leftStream) {
|
|
2476
|
+
checkDeadline();
|
|
2477
|
+
collected.push(item);
|
|
2478
|
+
if (options?.maxOutputSize !== void 0 && collected.length > options.maxOutputSize) {
|
|
2479
|
+
throw new Error(`Output size exceeds maximum allowed size of ${options.maxOutputSize}`);
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
const result = interpreter.search(node.right, collected, options);
|
|
2483
|
+
if (result !== null && result !== void 0) {
|
|
2484
|
+
yield result;
|
|
2485
|
+
}
|
|
2486
|
+
}
|
|
2487
|
+
return;
|
|
2488
|
+
}
|
|
2489
|
+
case "Identity":
|
|
2490
|
+
case "Current": {
|
|
2491
|
+
for await (const item of source) {
|
|
2492
|
+
checkDeadline();
|
|
2493
|
+
yield item;
|
|
2494
|
+
}
|
|
2495
|
+
return;
|
|
2496
|
+
}
|
|
2497
|
+
case "Field": {
|
|
2498
|
+
const key = node.name;
|
|
2499
|
+
for await (const item of source) {
|
|
2500
|
+
checkDeadline();
|
|
2501
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
2502
|
+
const val = item[key];
|
|
2503
|
+
if (val !== void 0 && val !== null) {
|
|
2504
|
+
yield val;
|
|
2505
|
+
}
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
return;
|
|
2509
|
+
}
|
|
2510
|
+
default: {
|
|
2511
|
+
if (isStreamableNode(node)) {
|
|
2512
|
+
for await (const item of source) {
|
|
2513
|
+
checkDeadline();
|
|
2514
|
+
const res = interpreter.visit(node, item);
|
|
2515
|
+
if (res !== null && res !== void 0) {
|
|
2516
|
+
yield res;
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
return;
|
|
2520
|
+
}
|
|
2521
|
+
const collected = [];
|
|
2522
|
+
for await (const item of source) {
|
|
2523
|
+
checkDeadline();
|
|
2524
|
+
collected.push(item);
|
|
2525
|
+
if (options?.maxOutputSize !== void 0 && collected.length > options.maxOutputSize) {
|
|
2526
|
+
throw new Error(`Output size exceeds maximum allowed size of ${options.maxOutputSize}`);
|
|
2527
|
+
}
|
|
2528
|
+
}
|
|
2529
|
+
const result = interpreter.search(node, collected, options);
|
|
2530
|
+
if (result !== null && result !== void 0) {
|
|
2531
|
+
yield result;
|
|
2532
|
+
}
|
|
2533
|
+
return;
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
}
|
|
2537
|
+
function isExpressionNode(val) {
|
|
2538
|
+
return typeof val === "object" && val !== null && "type" in val && typeof val.type === "string" && !(Symbol.iterator in val) && !(Symbol.asyncIterator in val);
|
|
2539
|
+
}
|
|
2540
|
+
async function* searchStream(sourceOrExpression, expressionOrSource, options) {
|
|
2541
|
+
let expression;
|
|
2542
|
+
let source;
|
|
2543
|
+
if (typeof sourceOrExpression === "string" || isExpressionNode(sourceOrExpression)) {
|
|
2544
|
+
expression = sourceOrExpression;
|
|
2545
|
+
source = expressionOrSource;
|
|
2546
|
+
} else {
|
|
2547
|
+
source = sourceOrExpression;
|
|
2548
|
+
expression = expressionOrSource;
|
|
2549
|
+
}
|
|
2550
|
+
if (typeof expression !== "string" && !isExpressionNode(expression)) {
|
|
2551
|
+
throw new TypeError("Expression must be a string or AST ExpressionNode");
|
|
2552
|
+
}
|
|
2553
|
+
const ast = typeof expression === "string" ? Parser_default.parse(expression, options) : expression;
|
|
2554
|
+
if (options) {
|
|
2555
|
+
const fnError = findDisallowedFunction(ast, options);
|
|
2556
|
+
if (fnError) {
|
|
2557
|
+
throw new Error(fnError);
|
|
2558
|
+
}
|
|
2559
|
+
}
|
|
2560
|
+
const interpreter = new TreeInterpreter(options);
|
|
2561
|
+
interpreter.runtime._functionTable = TreeInterpreterInstance.runtime._functionTable;
|
|
2562
|
+
const items = normalizeSource(source, options);
|
|
2563
|
+
const results = evaluateStreamNode(items, ast, interpreter, options);
|
|
2564
|
+
const limit = options?.limit;
|
|
2565
|
+
const maxOutputSize = options?.maxOutputSize;
|
|
2566
|
+
let count = 0;
|
|
2567
|
+
for await (const result of results) {
|
|
2568
|
+
yield result;
|
|
2569
|
+
count++;
|
|
2570
|
+
if (limit !== void 0 && count >= limit) {
|
|
2571
|
+
break;
|
|
2572
|
+
}
|
|
2573
|
+
if (maxOutputSize !== void 0 && count > maxOutputSize) {
|
|
2574
|
+
throw new Error(`Output size exceeds maximum allowed size of ${maxOutputSize}`);
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2024
2579
|
// src/index.ts
|
|
2025
2580
|
var TYPE_ANY = 1 /* TYPE_ANY */;
|
|
2026
2581
|
var TYPE_ARRAY = 3 /* TYPE_ARRAY */;
|
|
@@ -2035,8 +2590,37 @@ var TYPE_NUMBER = 0 /* TYPE_NUMBER */;
|
|
|
2035
2590
|
var TYPE_OBJECT = 4 /* TYPE_OBJECT */;
|
|
2036
2591
|
var TYPE_STRING = 2 /* TYPE_STRING */;
|
|
2037
2592
|
function compile(expression, options) {
|
|
2593
|
+
return Parser_default.parse(expression, options);
|
|
2594
|
+
}
|
|
2595
|
+
function compileQuery(expression, options) {
|
|
2038
2596
|
const nodeTree = Parser_default.parse(expression, options);
|
|
2039
|
-
|
|
2597
|
+
const fn = function(data) {
|
|
2598
|
+
return TreeInterpreter_default.search(nodeTree, data, options);
|
|
2599
|
+
};
|
|
2600
|
+
fn.search = (data) => TreeInterpreter_default.search(nodeTree, data, options);
|
|
2601
|
+
fn.searchStream = (source, streamOptions) => searchStream(source, nodeTree, { ...options, ...streamOptions });
|
|
2602
|
+
fn.ast = nodeTree;
|
|
2603
|
+
return fn;
|
|
2604
|
+
}
|
|
2605
|
+
function validate(expression, options) {
|
|
2606
|
+
if (typeof expression !== "string") {
|
|
2607
|
+
return { valid: false, error: "Expression must be a string" };
|
|
2608
|
+
}
|
|
2609
|
+
try {
|
|
2610
|
+
const ast = Parser_default.parse(expression, options);
|
|
2611
|
+
if (options) {
|
|
2612
|
+
const fnError = findDisallowedFunction(ast, options);
|
|
2613
|
+
if (fnError) {
|
|
2614
|
+
return { valid: false, error: fnError };
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
return { valid: true, ast };
|
|
2618
|
+
} catch (err) {
|
|
2619
|
+
return {
|
|
2620
|
+
valid: false,
|
|
2621
|
+
error: err instanceof Error ? err.message : String(err)
|
|
2622
|
+
};
|
|
2623
|
+
}
|
|
2040
2624
|
}
|
|
2041
2625
|
function tokenize(expression, options) {
|
|
2042
2626
|
return Lexer_default.tokenize(expression, options);
|
|
@@ -2062,9 +2646,26 @@ var getCustomFunctions = () => {
|
|
|
2062
2646
|
var clearCustomFunctions = () => {
|
|
2063
2647
|
TreeInterpreter_default.runtime.clearCustomFunctions();
|
|
2064
2648
|
};
|
|
2649
|
+
var MAX_CACHE_SIZE = 1e3;
|
|
2650
|
+
var astCache = /* @__PURE__ */ new Map();
|
|
2065
2651
|
function search(data, expression, options) {
|
|
2066
|
-
|
|
2067
|
-
|
|
2652
|
+
let nodeTree;
|
|
2653
|
+
if (!options) {
|
|
2654
|
+
nodeTree = astCache.get(expression);
|
|
2655
|
+
if (!nodeTree) {
|
|
2656
|
+
nodeTree = Parser_default.parse(expression);
|
|
2657
|
+
if (astCache.size >= MAX_CACHE_SIZE) {
|
|
2658
|
+
const firstKey = astCache.keys().next().value;
|
|
2659
|
+
if (firstKey !== void 0) {
|
|
2660
|
+
astCache.delete(firstKey);
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
astCache.set(expression, nodeTree);
|
|
2664
|
+
}
|
|
2665
|
+
} else {
|
|
2666
|
+
nodeTree = Parser_default.parse(expression, options);
|
|
2667
|
+
}
|
|
2668
|
+
return TreeInterpreter_default.search(nodeTree, data, options);
|
|
2068
2669
|
}
|
|
2069
2670
|
function Scope() {
|
|
2070
2671
|
return new ScopeChain();
|
|
@@ -2072,6 +2673,9 @@ function Scope() {
|
|
|
2072
2673
|
var TreeInterpreter2 = TreeInterpreter_default;
|
|
2073
2674
|
var jmespath = {
|
|
2074
2675
|
compile,
|
|
2676
|
+
compileQuery,
|
|
2677
|
+
searchStream,
|
|
2678
|
+
validate,
|
|
2075
2679
|
registerFunction,
|
|
2076
2680
|
register,
|
|
2077
2681
|
unregisterFunction,
|
|
@@ -2091,9 +2695,13 @@ var jmespath = {
|
|
|
2091
2695
|
TYPE_NULL,
|
|
2092
2696
|
TYPE_NUMBER,
|
|
2093
2697
|
TYPE_OBJECT,
|
|
2094
|
-
TYPE_STRING
|
|
2698
|
+
TYPE_STRING,
|
|
2699
|
+
TYPE_ARRAY_ARRAY,
|
|
2700
|
+
TYPE_ARRAY_OBJECT,
|
|
2701
|
+
Scope
|
|
2095
2702
|
};
|
|
2703
|
+
var index_default = jmespath;
|
|
2096
2704
|
|
|
2097
|
-
export {
|
|
2705
|
+
export { index_default as default };
|
|
2098
2706
|
//# sourceMappingURL=index.esm.js.map
|
|
2099
2707
|
//# sourceMappingURL=index.esm.js.map
|