@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/dist/index.mjs CHANGED
@@ -1,3 +1,81 @@
1
+ // src/utils/ast.ts
2
+ var CHILD_PROPS = ["left", "right", "condition", "child", "operand", "trueExpr", "falseExpr", "expression"];
3
+ function pushChildren(node, stack) {
4
+ const n = node;
5
+ for (const prop of CHILD_PROPS) {
6
+ const val = n[prop];
7
+ if (val && typeof val === "object" && "type" in val) {
8
+ stack.push(val);
9
+ }
10
+ }
11
+ if (Array.isArray(n.children)) {
12
+ for (const item of n.children) {
13
+ if (!item) {
14
+ continue;
15
+ }
16
+ stack.push(item);
17
+ if (item.type === "KeyValuePair" && item.value) {
18
+ stack.push(item.value);
19
+ }
20
+ }
21
+ }
22
+ if (Array.isArray(n.bindings)) {
23
+ for (const item of n.bindings) {
24
+ if (!item) {
25
+ continue;
26
+ }
27
+ stack.push(item);
28
+ if (item.reference) {
29
+ stack.push(item.reference);
30
+ }
31
+ }
32
+ }
33
+ }
34
+ function forEachNode(root, visitor) {
35
+ const stack = [root];
36
+ while (stack.length > 0) {
37
+ const current = stack.pop();
38
+ if (!current) {
39
+ break;
40
+ }
41
+ if (visitor(current) === false) {
42
+ return;
43
+ }
44
+ pushChildren(current, stack);
45
+ }
46
+ }
47
+ function countNodes(root) {
48
+ let count = 0;
49
+ forEachNode(root, () => {
50
+ count += 1;
51
+ return true;
52
+ });
53
+ return count;
54
+ }
55
+ function findDisallowedFunction(root, options) {
56
+ const { allowedFunctions, disallowedFunctions } = options;
57
+ if (!allowedFunctions && !disallowedFunctions) {
58
+ return null;
59
+ }
60
+ let violation = null;
61
+ forEachNode(root, (node) => {
62
+ if (node.type !== "Function") {
63
+ return true;
64
+ }
65
+ const name = node.name;
66
+ if (allowedFunctions && !allowedFunctions.includes(name)) {
67
+ violation = `Function '${name}' is not allowed`;
68
+ return false;
69
+ }
70
+ if (disallowedFunctions && disallowedFunctions.includes(name)) {
71
+ violation = `Function '${name}' is disallowed`;
72
+ return false;
73
+ }
74
+ return true;
75
+ });
76
+ return violation;
77
+ }
78
+
1
79
  // src/utils/index.ts
