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