2
80
  var isObject = (obj) => {
3
81
  return obj !== null && Object.prototype.toString.call(obj) === "[object Object]";
@@ -47,9 +125,6 @@ var isFalse = (obj) => {
47
125
  if (Array.isArray(obj)) {
48
126
  return obj.length === 0;
49
127
  }
50
- if (obj === null) {
51
- return true;
52
- }
53
128
  return Object.keys(obj).length === 0;
54
129
  }
55
130
  return false;
@@ -94,111 +169,28 @@ var notZero = (n) => {
94
169
  };
95
170
  var add = (left, right) => {
96
171
  ensureNumbers(left, right);
97
- const result = left + right;
98
- return result;
172
+ return left + right;
99
173
  };
100
174
  var sub = (left, right) => {
101
175
  ensureNumbers(left, right);
102
- const result = left - right;
103
- return result;
176
+ return left - right;
104
177
  };
105
178
  var mul = (left, right) => {
106
179
  ensureNumbers(left, right);
107
- const result = left * right;
108
- return result;
180
+ return left * right;
109
181
  };
110
182
  var divide = (left, right) => {
111
183
  ensureNumbers(left, right);
112
- const result = left / notZero(right);
113
- return result;
184
+ return left / notZero(right);
114
185
  };
115
186
  var div = (left, right) => {
116
187
  ensureNumbers(left, right);
117
- const result = Math.floor(left / notZero(right));
118
- return result;
188
+ return Math.floor(left / notZero(right));
119
189
  };
120
190
  var mod = (left, right) => {
121
191
  ensureNumbers(left, right);
122
- const result = left % right;
123
- return result;
124
- };
125
-
126
- // src/utils/strings.ts
127
- var findFirst = (subject, sub2, start, end) => {
128
- if (!subject || !sub2) {
129
- return null;
130
- }
131
- start = Math.max(ensureInteger(start = start || 0), 0);
132
- end = Math.min(ensureInteger(end = end || subject.length), subject.length);
133
- const offset = subject.slice(start, end).indexOf(sub2);
134
- return offset === -1 ? null : offset + start;
135
- };
136
- var findLast = (subject, sub2, start, end) => {
137
- if (!subject || !sub2) {
138
- return null;
139
- }
140
- start = Math.max(ensureInteger(start = start || 0), 0);
141
- end = Math.min(ensureInteger(end = end || subject.length), subject.length);
142
- const offset = subject.slice(start, end).lastIndexOf(sub2);
143
- const result = offset === -1 ? null : offset + start;
144
- return result;
145
- };
146
- var lower = (subject) => subject.toLowerCase();
147
- var ensurePadFuncParams = (name, width, padding) => {
148
- padding = padding || " ";
149
- if (padding.length > 1) {
150
- throw new Error(`invalid value, ${name} expects its 'pad' parameter to be a valid string with a single codepoint`);
151
- }
152
- ensurePositiveInteger(width);
153
- return padding;
154
- };
155
- var padLeft = (subject, width, padding) => {
156
- padding = ensurePadFuncParams("pad_left", width, padding);
157
- return subject && subject.padStart(width, padding) || "";
158
- };
159
- var padRight = (subject, width, padding) => {
160
- padding = ensurePadFuncParams("pad_right", width, padding);
161
- return subject && subject.padEnd(width, padding) || "";
162
- };
163
- var replace = (subject, string, by, count) => {
164
- if (count === 0) {
165
- return subject;
166
- }
167
- if (!count) {
168
- return subject.split(string).join(by);
169
- }
170
- ensurePositiveInteger(count);
171
- [...Array(count).keys()].map(() => subject = subject.replace(string, by));
172
- return subject;
173
- };
174
- var split = (subject, search2, count) => {
175
- if (subject.length == 0 && search2.length === 0) {
176
- return [];
177
- }
178
- if (count === null || count === void 0) {
179
- return subject.split(search2);
180
- }
181
- ensurePositiveInteger(count);
182
- if (count === 0) {
183
- return [subject];
184
- }
185
- const split2 = subject.split(search2);
186
- return [...split2.slice(0, count), split2.slice(count).join(search2)];
187
- };
188
- var trim = (subject, chars) => {
189
- return trimLeft(trimRight(subject, chars), chars);
190
- };
191
- var trimLeft = (subject, chars) => {
192
- return trimImpl(subject, (list) => new RegExp(`^[${list}]*(.*?)`), chars);
193
- };
194
- var trimRight = (subject, chars) => {
195
- return trimImpl(subject, (list) => new RegExp(`(.*?)[${list}]*$`), chars);
192
+ return left % right;
196
193
  };
197
- var trimImpl = (subject, regExper, chars) => {
198
- const pattern = chars ? chars.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&") : "\\s\x85";
199
- return subject.replace(regExper(pattern), "$1");
200
- };
201
- var upper = (subject) => subject.toUpperCase();
202
194
 
203
195
  // src/Lexer.ts
204
196
  var basicTokens = {
@@ -379,7 +371,7 @@ var StreamLexer = class {
379
371
  }
380
372
  this._current += 1;
381
373
  const literal = stream.slice(start + 1, this._current - 1);
382
- return replace(replace(literal, `\\\\`, `\\`), `\\'`, `'`);
374
+ return literal.replace(/\\(['\\])/g, "$1");
383
375
  }
384
376
  consumeNumber(stream) {
385
377
  const start = this._current;
@@ -544,14 +536,25 @@ var bindingPower = {
544
536
  var TokenParser = class _TokenParser {
545
537
  index = 0;
546
538
  tokens = [];
539
+ depth = 0;
540
+ maxDepth;
541
+ nodeCount = 0;
542
+ maxNodes;
547
543
  parse(expression, options) {
548
544
  this.loadTokens(expression, options || { enable_legacy_literals: false });
549
545
  this.index = 0;
546
+ this.depth = 0;
547
+ this.nodeCount = 0;
548
+ this.maxDepth = options?.maxDepth;
549
+ this.maxNodes = options?.maxNodes;
550
550
  const ast = this.expression(0);
551
551
  if (this.lookahead(0) !== "EOF" /* TOK_EOF */) {
552
552
  const token = this.lookaheadToken(0);
553
553
  this.errorToken(token, `Syntax error: unexpected token type: ${token.type}, value: ${token.value}`);
554
554
  }
555
+ if (this.maxNodes !== void 0 && countNodes(ast) > this.maxNodes) {
556
+ throw new Error(`Expression exceeds maximum allowed node count of ${this.maxNodes}`);
557
+ }
555
558
  return ast;
556
559
  }
557
560
  loadTokens(expression, options) {
@@ -559,16 +562,32 @@ var TokenParser = class _TokenParser {
559
562
  this.tokens.push({ type: "EOF" /* TOK_EOF */, value: "", start: expression.length });
560
563
  }
561
564
  expression(rbp) {
562
- const leftToken = this.lookaheadToken(0);
563
- this.advance();
564
- let left = this.nud(leftToken);
565
- let currentTokenType = this.lookahead(0);
566
- while (rbp < bindingPower[currentTokenType]) {
565
+ if (this.maxDepth !== void 0 && this.depth >= this.maxDepth) {
566
+ throw new Error(`Expression exceeds maximum allowed depth of ${this.maxDepth}`);
567
+ }
568
+ this.depth += 1;
569
+ this.trackNode();
570
+ try {
571
+ const leftToken = this.lookaheadToken(0);
567
572
  this.advance();
568
- left = this.led(currentTokenType, left);
569
- currentTokenType = this.lookahead(0);
573
+ let left = this.nud(leftToken);
574
+ let currentTokenType = this.lookahead(0);
575
+ while (rbp < bindingPower[currentTokenType]) {
576
+ this.trackNode();
577
+ this.advance();
578
+ left = this.led(currentTokenType, left);
579
+ currentTokenType = this.lookahead(0);
580
+ }
581
+ return left;
582
+ } finally {
583
+ this.depth -= 1;
584
+ }
585
+ }
586
+ trackNode() {
587
+ this.nodeCount += 1;
588
+ if (this.maxNodes !== void 0 && this.nodeCount > this.maxNodes) {
589
+ throw new Error(`Expression exceeds maximum allowed node count of ${this.maxNodes}`);
570
590
  }
571
- return left;
572
591
  }
573
592
  lookahead(offset) {
574
593
  return this.tokens[this.index + offset].type;
@@ -795,9 +814,13 @@ var TokenParser = class _TokenParser {
795
814
  right
796
815
  };
797
816
  if (right.type === "Slice") {
817
+ const rhs = this.parseProjectionRHS(bindingPower.Star);
818
+ if (rhs.type === "Identity") {
819
+ return indexExpr;
820
+ }
798
821
  return {
799
822
  left: indexExpr,
800
- right: this.parseProjectionRHS(bindingPower.Star),
823
+ right: rhs,
801
824
  type: "Projection"
802
825
  };
803
826
  }
@@ -957,6 +980,83 @@ var TokenParser = class _TokenParser {
957
980
  var Parser = new TokenParser();
958
981
  var Parser_default = Parser;
959
982
 
983
+ // src/utils/strings.ts
984
+ var findFirst = (subject, sub2, start, end) => {
985
+ if (!subject || !sub2) {
986
+ return null;
987
+ }
988
+ const s = Math.max(ensureInteger(start ?? 0), 0);
989
+ const e = Math.min(ensureInteger(end ?? subject.length), subject.length);
990
+ const offset = subject.slice(s, e).indexOf(sub2);
991
+ return offset === -1 ? null : offset + s;
992
+ };
993
+ var findLast = (subject, sub2, start, end) => {
994
+ if (!subject || !sub2) {
995
+ return null;
996
+ }
997
+ const s = Math.max(ensureInteger(start ?? 0), 0);
998
+ const e = Math.min(ensureInteger(end ?? subject.length), subject.length);
999
+ const offset = subject.slice(s, e).lastIndexOf(sub2);
1000
+ return offset === -1 ? null : offset + s;
1001
+ };
1002
+ var lower = (subject) => subject.toLowerCase();
1003
+ var ensurePadFuncParams = (name, width, padding = " ") => {
1004
+ if (padding.length > 1) {
1005
+ throw new Error(`invalid value, ${name} expects its 'pad' parameter to be a valid string with a single codepoint`);
1006
+ }
1007
+ ensurePositiveInteger(width);
1008
+ return padding;
1009
+ };
1010
+ var padLeft = (subject, width, padding) => {
1011
+ padding = ensurePadFuncParams("pad_left", width, padding);
1012
+ return subject && subject.padStart(width, padding) || "";
1013
+ };
1014
+ var padRight = (subject, width, padding) => {
1015
+ padding = ensurePadFuncParams("pad_right", width, padding);
1016
+ return subject && subject.padEnd(width, padding) || "";
1017
+ };
1018
+ var replace = (subject, string, by, count) => {
1019
+ if (count === 0) {
1020
+ return subject;
1021
+ }
1022
+ if (!count) {
1023
+ return subject.split(string).join(by);
1024
+ }
1025
+ ensurePositiveInteger(count);
1026
+ while (count-- > 0 && subject.includes(string)) {
1027
+ subject = subject.replace(string, by);
1028
+ }
1029
+ return subject;
1030
+ };
1031
+ var split = (subject, search2, count) => {
1032
+ if (subject.length == 0 && search2.length === 0) {
1033
+ return [];
1034
+ }
1035
+ if (count === null || count === void 0) {
1036
+ return subject.split(search2);
1037
+ }
1038
+ ensurePositiveInteger(count);
1039
+ if (count === 0) {
1040
+ return [subject];
1041
+ }
1042
+ const split2 = subject.split(search2);
1043
+ return [...split2.slice(0, count), split2.slice(count).join(search2)];
1044
+ };
1045
+ var trim = (subject, chars) => {
1046
+ return trimLeft(trimRight(subject, chars), chars);
1047
+ };
1048
+ var trimLeft = (subject, chars) => {
1049
+ return trimImpl(subject, (list) => new RegExp(`^[${list}]*(.*?)`), chars);
1050
+ };
1051
+ var trimRight = (subject, chars) => {
1052
+ return trimImpl(subject, (list) => new RegExp(`(.*?)[${list}]*$`), chars);
1053
+ };
1054
+ var trimImpl = (subject, regExper, chars) => {
1055
+ const pattern = chars ? chars.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&") : "\\s\x85";
1056
+ return subject.replace(regExper(pattern), "$1");
1057
+ };
1058
+ var upper = (subject) => subject.toUpperCase();
1059
+
960
1060
  // src/utils/text.ts
961
1061
  var Text = class _Text {
962
1062
  _text;
@@ -967,7 +1067,11 @@ var Text = class _Text {
967
1067
  return this._text;
968
1068
  }
969
1069
  get length() {
970
- return this.codePoints.length;
1070
+ let count = 0;
1071
+ for (const _ of this._text) {
1072
+ count += 1;
1073
+ }
1074
+ return count;
971
1075
  }
972
1076
  compareTo(other) {
973
1077
  return _Text.compare(this, new _Text(other));
@@ -1002,6 +1106,12 @@ var Text = class _Text {
1002
1106
  var createMathFunction = (mathFn) => ([value]) => mathFn(value);
1003
1107
  var createStringFunction = (stringFn) => ([subject]) => stringFn(subject);
1004
1108
  var createObjectFunction = (objFn) => ([obj]) => objFn(obj);
1109
+ var ARRAY_SUBTYPES = {
1110
+ [8 /* TYPE_ARRAY_NUMBER */]: 0 /* TYPE_NUMBER */,
1111
+ [10 /* TYPE_ARRAY_OBJECT */]: 4 /* TYPE_OBJECT */,
1112
+ [9 /* TYPE_ARRAY_STRING */]: 2 /* TYPE_STRING */,
1113
+ [11 /* TYPE_ARRAY_ARRAY */]: 3 /* TYPE_ARRAY */
1114
+ };
1005
1115
  var Runtime = class {
1006
1116
  _interpreter;
1007
1117
  _functionTable;
@@ -1319,34 +1429,18 @@ var Runtime = class {
1319
1429
  if (expected === 1 /* TYPE_ANY */) {
1320
1430
  return true;
1321
1431
  }
1322
- if (expected === 9 /* TYPE_ARRAY_STRING */ || expected === 8 /* TYPE_ARRAY_NUMBER */ || expected === 10 /* TYPE_ARRAY_OBJECT */ || expected === 11 /* TYPE_ARRAY_ARRAY */ || expected === 3 /* TYPE_ARRAY */) {
1323
- if (expected === 3 /* TYPE_ARRAY */) {
1324
- return actual === 3 /* TYPE_ARRAY */;
1325
- }
1326
- if (actual === 3 /* TYPE_ARRAY */) {
1327
- let subtype;
1328
- if (expected === 8 /* TYPE_ARRAY_NUMBER */) {
1329
- subtype = 0 /* TYPE_NUMBER */;
1330
- } else if (expected === 10 /* TYPE_ARRAY_OBJECT */) {
1331
- subtype = 4 /* TYPE_OBJECT */;
1332
- } else if (expected === 9 /* TYPE_ARRAY_STRING */) {
1333
- subtype = 2 /* TYPE_STRING */;
1334
- } else if (expected === 11 /* TYPE_ARRAY_ARRAY */) {
1335
- subtype = 3 /* TYPE_ARRAY */;
1336
- }
1337
- const array = argValue;
1338
- for (let i = 0; i < array.length; i += 1) {
1339
- const typeName = this.getTypeName(array[i]);
1340
- if (typeName !== void 0 && subtype !== void 0 && !this.typeMatches(typeName, subtype, array[i])) {
1341
- return false;
1342
- }
1343
- }
1344
- return true;
1432
+ const subtype = ARRAY_SUBTYPES[expected];
1433
+ if (subtype !== void 0) {
1434
+ if (actual !== 3 /* TYPE_ARRAY */) {
1435
+ return false;
1345
1436
  }
1346
- } else {
1347
- return actual === expected;
1437
+ const array = argValue;
1438
+ return array.every((item) => {
1439
+ const typeName = this.getTypeName(item);
1440
+ return typeName === void 0 || this.typeMatches(typeName, subtype, item);
1441
+ });
1348
1442
  }
1349
- return false;
1443
+ return actual === expected;
1350
1444
  }
1351
1445
  getTypeName(obj) {
1352
1446
  if (obj === null) {
@@ -1410,9 +1504,8 @@ var Runtime = class {
1410
1504
  }
1411
1505
  return null;
1412
1506
  };
1413
- functionEndsWith = (resolvedArgs) => {
1414
- const [searchStr, suffix] = resolvedArgs;
1415
- return searchStr.includes(suffix, searchStr.length - suffix.length);
1507
+ functionEndsWith = ([searchStr, suffix]) => {
1508
+ return searchStr.endsWith(suffix);
1416
1509
  };
1417
1510
  functionFindFirst = this.createFindFunction(findFirst);
1418
1511
  functionFindLast = this.createFindFunction(findLast);
@@ -1426,21 +1519,24 @@ var Runtime = class {
1426
1519
  };
1427
1520
  }
1428
1521
  functionFromItems = ([array]) => {
1429
- array.map((pair) => {
1430
- if (pair.length != 2 || typeof pair[0] !== "string") {
1522
+ for (const pair of array) {
1523
+ if (pair.length !== 2 || typeof pair[0] !== "string") {
1431
1524
  throw new Error("invalid value, each array must contain two elements, a pair of string and value");
1432
1525
  }
1433
- });
1526
+ }
1434
1527
  return Object.fromEntries(array);
1435
1528
  };
1436
1529
  functionGroupBy = ([array, exprefNode]) => {
1437
1530
  const keyFunction = this.createKeyFunction(exprefNode, [2 /* TYPE_STRING */]);
1438
- return array.reduce((acc, cur) => {
1439
- const k = keyFunction(cur ?? {});
1440
- const target = acc[k] = acc[k] || [];
1441
- target.push(cur);
1442
- return acc;
1443
- }, {});
1531
+ const groups = {};
1532
+ for (const item of array) {
1533
+ const key = keyFunction(item);
1534
+ if (!groups[key]) {
1535
+ groups[key] = [];
1536
+ }
1537
+ groups[key].push(item);
1538
+ }
1539
+ return groups;
1444
1540
  };
1445
1541
  functionItems = ([inputValue]) => {
1446
1542
  return Object.entries(inputValue);
@@ -1503,12 +1599,7 @@ var Runtime = class {
1503
1599
  return maxRecord || null;
1504
1600
  };
1505
1601
  functionMerge = (resolvedArgs) => {
1506
- let merged = {};
1507
- for (let i = 0; i < resolvedArgs.length; i += 1) {
1508
- const current = resolvedArgs[i];
1509
- merged = Object.assign(merged, current);
1510
- }
1511
- return merged;
1602
+ return Object.assign({}, ...resolvedArgs);
1512
1603
  };
1513
1604
  functionMin = ([inputValue]) => {
1514
1605
  if (!inputValue.length) {
@@ -1544,12 +1635,7 @@ var Runtime = class {
1544
1635
  return minRecord || null;
1545
1636
  };
1546
1637
  functionNotNull = (resolvedArgs) => {
1547
- for (let i = 0; i < resolvedArgs.length; i += 1) {
1548
- if (this.getTypeName(resolvedArgs[i]) !== 7 /* TYPE_NULL */) {
1549
- return resolvedArgs[i];
1550
- }
1551
- }
1552
- return null;
1638
+ return resolvedArgs.find((arg) => arg !== null) ?? null;
1553
1639
  };
1554
1640
  functionPadLeft = this.createPadFunction(padLeft);
1555
1641
  functionPadRight = this.createPadFunction(padRight);
@@ -1577,12 +1663,12 @@ var Runtime = class {
1577
1663
  if (typeName === 2 /* TYPE_STRING */) {
1578
1664
  return new Text(inputValue).reverse();
1579
1665
  }
1580
- const reversedArray = inputValue.slice(0);
1666
+ const reversedArray = [...inputValue];
1581
1667
  reversedArray.reverse();
1582
1668
  return reversedArray;
1583
1669
  };
1584
1670
  functionSort = ([inputValue]) => {
1585
- if (inputValue.length == 0) {
1671
+ if (inputValue.length <= 1) {
1586
1672
  return inputValue;
1587
1673
  }
1588
1674
  if (typeof inputValue[0] === "string") {
@@ -1591,8 +1677,8 @@ var Runtime = class {
1591
1677
  return [...inputValue].sort();
1592
1678
  };
1593
1679
  functionSortBy = (resolvedArgs) => {
1594
- const sortedArray = resolvedArgs[0].slice(0);
1595
- if (sortedArray.length === 0) {
1680
+ const sortedArray = [...resolvedArgs[0]];
1681
+ if (sortedArray.length <= 1) {
1596
1682
  return sortedArray;
1597
1683
  }
1598
1684
  const interpreter = this._interpreter;
@@ -1627,10 +1713,7 @@ var Runtime = class {
1627
1713
  return inputValue.reduce((x, y) => x + y, 0);
1628
1714
  };
1629
1715
  functionToArray = ([inputValue]) => {
1630
- if (this.getTypeName(inputValue) === 3 /* TYPE_ARRAY */) {
1631
- return inputValue;
1632
- }
1633
- return [inputValue];
1716
+ return Array.isArray(inputValue) ? inputValue : [inputValue];
1634
1717
  };
1635
1718
  functionToNumber = ([inputValue]) => {
1636
1719
  const typeName = this.getTypeName(inputValue);
@@ -1647,10 +1730,7 @@ var Runtime = class {
1647
1730
  return null;
1648
1731
  };
1649
1732
  functionToString = ([inputValue]) => {
1650
- if (this.getTypeName(inputValue) === 2 /* TYPE_STRING */) {
1651
- return inputValue;
1652
- }
1653
- return JSON.stringify(inputValue);
1733
+ return typeof inputValue === "string" ? inputValue : JSON.stringify(inputValue);
1654
1734
  };
1655
1735
  functionTrim = this.createTrimFunction(trim);
1656
1736
  functionTrimLeft = this.createTrimFunction(trimLeft);
@@ -1663,27 +1743,16 @@ var Runtime = class {
1663
1743
  };
1664
1744
  }
1665
1745
  functionType = ([inputValue]) => {
1666
- switch (this.getTypeName(inputValue)) {
1667
- case 0 /* TYPE_NUMBER */:
1668
- return "number";
1669
- case 2 /* TYPE_STRING */:
1670
- return "string";
1671
- case 3 /* TYPE_ARRAY */:
1672
- return "array";
1673
- case 4 /* TYPE_OBJECT */:
1674
- return "object";
1675
- case 5 /* TYPE_BOOLEAN */:
1676
- return "boolean";
1677
- case 7 /* TYPE_NULL */:
1678
- return "null";
1679
- default:
1680
- throw new Error("invalid-type");
1746
+ const type = this.getTypeName(inputValue);
1747
+ const name = type !== void 0 ? this.TYPE_NAME_TABLE[type] : void 0;
1748
+ if (!name) {
1749
+ throw new Error("invalid-type");
1681
1750
  }
1751
+ return name;
1682
1752
  };
1683
1753
  functionZip = (array) => {
1684
1754
  const length = Math.min(...array.map((arr) => arr.length));
1685
- const result = Array(length).fill(null).map((_, index) => array.map((arr) => arr[index]));
1686
- return result;
1755
+ return Array.from({ length }, (_, index) => array.map((arr) => arr[index]));
1687
1756
  };
1688
1757
  };
1689
1758
 
@@ -1717,23 +1786,108 @@ var TreeInterpreter = class _TreeInterpreter {
1717
1786
  runtime;
1718
1787
  _rootValue = null;
1719
1788
  _scope;
1720
- constructor() {
1789
+ _options;
1790
+ _depth = 0;
1791
+ _deadline = 0;
1792
+ constructor(options) {
1721
1793
  this.runtime = new Runtime(this);
1722
1794
  this._scope = new ScopeChain();
1795
+ if (options) {
1796
+ this._options = options;
1797
+ this._deadline = options.timeoutMs !== void 0 ? Date.now() + options.timeoutMs : 0;
1798
+ }
1723
1799
  }
1724
1800
  withScope(scope) {
1725
- const interpreter = new _TreeInterpreter();
1801
+ const interpreter = new _TreeInterpreter(this._options);
1726
1802
  interpreter.runtime._functionTable = this.runtime._functionTable;
1727
1803
  interpreter._rootValue = this._rootValue;
1728
1804
  interpreter._scope = this._scope.withScope(scope);
1805
+ interpreter._depth = this._depth;
1806
+ interpreter._deadline = this._deadline;
1729
1807
  return interpreter;
1730
1808
  }
1731
- search(node, value) {
1809
+ search(node, value, options) {
1810
+ if (options?.maxNodes !== void 0 && countNodes(node) > options.maxNodes) {
1811
+ throw new Error(`Expression exceeds maximum allowed node count of ${options.maxNodes}`);
1812
+ }
1732
1813
  this._rootValue = value;
1733
1814
  this._scope = emptyScopeChain;
1734
- return this.visit(node, value);
1815
+ this._options = options;
1816
+ this._depth = 0;
1817
+ this._deadline = options?.timeoutMs !== void 0 ? Date.now() + options.timeoutMs : 0;
1818
+ const result = this.visit(node, value);
1819
+ this.checkOutputSize(result);
1820
+ return result;
1821
+ }
1822
+ checkOutputSize(val) {
1823
+ const max = this._options?.maxOutputSize;
1824
+ if (max === void 0 || val == null) {
1825
+ return;
1826
+ }
1827
+ const size = Array.isArray(val) || typeof val === "string" ? val.length : typeof val === "object" ? Object.keys(val).length : 0;
1828
+ if (size > max) {
1829
+ throw new Error(`Output size exceeds maximum allowed size of ${max}`);
1830
+ }
1831
+ }
1832
+ collect(target, item) {
1833
+ target.push(item);
1834
+ if (this._options?.maxOutputSize !== void 0 && target.length > this._options.maxOutputSize) {
1835
+ throw new Error(`Output size exceeds maximum allowed size of ${this._options.maxOutputSize}`);
1836
+ }
1837
+ }
1838
+ evaluateProjectionItems(items, right) {
1839
+ const collected = [];
1840
+ if (right.type === "Field") {
1841
+ const key = right.name;
1842
+ for (let i = 0; i < items.length; i++) {
1843
+ if (this._deadline > 0 && Date.now() >= this._deadline) {
1844
+ throw new Error(`Query execution timed out after ${this._options?.timeoutMs}ms`);
1845
+ }
1846
+ const elem = items[i];
1847
+ if (!elem || typeof elem !== "object" || Array.isArray(elem)) {
1848
+ continue;
1849
+ }
1850
+ const val = elem[key];
1851
+ if (val !== void 0 && val !== null) {
1852
+ this.collect(collected, val);
1853
+ }
1854
+ }
1855
+ return collected;
1856
+ }
1857
+ if (right.type === "Identity") {
1858
+ for (let i = 0; i < items.length; i++) {
1859
+ const elem = items[i];
1860
+ if (elem !== null) {
1861
+ this.collect(collected, elem);
1862
+ }
1863
+ }
1864
+ return collected;
1865
+ }
1866
+ for (const elem of items) {
1867
+ const current = this.visit(right, elem);
1868
+ if (current !== null) {
1869
+ this.collect(collected, current);
1870
+ }
1871
+ }
1872
+ return collected;
1735
1873
  }
1736
1874
  visit(node, value) {
1875
+ if (this._options) {
1876
+ if (this._options.maxDepth !== void 0 && this._depth >= this._options.maxDepth) {
1877
+ throw new Error(`Evaluation exceeds maximum allowed depth of ${this._options.maxDepth}`);
1878
+ }
1879
+ if (this._deadline > 0 && Date.now() >= this._deadline) {
1880
+ throw new Error(`Query execution timed out after ${this._options.timeoutMs}ms`);
1881
+ }
1882
+ }
1883
+ this._depth += 1;
1884
+ try {
1885
+ return this.evaluateNode(node, value);
1886
+ } finally {
1887
+ this._depth -= 1;
1888
+ }
1889
+ }
1890
+ evaluateNode(node, value) {
1737
1891
  switch (node.type) {
1738
1892
  case "Ternary": {
1739
1893
  const condition = this.visit(node.condition, value);
@@ -1749,16 +1903,11 @@ var TreeInterpreter = class _TreeInterpreter {
1749
1903
  }
1750
1904
  return value[identifier] ?? null;
1751
1905
  case "LetExpression": {
1752
- const { bindings, expression } = node;
1753
- let scope = {};
1754
- bindings.forEach((binding) => {
1755
- const reference = this.visit(binding, value);
1756
- scope = {
1757
- ...scope,
1758
- ...reference
1759
- };
1760
- });
1761
- return this.withScope(scope).visit(expression, value);
1906
+ const scope = {};
1907
+ for (const binding of node.bindings) {
1908
+ Object.assign(scope, this.visit(binding, value));
1909
+ }
1910
+ return this.withScope(scope).visit(node.expression, value);
1762
1911
  }
1763
1912
  case "Binding": {
1764
1913
  const { variable, reference } = node;
@@ -1790,51 +1939,27 @@ var TreeInterpreter = class _TreeInterpreter {
1790
1939
  return null;
1791
1940
  }
1792
1941
  const { start, stop, step } = this.computeSliceParams(value.length, node);
1793
- if (typeof value === "string") {
1794
- const chars = [...value];
1795
- const sliced = this.slice(chars, start, stop, step);
1796
- return sliced.join("");
1797
- } else {
1798
- return this.slice(value, start, stop, step);
1799
- }
1942
+ const target = typeof value === "string" ? [...value] : value;
1943
+ const sliced = this.slice(target, start, stop, step);
1944
+ const res = typeof value === "string" ? sliced.join("") : sliced;
1945
+ this.checkOutputSize(res);
1946
+ return res;
1800
1947
  }
1801
1948
  case "Projection": {
1802
1949
  const { left, right } = node;
1803
- let allowString = false;
1804
- if (left.type === "IndexExpression" && left.right.type === "Slice") {
1805
- allowString = true;
1806
- }
1950
+ const allowString = left.type === "IndexExpression" && left.right.type === "Slice";
1807
1951
  const base = this.visit(left, value);
1808
1952
  if (allowString && typeof base === "string") {
1809
1953
  return this.visit(right, base);
1810
1954
  }
1811
- if (!Array.isArray(base)) {
1812
- return null;
1813
- }
1814
- const collected = [];
1815
- for (const elem of base) {
1816
- const current = this.visit(right, elem);
1817
- if (current !== null) {
1818
- collected.push(current);
1819
- }
1820
- }
1821
- return collected;
1955
+ return Array.isArray(base) ? this.evaluateProjectionItems(base, right) : null;
1822
1956
  }
1823
1957
  case "ValueProjection": {
1824
- const { left, right } = node;
1825
- const base = this.visit(left, value);
1958
+ const base = this.visit(node.left, value);
1826
1959
  if (base === null || typeof base !== "object" || Array.isArray(base)) {
1827
1960
  return null;
1828
1961
  }
1829
- const collected = [];
1830
- const values = Object.values(base);
1831
- for (const elem of values) {
1832
- const current = this.visit(right, elem);
1833
- if (current !== null) {
1834
- collected.push(current);
1835
- }
1836
- }
1837
- return collected;
1962
+ return this.evaluateProjectionItems(Object.values(base), node.right);
1838
1963
  }
1839
1964
  case "FilterProjection": {
1840
1965
  const { left, right, condition } = node;
@@ -1843,14 +1968,42 @@ var TreeInterpreter = class _TreeInterpreter {
1843
1968
  return null;
1844
1969
  }
1845
1970
  const results = [];
1971
+ if (right.type === "Field") {
1972
+ const key = right.name;
1973
+ for (let i = 0; i < base.length; i++) {
1974
+ const elem = base[i];
1975
+ if (isFalse(this.visit(condition, elem))) {
1976
+ continue;
1977
+ }
1978
+ if (!elem || typeof elem !== "object" || Array.isArray(elem)) {
1979
+ continue;
1980
+ }
1981
+ const val = elem[key];
1982
+ if (val !== void 0 && val !== null) {
1983
+ this.collect(results, val);
1984
+ }
1985
+ }
1986
+ return results;
1987
+ }
1988
+ if (right.type === "Identity") {
1989
+ for (let i = 0; i < base.length; i++) {
1990
+ const elem = base[i];
1991
+ if (isFalse(this.visit(condition, elem))) {
1992
+ continue;
1993
+ }
1994
+ if (elem !== null) {
1995
+ this.collect(results, elem);
1996
+ }
1997
+ }
1998
+ return results;
1999
+ }
1846
2000
  for (const elem of base) {
1847
- const matched = this.visit(condition, elem);
1848
- if (isFalse(matched)) {
2001
+ if (isFalse(this.visit(condition, elem))) {
1849
2002
  continue;
1850
2003
  }
1851
2004
  const result = this.visit(right, elem);
1852
2005
  if (result !== null) {
1853
- results.push(result);
2006
+ this.collect(results, result);
1854
2007
  }
1855
2008
  }
1856
2009
  return results;
@@ -1914,7 +2067,9 @@ var TreeInterpreter = class _TreeInterpreter {
1914
2067
  }
1915
2068
  case "Flatten": {
1916
2069
  const original = this.visit(node.child, value);
1917
- return Array.isArray(original) ? original.flat() : null;
2070
+ const res = Array.isArray(original) ? original.flat() : null;
2071
+ this.checkOutputSize(res);
2072
+ return res;
1918
2073
  }
1919
2074
  case "Root":
1920
2075
  return this._rootValue;
@@ -1923,6 +2078,7 @@ var TreeInterpreter = class _TreeInterpreter {
1923
2078
  for (const child of node.children) {
1924
2079
  collected.push(this.visit(child, value));
1925
2080
  }
2081
+ this.checkOutputSize(collected);
1926
2082
  return collected;
1927
2083
  }
1928
2084
  case "MultiSelectHash": {
@@ -1930,6 +2086,7 @@ var TreeInterpreter = class _TreeInterpreter {
1930
2086
  for (const child of node.children) {
1931
2087
  collected[child.name] = this.visit(child.value, value);
1932
2088
  }
2089
+ this.checkOutputSize(collected);
1933
2090
  return collected;
1934
2091
  }
1935
2092
  case "OrExpression": {
@@ -1953,11 +2110,19 @@ var TreeInterpreter = class _TreeInterpreter {
1953
2110
  case "Pipe":
1954
2111
  return this.visit(node.right, this.visit(node.left, value));
1955
2112
  case "Function": {
2113
+ if (this._options?.allowedFunctions && !this._options.allowedFunctions.includes(node.name)) {
2114
+ throw new Error(`Function '${node.name}' is not allowed`);
2115
+ }
2116
+ if (this._options?.disallowedFunctions && this._options.disallowedFunctions.includes(node.name)) {
2117
+ throw new Error(`Function '${node.name}' is disallowed`);
2118
+ }
1956
2119
  const args = [];
1957
2120
  for (const child of node.children) {
1958
2121
  args.push(this.visit(child, value));
1959
2122
  }
1960
- return this.runtime.callFunction(node.name, args);
2123
+ const res = this.runtime.callFunction(node.name, args);
2124
+ this.checkOutputSize(res);
2125
+ return res;
1961
2126
  }
1962
2127
  case "ExpressionReference":
1963
2128
  return {
@@ -1995,14 +2160,19 @@ var TreeInterpreter = class _TreeInterpreter {
1995
2160
  return nextActualValue;
1996
2161
  }
1997
2162
  slice(collection, start, end, step) {
1998
- const result = [];
2163
+ if (step === 1) {
2164
+ return collection.slice(start, end);
2165
+ }
2166
+ const len = Math.ceil(Math.abs(start - end) / Math.abs(step));
2167
+ const result = new Array(len);
2168
+ let idx = 0;
1999
2169
  if (step > 0) {
2000
2170
  for (let i = start; i < end; i += step) {
2001
- result.push(collection[i]);
2171
+ result[idx++] = collection[i];
2002
2172
  }
2003
2173
  } else {
2004
2174
  for (let i = start; i > end; i += step) {
2005
- result.push(collection[i]);
2175
+ result[idx++] = collection[i];
2006
2176
  }
2007
2177
  }
2008
2178
  return result;
@@ -2011,6 +2181,391 @@ var TreeInterpreter = class _TreeInterpreter {
2011
2181
  var TreeInterpreterInstance = new TreeInterpreter();
2012
2182
  var TreeInterpreter_default = TreeInterpreterInstance;
2013
2183
 
2184
+ // src/Stream.ts
2185
+ async function* toAsyncIterable(source) {
2186
+ if (source == null) {
2187
+ return;
2188
+ }
2189
+ if (typeof source !== "object" && typeof source !== "function") {
2190
+ throw new TypeError("Invalid stream source: expected AsyncIterable, Iterable, or ReadableStream");
2191
+ }
2192
+ if (Symbol.asyncIterator in source) {
2193
+ for await (const chunk of source) {
2194
+ yield chunk;
2195
+ }
2196
+ return;
2197
+ }
2198
+ if (typeof source.getReader === "function") {
2199
+ const reader = source.getReader();
2200
+ try {
2201
+ while (true) {
2202
+ const { done, value } = await reader.read();
2203
+ if (done) {
2204
+ break;
2205
+ }
2206
+ yield value;
2207
+ }
2208
+ } finally {
2209
+ reader.releaseLock();
2210
+ }
2211
+ return;
2212
+ }
2213
+ if (Symbol.iterator in source) {
2214
+ for (const chunk of source) {
2215
+ yield chunk;
2216
+ }
2217
+ return;
2218
+ }
2219
+ throw new TypeError("Invalid stream source: expected AsyncIterable, Iterable, or ReadableStream");
2220
+ }
2221
+ function parseItem(str, parseJson) {
2222
+ if (parseJson === true) {
2223
+ return JSON.parse(str);
2224
+ }
2225
+ if (parseJson === "auto") {
2226
+ try {
2227
+ return JSON.parse(str);
2228
+ } catch {
2229
+ return str;
2230
+ }
2231
+ }
2232
+ return str;
2233
+ }
2234
+ async function* normalizeSource(source, options) {
2235
+ const parseJson = options?.parseJson ?? "auto";
2236
+ const flatten = options?.flattenChunks ?? true;
2237
+ let buffer = "";
2238
+ const textDecoder = typeof TextDecoder !== "undefined" ? new TextDecoder() : null;
2239
+ for await (const chunk of toAsyncIterable(source)) {
2240
+ if (chunk instanceof Uint8Array && textDecoder) {
2241
+ buffer += textDecoder.decode(chunk, { stream: true });
2242
+ if (buffer.includes("\n")) {
2243
+ const lines = buffer.split("\n");
2244
+ buffer = lines.pop() ?? "";
2245
+ for (const line of lines) {
2246
+ const trimmed = line.trim();
2247
+ if (trimmed) {
2248
+ yield parseItem(trimmed, parseJson);
2249
+ }
2250
+ }
2251
+ }
2252
+ } else if (typeof chunk === "string") {
2253
+ if (parseJson === false) {
2254
+ yield chunk;
2255
+ } else {
2256
+ buffer += chunk;
2257
+ if (buffer.includes("\n")) {
2258
+ const lines = buffer.split("\n");
2259
+ buffer = lines.pop() ?? "";
2260
+ for (const line of lines) {
2261
+ const trimmed = line.trim();
2262
+ if (trimmed) {
2263
+ yield parseItem(trimmed, parseJson);
2264
+ }
2265
+ }
2266
+ }
2267
+ }
2268
+ } else if (flatten && Array.isArray(chunk)) {
2269
+ if (buffer.trim()) {
2270
+ yield parseItem(buffer.trim(), parseJson);
2271
+ buffer = "";
2272
+ }
2273
+ for (let i = 0; i < chunk.length; i++) {
2274
+ yield chunk[i];
2275
+ }
2276
+ } else {
2277
+ if (buffer.trim()) {
2278
+ yield parseItem(buffer.trim(), parseJson);
2279
+ buffer = "";
2280
+ }
2281
+ yield chunk;
2282
+ }
2283
+ }
2284
+ if (textDecoder && buffer) {
2285
+ buffer += textDecoder.decode();
2286
+ }
2287
+ if (buffer.trim()) {
2288
+ yield parseItem(buffer.trim(), parseJson);
2289
+ }
2290
+ }
2291
+ function isStreamableNode(node) {
2292
+ switch (node.type) {
2293
+ case "Projection":
2294
+ if (node.left.type === "Identity" || node.left.type === "Current") {
2295
+ return true;
2296
+ }
2297
+ if (node.left.type === "IndexExpression" && node.left.right.type === "Slice") {
2298
+ const slice = node.left.right;
2299
+ return (slice.start === null || slice.start >= 0) && (slice.stop === null || slice.stop >= 0) && (slice.step === null || slice.step > 0);
2300
+ }
2301
+ return false;
2302
+ case "FilterProjection":
2303
+ return node.left.type === "Identity" || node.left.type === "Current";
2304
+ case "IndexExpression":
2305
+ if (node.right.type === "Slice" && (node.left.type === "Identity" || node.left.type === "Current")) {
2306
+ const slice = node.right;
2307
+ return (slice.start === null || slice.start >= 0) && (slice.stop === null || slice.stop >= 0) && (slice.step === null || slice.step > 0);
2308
+ }
2309
+ return true;
2310
+ case "Field":
2311
+ case "Identity":
2312
+ case "Current":
2313
+ case "Subexpression":
2314
+ case "MultiSelectHash":
2315
+ case "MultiSelectList":
2316
+ case "Ternary":
2317
+ case "Comparator":
2318
+ case "Arithmetic":
2319
+ case "NotExpression":
2320
+ return true;
2321
+ case "Pipe":
2322
+ return isStreamableNode(node.left) && isStreamableNode(node.right);
2323
+ default:
2324
+ return false;
2325
+ }
2326
+ }
2327
+ async function* evaluateStreamNode(source, node, interpreter, options) {
2328
+ const deadline = options?.timeoutMs !== void 0 ? Date.now() + options.timeoutMs : 0;
2329
+ function checkDeadline() {
2330
+ if (deadline > 0 && Date.now() >= deadline) {
2331
+ throw new Error(`Query execution timed out after ${options?.timeoutMs}ms`);
2332
+ }
2333
+ }
2334
+ switch (node.type) {
2335
+ case "Projection": {
2336
+ const { left, right } = node;
2337
+ let streamSource = source;
2338
+ if (left.type === "IndexExpression" && left.right.type === "Slice") {
2339
+ streamSource = evaluateStreamNode(source, left, interpreter, options);
2340
+ }
2341
+ if (right.type === "Identity" || right.type === "Current") {
2342
+ for await (const item of streamSource) {
2343
+ checkDeadline();
2344
+ if (item !== null && item !== void 0) {
2345
+ yield item;
2346
+ }
2347
+ }
2348
+ return;
2349
+ }
2350
+ if (right.type === "Field") {
2351
+ const key = right.name;
2352
+ for await (const item of streamSource) {
2353
+ checkDeadline();
2354
+ if (item && typeof item === "object" && !Array.isArray(item)) {
2355
+ const val = item[key];
2356
+ if (val !== void 0 && val !== null) {
2357
+ yield val;
2358
+ }
2359
+ }
2360
+ }
2361
+ return;
2362
+ }
2363
+ for await (const item of streamSource) {
2364
+ checkDeadline();
2365
+ const res = interpreter.visit(right, item);
2366
+ if (res !== null && res !== void 0) {
2367
+ yield res;
2368
+ }
2369
+ }
2370
+ return;
2371
+ }
2372
+ case "IndexExpression": {
2373
+ if (node.right.type === "Slice" && (node.left.type === "Identity" || node.left.type === "Current")) {
2374
+ const slice = node.right;
2375
+ const start = slice.start ?? 0;
2376
+ const stop = slice.stop ?? Infinity;
2377
+ const step = slice.step ?? 1;
2378
+ if (start >= 0 && stop >= 0 && step > 0) {
2379
+ let index = 0;
2380
+ for await (const item of source) {
2381
+ checkDeadline();
2382
+ if (index >= stop) {
2383
+ break;
2384
+ }
2385
+ if (index >= start && (index - start) % step === 0) {
2386
+ yield item;
2387
+ }
2388
+ index++;
2389
+ if (index >= stop) {
2390
+ break;
2391
+ }
2392
+ }
2393
+ return;
2394
+ }
2395
+ const collected = [];
2396
+ for await (const item of source) {
2397
+ checkDeadline();
2398
+ collected.push(item);
2399
+ if (options?.maxOutputSize !== void 0 && collected.length > options.maxOutputSize) {
2400
+ throw new Error(`Output size exceeds maximum allowed size of ${options.maxOutputSize}`);
2401
+ }
2402
+ }
2403
+ const result = interpreter.search(node, collected, options);
2404
+ if (Array.isArray(result)) {
2405
+ for (const item of result) {
2406
+ yield item;
2407
+ }
2408
+ }
2409
+ return;
2410
+ }
2411
+ for await (const item of source) {
2412
+ checkDeadline();
2413
+ const res = interpreter.visit(node, item);
2414
+ if (res !== null && res !== void 0) {
2415
+ yield res;
2416
+ }
2417
+ }
2418
+ return;
2419
+ }
2420
+ case "FilterProjection": {
2421
+ const { condition, right } = node;
2422
+ if (right.type === "Identity" || right.type === "Current") {
2423
+ for await (const item of source) {
2424
+ checkDeadline();
2425
+ if (!isFalse(interpreter.visit(condition, item))) {
2426
+ yield item;
2427
+ }
2428
+ }
2429
+ return;
2430
+ }
2431
+ if (right.type === "Field") {
2432
+ const key = right.name;
2433
+ for await (const item of source) {
2434
+ checkDeadline();
2435
+ if (!isFalse(interpreter.visit(condition, item))) {
2436
+ if (item && typeof item === "object" && !Array.isArray(item)) {
2437
+ const val = item[key];
2438
+ if (val !== void 0 && val !== null) {
2439
+ yield val;
2440
+ }
2441
+ }
2442
+ }
2443
+ }
2444
+ return;
2445
+ }
2446
+ for await (const item of source) {
2447
+ checkDeadline();
2448
+ if (!isFalse(interpreter.visit(condition, item))) {
2449
+ const res = interpreter.visit(right, item);
2450
+ if (res !== null && res !== void 0) {
2451
+ yield res;
2452
+ }
2453
+ }
2454
+ }
2455
+ return;
2456
+ }
2457
+ case "Pipe": {
2458
+ const leftStream = evaluateStreamNode(source, node.left, interpreter, options);
2459
+ if (isStreamableNode(node.right)) {
2460
+ for await (const res of evaluateStreamNode(leftStream, node.right, interpreter, options)) {
2461
+ yield res;
2462
+ }
2463
+ } else {
2464
+ const collected = [];
2465
+ for await (const item of leftStream) {
2466
+ checkDeadline();
2467
+ collected.push(item);
2468
+ if (options?.maxOutputSize !== void 0 && collected.length > options.maxOutputSize) {
2469
+ throw new Error(`Output size exceeds maximum allowed size of ${options.maxOutputSize}`);
2470
+ }
2471
+ }
2472
+ const result = interpreter.search(node.right, collected, options);
2473
+ if (result !== null && result !== void 0) {
2474
+ yield result;
2475
+ }
2476
+ }
2477
+ return;
2478
+ }
2479
+ case "Identity":
2480
+ case "Current": {
2481
+ for await (const item of source) {
2482
+ checkDeadline();
2483
+ yield item;
2484
+ }
2485
+ return;
2486
+ }
2487
+ case "Field": {
2488
+ const key = node.name;
2489
+ for await (const item of source) {
2490
+ checkDeadline();
2491
+ if (item && typeof item === "object" && !Array.isArray(item)) {
2492
+ const val = item[key];
2493
+ if (val !== void 0 && val !== null) {
2494
+ yield val;
2495
+ }
2496
+ }
2497
+ }
2498
+ return;
2499
+ }
2500
+ default: {
2501
+ if (isStreamableNode(node)) {
2502
+ for await (const item of source) {
2503
+ checkDeadline();
2504
+ const res = interpreter.visit(node, item);
2505
+ if (res !== null && res !== void 0) {
2506
+ yield res;
2507
+ }
2508
+ }
2509
+ return;
2510
+ }
2511
+ const collected = [];
2512
+ for await (const item of source) {
2513
+ checkDeadline();
2514
+ collected.push(item);
2515
+ if (options?.maxOutputSize !== void 0 && collected.length > options.maxOutputSize) {
2516
+ throw new Error(`Output size exceeds maximum allowed size of ${options.maxOutputSize}`);
2517
+ }
2518
+ }
2519
+ const result = interpreter.search(node, collected, options);
2520
+ if (result !== null && result !== void 0) {
2521
+ yield result;
2522
+ }
2523
+ return;
2524
+ }
2525
+ }
2526
+ }
2527
+ function isExpressionNode(val) {
2528
+ return typeof val === "object" && val !== null && "type" in val && typeof val.type === "string" && !(Symbol.iterator in val) && !(Symbol.asyncIterator in val);
2529
+ }
2530
+ async function* searchStream(sourceOrExpression, expressionOrSource, options) {
2531
+ let expression;
2532
+ let source;
2533
+ if (typeof sourceOrExpression === "string" || isExpressionNode(sourceOrExpression)) {
2534
+ expression = sourceOrExpression;
2535
+ source = expressionOrSource;
2536
+ } else {
2537
+ source = sourceOrExpression;
2538
+ expression = expressionOrSource;
2539
+ }
2540
+ if (typeof expression !== "string" && !isExpressionNode(expression)) {
2541
+ throw new TypeError("Expression must be a string or AST ExpressionNode");
2542
+ }
2543
+ const ast = typeof expression === "string" ? Parser_default.parse(expression, options) : expression;
2544
+ if (options) {
2545
+ const fnError = findDisallowedFunction(ast, options);
2546
+ if (fnError) {
2547
+ throw new Error(fnError);
2548
+ }
2549
+ }
2550
+ const interpreter = new TreeInterpreter(options);
2551
+ interpreter.runtime._functionTable = TreeInterpreterInstance.runtime._functionTable;
2552
+ const items = normalizeSource(source, options);
2553
+ const results = evaluateStreamNode(items, ast, interpreter, options);
2554
+ const limit = options?.limit;
2555
+ const maxOutputSize = options?.maxOutputSize;
2556
+ let count = 0;
2557
+ for await (const result of results) {
2558
+ yield result;
2559
+ count++;
2560
+ if (limit !== void 0 && count >= limit) {
2561
+ break;
2562
+ }
2563
+ if (maxOutputSize !== void 0 && count > maxOutputSize) {
2564
+ throw new Error(`Output size exceeds maximum allowed size of ${maxOutputSize}`);
2565
+ }
2566
+ }
2567
+ }
2568
+
2014
2569
  // src/index.ts
2015
2570
  var TYPE_ANY = 1 /* TYPE_ANY */;
2016
2571
  var TYPE_ARRAY = 3 /* TYPE_ARRAY */;
@@ -2025,8 +2580,37 @@ var TYPE_NUMBER = 0 /* TYPE_NUMBER */;
2025
2580
  var TYPE_OBJECT = 4 /* TYPE_OBJECT */;
2026
2581
  var TYPE_STRING = 2 /* TYPE_STRING */;
2027
2582
  function compile(expression, options) {
2583
+ return Parser_default.parse(expression, options);
2584
+ }
2585
+ function compileQuery(expression, options) {
2028
2586
  const nodeTree = Parser_default.parse(expression, options);
2029
- return nodeTree;
2587
+ const fn = function(data) {
2588
+ return TreeInterpreter_default.search(nodeTree, data, options);
2589
+ };
2590
+ fn.search = (data) => TreeInterpreter_default.search(nodeTree, data, options);
2591
+ fn.searchStream = (source, streamOptions) => searchStream(source, nodeTree, { ...options, ...streamOptions });
2592
+ fn.ast = nodeTree;
2593
+ return fn;
2594
+ }
2595
+ function validate(expression, options) {
2596
+ if (typeof expression !== "string") {
2597
+ return { valid: false, error: "Expression must be a string" };
2598
+ }
2599
+ try {
2600
+ const ast = Parser_default.parse(expression, options);
2601
+ if (options) {
2602
+ const fnError = findDisallowedFunction(ast, options);
2603
+ if (fnError) {
2604
+ return { valid: false, error: fnError };
2605
+ }
2606
+ }
2607
+ return { valid: true, ast };
2608
+ } catch (err) {
2609
+ return {
2610
+ valid: false,
2611
+ error: err instanceof Error ? err.message : String(err)
2612
+ };
2613
+ }
2030
2614
  }
2031
2615
  function tokenize(expression, options) {
2032
2616
  return Lexer_default.tokenize(expression, options);
@@ -2052,9 +2636,26 @@ var getCustomFunctions = () => {
2052
2636
  var clearCustomFunctions = () => {
2053
2637
  TreeInterpreter_default.runtime.clearCustomFunctions();
2054
2638
  };
2639
+ var MAX_CACHE_SIZE = 1e3;
2640
+ var astCache = /* @__PURE__ */ new Map();
2055
2641
  function search(data, expression, options) {
2056
- const nodeTree = Parser_default.parse(expression, options);
2057
- return TreeInterpreter_default.search(nodeTree, data);
2642
+ let nodeTree;
2643
+ if (!options) {
2644
+ nodeTree = astCache.get(expression);
2645
+ if (!nodeTree) {
2646
+ nodeTree = Parser_default.parse(expression);
2647
+ if (astCache.size >= MAX_CACHE_SIZE) {
2648
+ const firstKey = astCache.keys().next().value;
2649
+ if (firstKey !== void 0) {
2650
+ astCache.delete(firstKey);
2651
+ }
2652
+ }
2653
+ astCache.set(expression, nodeTree);
2654
+ }
2655
+ } else {
2656
+ nodeTree = Parser_default.parse(expression, options);
2657
+ }
2658
+ return TreeInterpreter_default.search(nodeTree, data, options);
2058
2659
  }
2059
2660
  function Scope() {
2060
2661
  return new ScopeChain();
@@ -2062,6 +2663,9 @@ function Scope() {
2062
2663
  var TreeInterpreter2 = TreeInterpreter_default;
2063
2664
  var jmespath = {
2064
2665
  compile,
2666
+ compileQuery,
2667
+ searchStream,
2668
+ validate,
2065
2669
  registerFunction,
2066
2670
  register,
2067
2671
  unregisterFunction,
@@ -2081,9 +2685,13 @@ var jmespath = {
2081
2685
  TYPE_NULL,
2082
2686
  TYPE_NUMBER,
2083
2687
  TYPE_OBJECT,
2084
- TYPE_STRING
2688
+ TYPE_STRING,
2689
+ TYPE_ARRAY_ARRAY,
2690
+ TYPE_ARRAY_OBJECT,
2691
+ Scope
2085
2692
  };
2693
+ var index_default = jmespath;
2086
2694
 
2087
- export { Scope, TYPE_ANY, TYPE_ARRAY, TYPE_ARRAY_ARRAY, TYPE_ARRAY_NUMBER, TYPE_ARRAY_OBJECT, TYPE_ARRAY_STRING, TYPE_BOOLEAN, TYPE_EXPREF, TYPE_NULL, TYPE_NUMBER, TYPE_OBJECT, TYPE_STRING, TreeInterpreter2 as TreeInterpreter, clearCustomFunctions, compile, jmespath as default, getCustomFunctions, getRegisteredFunctions, isRegistered, jmespath, register, registerFunction, search, tokenize, unregisterFunction };
2695
+ export { index_default as default };
2088
2696
  //# sourceMappingURL=index.mjs.map
2089
2697
  //# sourceMappingURL=index.mjs.map