@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/cli.mjs CHANGED
@@ -1,11 +1,89 @@
1
1
  #!/usr/bin/env node
2
- import { parseArgs } from 'util';
3
2
  import * as fs from 'fs';
3
+ import { parseArgs } from 'util';
4
4
 
5
5
  // package.json
6
6
  var package_default = {
7
7
  name: "@jmespath-community/jmespath",
8
- version: "1.3.0"};
8
+ version: "1.4.0"};
9
+
10
+ // src/utils/ast.ts
11
+ var CHILD_PROPS = ["left", "right", "condition", "child", "operand", "trueExpr", "falseExpr", "expression"];
12
+ function pushChildren(node, stack) {
13
+ const n = node;
14
+ for (const prop of CHILD_PROPS) {
15
+ const val = n[prop];
16
+ if (val && typeof val === "object" && "type" in val) {
17
+ stack.push(val);
18
+ }
19
+ }
20
+ if (Array.isArray(n.children)) {
21
+ for (const item of n.children) {
22
+ if (!item) {
23
+ continue;
24
+ }
25
+ stack.push(item);
26
+ if (item.type === "KeyValuePair" && item.value) {
27
+ stack.push(item.value);
28
+ }
29
+ }
30
+ }
31
+ if (Array.isArray(n.bindings)) {
32
+ for (const item of n.bindings) {
33
+ if (!item) {
34
+ continue;
35
+ }
36
+ stack.push(item);
37
+ if (item.reference) {
38
+ stack.push(item.reference);
39
+ }
40
+ }
41
+ }
42
+ }
43
+ function forEachNode(root, visitor) {
44
+ const stack = [root];
45
+ while (stack.length > 0) {
46
+ const current = stack.pop();
47
+ if (!current) {
48
+ break;
49
+ }
50
+ if (visitor(current) === false) {
51
+ return;
52
+ }
53
+ pushChildren(current, stack);
54
+ }
55
+ }
56
+ function countNodes(root) {
57
+ let count = 0;
58
+ forEachNode(root, () => {
59
+ count += 1;
60
+ return true;
61
+ });
62
+ return count;
63
+ }
64
+ function findDisallowedFunction(root, options) {
65
+ const { allowedFunctions, disallowedFunctions } = options;
66
+ if (!allowedFunctions && !disallowedFunctions) {
67
+ return null;
68
+ }
69
+ let violation = null;
70
+ forEachNode(root, (node) => {
71
+ if (node.type !== "Function") {
72
+ return true;
73
+ }
74
+ const name = node.name;
75
+ if (allowedFunctions && !allowedFunctions.includes(name)) {
76
+ violation = `Function '${name}' is not allowed`;
77
+ return false;
78
+ }
79
+ if (disallowedFunctions && disallowedFunctions.includes(name)) {
80
+ violation = `Function '${name}' is disallowed`;
81
+ return false;
82
+ }
83
+ return true;
84
+ });
85
+ return violation;
86
+ }
9
87
 
10
88
  // src/utils/index.ts
11
89
  var isObject = (obj) => {
@@ -56,9 +134,6 @@ var isFalse = (obj) => {
56
134
  if (Array.isArray(obj)) {
57
135
  return obj.length === 0;
58
136
  }
59
- if (obj === null) {
60
- return true;
61
- }
62
137
  return Object.keys(obj).length === 0;
63
138
  }
64
139
  return false;
@@ -103,111 +178,28 @@ var notZero = (n) => {
103
178
  };
104
179
  var add = (left, right) => {
105
180
  ensureNumbers(left, right);
106
- const result = left + right;
107
- return result;
181
+ return left + right;
108
182
  };
109
183
  var sub = (left, right) => {
110
184
  ensureNumbers(left, right);
111
- const result = left - right;
112
- return result;
185
+ return left - right;
113
186
  };
114
187
  var mul = (left, right) => {
115
188
  ensureNumbers(left, right);
116
- const result = left * right;
117
- return result;
189
+ return left * right;
118
190
  };
119
191
  var divide = (left, right) => {
120
192
  ensureNumbers(left, right);
121
- const result = left / notZero(right);
122
- return result;
193
+ return left / notZero(right);
123
194
  };
124
195
  var div = (left, right) => {
125
196
  ensureNumbers(left, right);
126
- const result = Math.floor(left / notZero(right));
127
- return result;
197
+ return Math.floor(left / notZero(right));
128
198
  };
129
199
  var mod = (left, right) => {
130
200
  ensureNumbers(left, right);
131
- const result = left % right;
132
- return result;
133
- };
134
-
135
- // src/utils/strings.ts
136
- var findFirst = (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).indexOf(sub2);
143
- return offset === -1 ? null : offset + start;
144
- };
145
- var findLast = (subject, sub2, start, end) => {
146
- if (!subject || !sub2) {
147
- return null;
148
- }
149
- start = Math.max(ensureInteger(start = start || 0), 0);
150
- end = Math.min(ensureInteger(end = end || subject.length), subject.length);
151
- const offset = subject.slice(start, end).lastIndexOf(sub2);
152
- const result = offset === -1 ? null : offset + start;
153
- return result;
154
- };
155
- var lower = (subject) => subject.toLowerCase();
156
- var ensurePadFuncParams = (name, width, padding) => {
157
- padding = padding || " ";
158
- if (padding.length > 1) {
159
- throw new Error(`invalid value, ${name} expects its 'pad' parameter to be a valid string with a single codepoint`);
160
- }
161
- ensurePositiveInteger(width);
162
- return padding;
163
- };
164
- var padLeft = (subject, width, padding) => {
165
- padding = ensurePadFuncParams("pad_left", width, padding);
166
- return subject && subject.padStart(width, padding) || "";
167
- };
168
- var padRight = (subject, width, padding) => {
169
- padding = ensurePadFuncParams("pad_right", width, padding);
170
- return subject && subject.padEnd(width, padding) || "";
171
- };
172
- var replace = (subject, string, by, count) => {
173
- if (count === 0) {
174
- return subject;
175
- }
176
- if (!count) {
177
- return subject.split(string).join(by);
178
- }
179
- ensurePositiveInteger(count);
180
- [...Array(count).keys()].map(() => subject = subject.replace(string, by));
181
- return subject;
182
- };
183
- var split = (subject, search2, count) => {
184
- if (subject.length == 0 && search2.length === 0) {
185
- return [];
186
- }
187
- if (count === null || count === void 0) {
188
- return subject.split(search2);
189
- }
190
- ensurePositiveInteger(count);
191
- if (count === 0) {
192
- return [subject];
193
- }
194
- const split2 = subject.split(search2);
195
- return [...split2.slice(0, count), split2.slice(count).join(search2)];
196
- };
197
- var trim = (subject, chars) => {
198
- return trimLeft(trimRight(subject, chars), chars);
199
- };
200
- var trimLeft = (subject, chars) => {
201
- return trimImpl(subject, (list) => new RegExp(`^[${list}]*(.*?)`), chars);
202
- };
203
- var trimRight = (subject, chars) => {
204
- return trimImpl(subject, (list) => new RegExp(`(.*?)[${list}]*$`), chars);
205
- };
206
- var trimImpl = (subject, regExper, chars) => {
207
- const pattern = chars ? chars.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&") : "\\s\x85";
208
- return subject.replace(regExper(pattern), "$1");
201
+ return left % right;
209
202
  };
210
- var upper = (subject) => subject.toUpperCase();
211
203
 
212
204
  // src/Lexer.ts
213
205
  var basicTokens = {
@@ -388,7 +380,7 @@ var StreamLexer = class {
388
380
  }
389
381
  this._current += 1;
390
382
  const literal = stream.slice(start + 1, this._current - 1);
391
- return replace(replace(literal, `\\\\`, `\\`), `\\'`, `'`);
383
+ return literal.replace(/\\(['\\])/g, "$1");
392
384
  }
393
385
  consumeNumber(stream) {
394
386
  const start = this._current;
@@ -553,14 +545,25 @@ var bindingPower = {
553
545
  var TokenParser = class _TokenParser {
554
546
  index = 0;
555
547
  tokens = [];
548
+ depth = 0;
549
+ maxDepth;
550
+ nodeCount = 0;
551
+ maxNodes;
556
552
  parse(expression2, options) {
557
553
  this.loadTokens(expression2, options || { enable_legacy_literals: false });
558
554
  this.index = 0;
555
+ this.depth = 0;
556
+ this.nodeCount = 0;
557
+ this.maxDepth = options?.maxDepth;
558
+ this.maxNodes = options?.maxNodes;
559
559
  const ast = this.expression(0);
560
560
  if (this.lookahead(0) !== "EOF" /* TOK_EOF */) {
561
561
  const token = this.lookaheadToken(0);
562
562
  this.errorToken(token, `Syntax error: unexpected token type: ${token.type}, value: ${token.value}`);
563
563
  }
564
+ if (this.maxNodes !== void 0 && countNodes(ast) > this.maxNodes) {
565
+ throw new Error(`Expression exceeds maximum allowed node count of ${this.maxNodes}`);
566
+ }
564
567
  return ast;
565
568
  }
566
569
  loadTokens(expression2, options) {
@@ -568,16 +571,32 @@ var TokenParser = class _TokenParser {
568
571
  this.tokens.push({ type: "EOF" /* TOK_EOF */, value: "", start: expression2.length });
569
572
  }
570
573
  expression(rbp) {
571
- const leftToken = this.lookaheadToken(0);
572
- this.advance();
573
- let left = this.nud(leftToken);
574
- let currentTokenType = this.lookahead(0);
575
- while (rbp < bindingPower[currentTokenType]) {
574
+ if (this.maxDepth !== void 0 && this.depth >= this.maxDepth) {
575
+ throw new Error(`Expression exceeds maximum allowed depth of ${this.maxDepth}`);
576
+ }
577
+ this.depth += 1;
578
+ this.trackNode();
579
+ try {
580
+ const leftToken = this.lookaheadToken(0);
576
581
  this.advance();
577
- left = this.led(currentTokenType, left);
578
- currentTokenType = this.lookahead(0);
582
+ let left = this.nud(leftToken);
583
+ let currentTokenType = this.lookahead(0);
584
+ while (rbp < bindingPower[currentTokenType]) {
585
+ this.trackNode();
586
+ this.advance();
587
+ left = this.led(currentTokenType, left);
588
+ currentTokenType = this.lookahead(0);
589
+ }
590
+ return left;
591
+ } finally {
592
+ this.depth -= 1;
593
+ }
594
+ }
595
+ trackNode() {
596
+ this.nodeCount += 1;
597
+ if (this.maxNodes !== void 0 && this.nodeCount > this.maxNodes) {
598
+ throw new Error(`Expression exceeds maximum allowed node count of ${this.maxNodes}`);
579
599
  }
580
- return left;
581
600
  }
582
601
  lookahead(offset) {
583
602
  return this.tokens[this.index + offset].type;
@@ -804,9 +823,13 @@ var TokenParser = class _TokenParser {
804
823
  right
805
824
  };
806
825
  if (right.type === "Slice") {
826
+ const rhs = this.parseProjectionRHS(bindingPower.Star);
827
+ if (rhs.type === "Identity") {
828
+ return indexExpr;
829
+ }
807
830
  return {
808
831
  left: indexExpr,
809
- right: this.parseProjectionRHS(bindingPower.Star),
832
+ right: rhs,
810
833
  type: "Projection"
811
834
  };
812
835
  }
@@ -966,6 +989,83 @@ var TokenParser = class _TokenParser {
966
989
  var Parser = new TokenParser();
967
990
  var Parser_default = Parser;
968
991
 
992
+ // src/utils/strings.ts
993
+ var findFirst = (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).indexOf(sub2);
1000
+ return offset === -1 ? null : offset + s;
1001
+ };
1002
+ var findLast = (subject, sub2, start, end) => {
1003
+ if (!subject || !sub2) {
1004
+ return null;
1005
+ }
1006
+ const s = Math.max(ensureInteger(start ?? 0), 0);
1007
+ const e = Math.min(ensureInteger(end ?? subject.length), subject.length);
1008
+ const offset = subject.slice(s, e).lastIndexOf(sub2);
1009
+ return offset === -1 ? null : offset + s;
1010
+ };
1011
+ var lower = (subject) => subject.toLowerCase();
1012
+ var ensurePadFuncParams = (name, width, padding = " ") => {
1013
+ if (padding.length > 1) {
1014
+ throw new Error(`invalid value, ${name} expects its 'pad' parameter to be a valid string with a single codepoint`);
1015
+ }
1016
+ ensurePositiveInteger(width);
1017
+ return padding;
1018
+ };
1019
+ var padLeft = (subject, width, padding) => {
1020
+ padding = ensurePadFuncParams("pad_left", width, padding);
1021
+ return subject && subject.padStart(width, padding) || "";
1022
+ };
1023
+ var padRight = (subject, width, padding) => {
1024
+ padding = ensurePadFuncParams("pad_right", width, padding);
1025
+ return subject && subject.padEnd(width, padding) || "";
1026
+ };
1027
+ var replace = (subject, string, by, count) => {
1028
+ if (count === 0) {
1029
+ return subject;
1030
+ }
1031
+ if (!count) {
1032
+ return subject.split(string).join(by);
1033
+ }
1034
+ ensurePositiveInteger(count);
1035
+ while (count-- > 0 && subject.includes(string)) {
1036
+ subject = subject.replace(string, by);
1037
+ }
1038
+ return subject;
1039
+ };
1040
+ var split = (subject, search2, count) => {
1041
+ if (subject.length == 0 && search2.length === 0) {
1042
+ return [];
1043
+ }
1044
+ if (count === null || count === void 0) {
1045
+ return subject.split(search2);
1046
+ }
1047
+ ensurePositiveInteger(count);
1048
+ if (count === 0) {
1049
+ return [subject];
1050
+ }
1051
+ const split2 = subject.split(search2);
1052
+ return [...split2.slice(0, count), split2.slice(count).join(search2)];
1053
+ };
1054
+ var trim = (subject, chars) => {
1055
+ return trimLeft(trimRight(subject, chars), chars);
1056
+ };
1057
+ var trimLeft = (subject, chars) => {
1058
+ return trimImpl(subject, (list) => new RegExp(`^[${list}]*(.*?)`), chars);
1059
+ };
1060
+ var trimRight = (subject, chars) => {
1061
+ return trimImpl(subject, (list) => new RegExp(`(.*?)[${list}]*$`), chars);
1062
+ };
1063
+ var trimImpl = (subject, regExper, chars) => {
1064
+ const pattern = chars ? chars.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&") : "\\s\x85";
1065
+ return subject.replace(regExper(pattern), "$1");
1066
+ };
1067
+ var upper = (subject) => subject.toUpperCase();
1068
+
969
1069
  // src/utils/text.ts
970
1070
  var Text = class _Text {
971
1071
  _text;
@@ -976,7 +1076,11 @@ var Text = class _Text {
976
1076
  return this._text;
977
1077
  }
978
1078
  get length() {
979
- return this.codePoints.length;
1079
+ let count = 0;
1080
+ for (const _ of this._text) {
1081
+ count += 1;
1082
+ }
1083
+ return count;
980
1084
  }
981
1085
  compareTo(other) {
982
1086
  return _Text.compare(this, new _Text(other));
@@ -1011,6 +1115,12 @@ var Text = class _Text {
1011
1115
  var createMathFunction = (mathFn) => ([value]) => mathFn(value);
1012
1116
  var createStringFunction = (stringFn) => ([subject]) => stringFn(subject);
1013
1117
  var createObjectFunction = (objFn) => ([obj]) => objFn(obj);
1118
+ var ARRAY_SUBTYPES = {
1119
+ [8 /* TYPE_ARRAY_NUMBER */]: 0 /* TYPE_NUMBER */,
1120
+ [10 /* TYPE_ARRAY_OBJECT */]: 4 /* TYPE_OBJECT */,
1121
+ [9 /* TYPE_ARRAY_STRING */]: 2 /* TYPE_STRING */,
1122
+ [11 /* TYPE_ARRAY_ARRAY */]: 3 /* TYPE_ARRAY */
1123
+ };
1014
1124
  var Runtime = class {
1015
1125
  _interpreter;
1016
1126
  _functionTable;
@@ -1328,34 +1438,18 @@ var Runtime = class {
1328
1438
  if (expected === 1 /* TYPE_ANY */) {
1329
1439
  return true;
1330
1440
  }
1331
- 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 */) {
1332
- if (expected === 3 /* TYPE_ARRAY */) {
1333
- return actual === 3 /* TYPE_ARRAY */;
1334
- }
1335
- if (actual === 3 /* TYPE_ARRAY */) {
1336
- let subtype;
1337
- if (expected === 8 /* TYPE_ARRAY_NUMBER */) {
1338
- subtype = 0 /* TYPE_NUMBER */;
1339
- } else if (expected === 10 /* TYPE_ARRAY_OBJECT */) {
1340
- subtype = 4 /* TYPE_OBJECT */;
1341
- } else if (expected === 9 /* TYPE_ARRAY_STRING */) {
1342
- subtype = 2 /* TYPE_STRING */;
1343
- } else if (expected === 11 /* TYPE_ARRAY_ARRAY */) {
1344
- subtype = 3 /* TYPE_ARRAY */;
1345
- }
1346
- const array = argValue;
1347
- for (let i = 0; i < array.length; i += 1) {
1348
- const typeName = this.getTypeName(array[i]);
1349
- if (typeName !== void 0 && subtype !== void 0 && !this.typeMatches(typeName, subtype, array[i])) {
1350
- return false;
1351
- }
1352
- }
1353
- return true;
1441
+ const subtype = ARRAY_SUBTYPES[expected];
1442
+ if (subtype !== void 0) {
1443
+ if (actual !== 3 /* TYPE_ARRAY */) {
1444
+ return false;
1354
1445
  }
1355
- } else {
1356
- return actual === expected;
1446
+ const array = argValue;
1447
+ return array.every((item) => {
1448
+ const typeName = this.getTypeName(item);
1449
+ return typeName === void 0 || this.typeMatches(typeName, subtype, item);
1450
+ });
1357
1451
  }
1358
- return false;
1452
+ return actual === expected;
1359
1453
  }
1360
1454
  getTypeName(obj) {
1361
1455
  if (obj === null) {
@@ -1419,9 +1513,8 @@ var Runtime = class {
1419
1513
  }
1420
1514
  return null;
1421
1515
  };
1422
- functionEndsWith = (resolvedArgs) => {
1423
- const [searchStr, suffix] = resolvedArgs;
1424
- return searchStr.includes(suffix, searchStr.length - suffix.length);
1516
+ functionEndsWith = ([searchStr, suffix]) => {
1517
+ return searchStr.endsWith(suffix);
1425
1518
  };
1426
1519
  functionFindFirst = this.createFindFunction(findFirst);
1427
1520
  functionFindLast = this.createFindFunction(findLast);
@@ -1435,21 +1528,24 @@ var Runtime = class {
1435
1528
  };
1436
1529
  }
1437
1530
  functionFromItems = ([array]) => {
1438
- array.map((pair) => {
1439
- if (pair.length != 2 || typeof pair[0] !== "string") {
1531
+ for (const pair of array) {
1532
+ if (pair.length !== 2 || typeof pair[0] !== "string") {
1440
1533
  throw new Error("invalid value, each array must contain two elements, a pair of string and value");
1441
1534
  }
1442
- });
1535
+ }
1443
1536
  return Object.fromEntries(array);
1444
1537
  };
1445
1538
  functionGroupBy = ([array, exprefNode]) => {
1446
1539
  const keyFunction = this.createKeyFunction(exprefNode, [2 /* TYPE_STRING */]);
1447
- return array.reduce((acc, cur) => {
1448
- const k = keyFunction(cur ?? {});
1449
- const target = acc[k] = acc[k] || [];
1450
- target.push(cur);
1451
- return acc;
1452
- }, {});
1540
+ const groups = {};
1541
+ for (const item of array) {
1542
+ const key = keyFunction(item);
1543
+ if (!groups[key]) {
1544
+ groups[key] = [];
1545
+ }
1546
+ groups[key].push(item);
1547
+ }
1548
+ return groups;
1453
1549
  };
1454
1550
  functionItems = ([inputValue]) => {
1455
1551
  return Object.entries(inputValue);
@@ -1512,12 +1608,7 @@ var Runtime = class {
1512
1608
  return maxRecord || null;
1513
1609
  };
1514
1610
  functionMerge = (resolvedArgs) => {
1515
- let merged = {};
1516
- for (let i = 0; i < resolvedArgs.length; i += 1) {
1517
- const current = resolvedArgs[i];
1518
- merged = Object.assign(merged, current);
1519
- }
1520
- return merged;
1611
+ return Object.assign({}, ...resolvedArgs);
1521
1612
  };
1522
1613
  functionMin = ([inputValue]) => {
1523
1614
  if (!inputValue.length) {
@@ -1553,12 +1644,7 @@ var Runtime = class {
1553
1644
  return minRecord || null;
1554
1645
  };
1555
1646
  functionNotNull = (resolvedArgs) => {
1556
- for (let i = 0; i < resolvedArgs.length; i += 1) {
1557
- if (this.getTypeName(resolvedArgs[i]) !== 7 /* TYPE_NULL */) {
1558
- return resolvedArgs[i];
1559
- }
1560
- }
1561
- return null;
1647
+ return resolvedArgs.find((arg) => arg !== null) ?? null;
1562
1648
  };
1563
1649
  functionPadLeft = this.createPadFunction(padLeft);
1564
1650
  functionPadRight = this.createPadFunction(padRight);
@@ -1586,12 +1672,12 @@ var Runtime = class {
1586
1672
  if (typeName === 2 /* TYPE_STRING */) {
1587
1673
  return new Text(inputValue).reverse();
1588
1674
  }
1589
- const reversedArray = inputValue.slice(0);
1675
+ const reversedArray = [...inputValue];
1590
1676
  reversedArray.reverse();
1591
1677
  return reversedArray;
1592
1678
  };
1593
1679
  functionSort = ([inputValue]) => {
1594
- if (inputValue.length == 0) {
1680
+ if (inputValue.length <= 1) {
1595
1681
  return inputValue;
1596
1682
  }
1597
1683
  if (typeof inputValue[0] === "string") {
@@ -1600,8 +1686,8 @@ var Runtime = class {
1600
1686
  return [...inputValue].sort();
1601
1687
  };
1602
1688
  functionSortBy = (resolvedArgs) => {
1603
- const sortedArray = resolvedArgs[0].slice(0);
1604
- if (sortedArray.length === 0) {
1689
+ const sortedArray = [...resolvedArgs[0]];
1690
+ if (sortedArray.length <= 1) {
1605
1691
  return sortedArray;
1606
1692
  }
1607
1693
  const interpreter = this._interpreter;
@@ -1636,10 +1722,7 @@ var Runtime = class {
1636
1722
  return inputValue.reduce((x, y) => x + y, 0);
1637
1723
  };
1638
1724
  functionToArray = ([inputValue]) => {
1639
- if (this.getTypeName(inputValue) === 3 /* TYPE_ARRAY */) {
1640
- return inputValue;
1641
- }
1642
- return [inputValue];
1725
+ return Array.isArray(inputValue) ? inputValue : [inputValue];
1643
1726
  };
1644
1727
  functionToNumber = ([inputValue]) => {
1645
1728
  const typeName = this.getTypeName(inputValue);
@@ -1656,10 +1739,7 @@ var Runtime = class {
1656
1739
  return null;
1657
1740
  };
1658
1741
  functionToString = ([inputValue]) => {
1659
- if (this.getTypeName(inputValue) === 2 /* TYPE_STRING */) {
1660
- return inputValue;
1661
- }
1662
- return JSON.stringify(inputValue);
1742
+ return typeof inputValue === "string" ? inputValue : JSON.stringify(inputValue);
1663
1743
  };
1664
1744
  functionTrim = this.createTrimFunction(trim);
1665
1745
  functionTrimLeft = this.createTrimFunction(trimLeft);
@@ -1672,27 +1752,16 @@ var Runtime = class {
1672
1752
  };
1673
1753
  }
1674
1754
  functionType = ([inputValue]) => {
1675
- switch (this.getTypeName(inputValue)) {
1676
- case 0 /* TYPE_NUMBER */:
1677
- return "number";
1678
- case 2 /* TYPE_STRING */:
1679
- return "string";
1680
- case 3 /* TYPE_ARRAY */:
1681
- return "array";
1682
- case 4 /* TYPE_OBJECT */:
1683
- return "object";
1684
- case 5 /* TYPE_BOOLEAN */:
1685
- return "boolean";
1686
- case 7 /* TYPE_NULL */:
1687
- return "null";
1688
- default:
1689
- throw new Error("invalid-type");
1755
+ const type = this.getTypeName(inputValue);
1756
+ const name = type !== void 0 ? this.TYPE_NAME_TABLE[type] : void 0;
1757
+ if (!name) {
1758
+ throw new Error("invalid-type");
1690
1759
  }
1760
+ return name;
1691
1761
  };
1692
1762
  functionZip = (array) => {
1693
1763
  const length = Math.min(...array.map((arr) => arr.length));
1694
- const result = Array(length).fill(null).map((_, index) => array.map((arr) => arr[index]));
1695
- return result;
1764
+ return Array.from({ length }, (_, index) => array.map((arr) => arr[index]));
1696
1765
  };
1697
1766
  };
1698
1767
 
@@ -1726,23 +1795,108 @@ var TreeInterpreter = class _TreeInterpreter {
1726
1795
  runtime;
1727
1796
  _rootValue = null;
1728
1797
  _scope;
1729
- constructor() {
1798
+ _options;
1799
+ _depth = 0;
1800
+ _deadline = 0;
1801
+ constructor(options) {
1730
1802
  this.runtime = new Runtime(this);
1731
1803
  this._scope = new ScopeChain();
1804
+ if (options) {
1805
+ this._options = options;
1806
+ this._deadline = options.timeoutMs !== void 0 ? Date.now() + options.timeoutMs : 0;
1807
+ }
1732
1808
  }
1733
1809
  withScope(scope) {
1734
- const interpreter = new _TreeInterpreter();
1810
+ const interpreter = new _TreeInterpreter(this._options);
1735
1811
  interpreter.runtime._functionTable = this.runtime._functionTable;
1736
1812
  interpreter._rootValue = this._rootValue;
1737
1813
  interpreter._scope = this._scope.withScope(scope);
1814
+ interpreter._depth = this._depth;
1815
+ interpreter._deadline = this._deadline;
1738
1816
  return interpreter;
1739
1817
  }
1740
- search(node, value) {
1818
+ search(node, value, options) {
1819
+ if (options?.maxNodes !== void 0 && countNodes(node) > options.maxNodes) {
1820
+ throw new Error(`Expression exceeds maximum allowed node count of ${options.maxNodes}`);
1821
+ }
1741
1822
  this._rootValue = value;
1742
1823
  this._scope = emptyScopeChain;
1743
- return this.visit(node, value);
1824
+ this._options = options;
1825
+ this._depth = 0;
1826
+ this._deadline = options?.timeoutMs !== void 0 ? Date.now() + options.timeoutMs : 0;
1827
+ const result = this.visit(node, value);
1828
+ this.checkOutputSize(result);
1829
+ return result;
1830
+ }
1831
+ checkOutputSize(val) {
1832
+ const max = this._options?.maxOutputSize;
1833
+ if (max === void 0 || val == null) {
1834
+ return;
1835
+ }
1836
+ const size = Array.isArray(val) || typeof val === "string" ? val.length : typeof val === "object" ? Object.keys(val).length : 0;
1837
+ if (size > max) {
1838
+ throw new Error(`Output size exceeds maximum allowed size of ${max}`);
1839
+ }
1840
+ }
1841
+ collect(target, item) {
1842
+ target.push(item);
1843
+ if (this._options?.maxOutputSize !== void 0 && target.length > this._options.maxOutputSize) {
1844
+ throw new Error(`Output size exceeds maximum allowed size of ${this._options.maxOutputSize}`);
1845
+ }
1846
+ }
1847
+ evaluateProjectionItems(items, right) {
1848
+ const collected = [];
1849
+ if (right.type === "Field") {
1850
+ const key = right.name;
1851
+ for (let i = 0; i < items.length; i++) {
1852
+ if (this._deadline > 0 && Date.now() >= this._deadline) {
1853
+ throw new Error(`Query execution timed out after ${this._options?.timeoutMs}ms`);
1854
+ }
1855
+ const elem = items[i];
1856
+ if (!elem || typeof elem !== "object" || Array.isArray(elem)) {
1857
+ continue;
1858
+ }
1859
+ const val = elem[key];
1860
+ if (val !== void 0 && val !== null) {
1861
+ this.collect(collected, val);
1862
+ }
1863
+ }
1864
+ return collected;
1865
+ }
1866
+ if (right.type === "Identity") {
1867
+ for (let i = 0; i < items.length; i++) {
1868
+ const elem = items[i];
1869
+ if (elem !== null) {
1870
+ this.collect(collected, elem);
1871
+ }
1872
+ }
1873
+ return collected;
1874
+ }
1875
+ for (const elem of items) {
1876
+ const current = this.visit(right, elem);
1877
+ if (current !== null) {
1878
+ this.collect(collected, current);
1879
+ }
1880
+ }
1881
+ return collected;
1744
1882
  }
1745
1883
  visit(node, value) {
1884
+ if (this._options) {
1885
+ if (this._options.maxDepth !== void 0 && this._depth >= this._options.maxDepth) {
1886
+ throw new Error(`Evaluation exceeds maximum allowed depth of ${this._options.maxDepth}`);
1887
+ }
1888
+ if (this._deadline > 0 && Date.now() >= this._deadline) {
1889
+ throw new Error(`Query execution timed out after ${this._options.timeoutMs}ms`);
1890
+ }
1891
+ }
1892
+ this._depth += 1;
1893
+ try {
1894
+ return this.evaluateNode(node, value);
1895
+ } finally {
1896
+ this._depth -= 1;
1897
+ }
1898
+ }
1899
+ evaluateNode(node, value) {
1746
1900
  switch (node.type) {
1747
1901
  case "Ternary": {
1748
1902
  const condition = this.visit(node.condition, value);
@@ -1758,16 +1912,11 @@ var TreeInterpreter = class _TreeInterpreter {
1758
1912
  }
1759
1913
  return value[identifier] ?? null;
1760
1914
  case "LetExpression": {
1761
- const { bindings, expression: expression2 } = node;
1762
- let scope = {};
1763
- bindings.forEach((binding) => {
1764
- const reference = this.visit(binding, value);
1765
- scope = {
1766
- ...scope,
1767
- ...reference
1768
- };
1769
- });
1770
- return this.withScope(scope).visit(expression2, value);
1915
+ const scope = {};
1916
+ for (const binding of node.bindings) {
1917
+ Object.assign(scope, this.visit(binding, value));
1918
+ }
1919
+ return this.withScope(scope).visit(node.expression, value);
1771
1920
  }
1772
1921
  case "Binding": {
1773
1922
  const { variable, reference } = node;
@@ -1799,51 +1948,27 @@ var TreeInterpreter = class _TreeInterpreter {
1799
1948
  return null;
1800
1949
  }
1801
1950
  const { start, stop, step } = this.computeSliceParams(value.length, node);
1802
- if (typeof value === "string") {
1803
- const chars = [...value];
1804
- const sliced = this.slice(chars, start, stop, step);
1805
- return sliced.join("");
1806
- } else {
1807
- return this.slice(value, start, stop, step);
1808
- }
1951
+ const target = typeof value === "string" ? [...value] : value;
1952
+ const sliced = this.slice(target, start, stop, step);
1953
+ const res = typeof value === "string" ? sliced.join("") : sliced;
1954
+ this.checkOutputSize(res);
1955
+ return res;
1809
1956
  }
1810
1957
  case "Projection": {
1811
1958
  const { left, right } = node;
1812
- let allowString = false;
1813
- if (left.type === "IndexExpression" && left.right.type === "Slice") {
1814
- allowString = true;
1815
- }
1959
+ const allowString = left.type === "IndexExpression" && left.right.type === "Slice";
1816
1960
  const base = this.visit(left, value);
1817
1961
  if (allowString && typeof base === "string") {
1818
1962
  return this.visit(right, base);
1819
1963
  }
1820
- if (!Array.isArray(base)) {
1821
- return null;
1822
- }
1823
- const collected = [];
1824
- for (const elem of base) {
1825
- const current = this.visit(right, elem);
1826
- if (current !== null) {
1827
- collected.push(current);
1828
- }
1829
- }
1830
- return collected;
1964
+ return Array.isArray(base) ? this.evaluateProjectionItems(base, right) : null;
1831
1965
  }
1832
1966
  case "ValueProjection": {
1833
- const { left, right } = node;
1834
- const base = this.visit(left, value);
1967
+ const base = this.visit(node.left, value);
1835
1968
  if (base === null || typeof base !== "object" || Array.isArray(base)) {
1836
1969
  return null;
1837
1970
  }
1838
- const collected = [];
1839
- const values = Object.values(base);
1840
- for (const elem of values) {
1841
- const current = this.visit(right, elem);
1842
- if (current !== null) {
1843
- collected.push(current);
1844
- }
1845
- }
1846
- return collected;
1971
+ return this.evaluateProjectionItems(Object.values(base), node.right);
1847
1972
  }
1848
1973
  case "FilterProjection": {
1849
1974
  const { left, right, condition } = node;
@@ -1852,14 +1977,42 @@ var TreeInterpreter = class _TreeInterpreter {
1852
1977
  return null;
1853
1978
  }
1854
1979
  const results = [];
1980
+ if (right.type === "Field") {
1981
+ const key = right.name;
1982
+ for (let i = 0; i < base.length; i++) {
1983
+ const elem = base[i];
1984
+ if (isFalse(this.visit(condition, elem))) {
1985
+ continue;
1986
+ }
1987
+ if (!elem || typeof elem !== "object" || Array.isArray(elem)) {
1988
+ continue;
1989
+ }
1990
+ const val = elem[key];
1991
+ if (val !== void 0 && val !== null) {
1992
+ this.collect(results, val);
1993
+ }
1994
+ }
1995
+ return results;
1996
+ }
1997
+ if (right.type === "Identity") {
1998
+ for (let i = 0; i < base.length; i++) {
1999
+ const elem = base[i];
2000
+ if (isFalse(this.visit(condition, elem))) {
2001
+ continue;
2002
+ }
2003
+ if (elem !== null) {
2004
+ this.collect(results, elem);
2005
+ }
2006
+ }
2007
+ return results;
2008
+ }
1855
2009
  for (const elem of base) {
1856
- const matched = this.visit(condition, elem);
1857
- if (isFalse(matched)) {
2010
+ if (isFalse(this.visit(condition, elem))) {
1858
2011
  continue;
1859
2012
  }
1860
2013
  const result = this.visit(right, elem);
1861
2014
  if (result !== null) {
1862
- results.push(result);
2015
+ this.collect(results, result);
1863
2016
  }
1864
2017
  }
1865
2018
  return results;
@@ -1923,7 +2076,9 @@ var TreeInterpreter = class _TreeInterpreter {
1923
2076
  }
1924
2077
  case "Flatten": {
1925
2078
  const original = this.visit(node.child, value);
1926
- return Array.isArray(original) ? original.flat() : null;
2079
+ const res = Array.isArray(original) ? original.flat() : null;
2080
+ this.checkOutputSize(res);
2081
+ return res;
1927
2082
  }
1928
2083
  case "Root":
1929
2084
  return this._rootValue;
@@ -1932,6 +2087,7 @@ var TreeInterpreter = class _TreeInterpreter {
1932
2087
  for (const child of node.children) {
1933
2088
  collected.push(this.visit(child, value));
1934
2089
  }
2090
+ this.checkOutputSize(collected);
1935
2091
  return collected;
1936
2092
  }
1937
2093
  case "MultiSelectHash": {
@@ -1939,6 +2095,7 @@ var TreeInterpreter = class _TreeInterpreter {
1939
2095
  for (const child of node.children) {
1940
2096
  collected[child.name] = this.visit(child.value, value);
1941
2097
  }
2098
+ this.checkOutputSize(collected);
1942
2099
  return collected;
1943
2100
  }
1944
2101
  case "OrExpression": {
@@ -1962,11 +2119,19 @@ var TreeInterpreter = class _TreeInterpreter {
1962
2119
  case "Pipe":
1963
2120
  return this.visit(node.right, this.visit(node.left, value));
1964
2121
  case "Function": {
2122
+ if (this._options?.allowedFunctions && !this._options.allowedFunctions.includes(node.name)) {
2123
+ throw new Error(`Function '${node.name}' is not allowed`);
2124
+ }
2125
+ if (this._options?.disallowedFunctions && this._options.disallowedFunctions.includes(node.name)) {
2126
+ throw new Error(`Function '${node.name}' is disallowed`);
2127
+ }
1965
2128
  const args2 = [];
1966
2129
  for (const child of node.children) {
1967
2130
  args2.push(this.visit(child, value));
1968
2131
  }
1969
- return this.runtime.callFunction(node.name, args2);
2132
+ const res = this.runtime.callFunction(node.name, args2);
2133
+ this.checkOutputSize(res);
2134
+ return res;
1970
2135
  }
1971
2136
  case "ExpressionReference":
1972
2137
  return {
@@ -2004,14 +2169,19 @@ var TreeInterpreter = class _TreeInterpreter {
2004
2169
  return nextActualValue;
2005
2170
  }
2006
2171
  slice(collection, start, end, step) {
2007
- const result = [];
2172
+ if (step === 1) {
2173
+ return collection.slice(start, end);
2174
+ }
2175
+ const len = Math.ceil(Math.abs(start - end) / Math.abs(step));
2176
+ const result = new Array(len);
2177
+ let idx = 0;
2008
2178
  if (step > 0) {
2009
2179
  for (let i = start; i < end; i += step) {
2010
- result.push(collection[i]);
2180
+ result[idx++] = collection[i];
2011
2181
  }
2012
2182
  } else {
2013
2183
  for (let i = start; i > end; i += step) {
2014
- result.push(collection[i]);
2184
+ result[idx++] = collection[i];
2015
2185
  }
2016
2186
  }
2017
2187
  return result;
@@ -2020,10 +2190,397 @@ var TreeInterpreter = class _TreeInterpreter {
2020
2190
  var TreeInterpreterInstance = new TreeInterpreter();
2021
2191
  var TreeInterpreter_default = TreeInterpreterInstance;
2022
2192
 
2193
+ // src/Stream.ts
2194
+ async function* toAsyncIterable(source) {
2195
+ if (source == null) {
2196
+ return;
2197
+ }
2198
+ if (typeof source !== "object" && typeof source !== "function") {
2199
+ throw new TypeError("Invalid stream source: expected AsyncIterable, Iterable, or ReadableStream");
2200
+ }
2201
+ if (Symbol.asyncIterator in source) {
2202
+ for await (const chunk of source) {
2203
+ yield chunk;
2204
+ }
2205
+ return;
2206
+ }
2207
+ if (typeof source.getReader === "function") {
2208
+ const reader = source.getReader();
2209
+ try {
2210
+ while (true) {
2211
+ const { done, value } = await reader.read();
2212
+ if (done) {
2213
+ break;
2214
+ }
2215
+ yield value;
2216
+ }
2217
+ } finally {
2218
+ reader.releaseLock();
2219
+ }
2220
+ return;
2221
+ }
2222
+ if (Symbol.iterator in source) {
2223
+ for (const chunk of source) {
2224
+ yield chunk;
2225
+ }
2226
+ return;
2227
+ }
2228
+ throw new TypeError("Invalid stream source: expected AsyncIterable, Iterable, or ReadableStream");
2229
+ }
2230
+ function parseItem(str, parseJson) {
2231
+ if (parseJson === true) {
2232
+ return JSON.parse(str);
2233
+ }
2234
+ if (parseJson === "auto") {
2235
+ try {
2236
+ return JSON.parse(str);
2237
+ } catch {
2238
+ return str;
2239
+ }
2240
+ }
2241
+ return str;
2242
+ }
2243
+ async function* normalizeSource(source, options) {
2244
+ const parseJson = options?.parseJson ?? "auto";
2245
+ const flatten = options?.flattenChunks ?? true;
2246
+ let buffer = "";
2247
+ const textDecoder = typeof TextDecoder !== "undefined" ? new TextDecoder() : null;
2248
+ for await (const chunk of toAsyncIterable(source)) {
2249
+ if (chunk instanceof Uint8Array && textDecoder) {
2250
+ buffer += textDecoder.decode(chunk, { stream: true });
2251
+ if (buffer.includes("\n")) {
2252
+ const lines = buffer.split("\n");
2253
+ buffer = lines.pop() ?? "";
2254
+ for (const line of lines) {
2255
+ const trimmed = line.trim();
2256
+ if (trimmed) {
2257
+ yield parseItem(trimmed, parseJson);
2258
+ }
2259
+ }
2260
+ }
2261
+ } else if (typeof chunk === "string") {
2262
+ if (parseJson === false) {
2263
+ yield chunk;
2264
+ } else {
2265
+ buffer += chunk;
2266
+ if (buffer.includes("\n")) {
2267
+ const lines = buffer.split("\n");
2268
+ buffer = lines.pop() ?? "";
2269
+ for (const line of lines) {
2270
+ const trimmed = line.trim();
2271
+ if (trimmed) {
2272
+ yield parseItem(trimmed, parseJson);
2273
+ }
2274
+ }
2275
+ }
2276
+ }
2277
+ } else if (flatten && Array.isArray(chunk)) {
2278
+ if (buffer.trim()) {
2279
+ yield parseItem(buffer.trim(), parseJson);
2280
+ buffer = "";
2281
+ }
2282
+ for (let i = 0; i < chunk.length; i++) {
2283
+ yield chunk[i];
2284
+ }
2285
+ } else {
2286
+ if (buffer.trim()) {
2287
+ yield parseItem(buffer.trim(), parseJson);
2288
+ buffer = "";
2289
+ }
2290
+ yield chunk;
2291
+ }
2292
+ }
2293
+ if (textDecoder && buffer) {
2294
+ buffer += textDecoder.decode();
2295
+ }
2296
+ if (buffer.trim()) {
2297
+ yield parseItem(buffer.trim(), parseJson);
2298
+ }
2299
+ }
2300
+ function isStreamableNode(node) {
2301
+ switch (node.type) {
2302
+ case "Projection":
2303
+ if (node.left.type === "Identity" || node.left.type === "Current") {
2304
+ return true;
2305
+ }
2306
+ if (node.left.type === "IndexExpression" && node.left.right.type === "Slice") {
2307
+ const slice = node.left.right;
2308
+ return (slice.start === null || slice.start >= 0) && (slice.stop === null || slice.stop >= 0) && (slice.step === null || slice.step > 0);
2309
+ }
2310
+ return false;
2311
+ case "FilterProjection":
2312
+ return node.left.type === "Identity" || node.left.type === "Current";
2313
+ case "IndexExpression":
2314
+ if (node.right.type === "Slice" && (node.left.type === "Identity" || node.left.type === "Current")) {
2315
+ const slice = node.right;
2316
+ return (slice.start === null || slice.start >= 0) && (slice.stop === null || slice.stop >= 0) && (slice.step === null || slice.step > 0);
2317
+ }
2318
+ return true;
2319
+ case "Field":
2320
+ case "Identity":
2321
+ case "Current":
2322
+ case "Subexpression":
2323
+ case "MultiSelectHash":
2324
+ case "MultiSelectList":
2325
+ case "Ternary":
2326
+ case "Comparator":
2327
+ case "Arithmetic":
2328
+ case "NotExpression":
2329
+ return true;
2330
+ case "Pipe":
2331
+ return isStreamableNode(node.left) && isStreamableNode(node.right);
2332
+ default:
2333
+ return false;
2334
+ }
2335
+ }
2336
+ async function* evaluateStreamNode(source, node, interpreter, options) {
2337
+ const deadline = options?.timeoutMs !== void 0 ? Date.now() + options.timeoutMs : 0;
2338
+ function checkDeadline() {
2339
+ if (deadline > 0 && Date.now() >= deadline) {
2340
+ throw new Error(`Query execution timed out after ${options?.timeoutMs}ms`);
2341
+ }
2342
+ }
2343
+ switch (node.type) {
2344
+ case "Projection": {
2345
+ const { left, right } = node;
2346
+ let streamSource = source;
2347
+ if (left.type === "IndexExpression" && left.right.type === "Slice") {
2348
+ streamSource = evaluateStreamNode(source, left, interpreter, options);
2349
+ }
2350
+ if (right.type === "Identity" || right.type === "Current") {
2351
+ for await (const item of streamSource) {
2352
+ checkDeadline();
2353
+ if (item !== null && item !== void 0) {
2354
+ yield item;
2355
+ }
2356
+ }
2357
+ return;
2358
+ }
2359
+ if (right.type === "Field") {
2360
+ const key = right.name;
2361
+ for await (const item of streamSource) {
2362
+ checkDeadline();
2363
+ if (item && typeof item === "object" && !Array.isArray(item)) {
2364
+ const val = item[key];
2365
+ if (val !== void 0 && val !== null) {
2366
+ yield val;
2367
+ }
2368
+ }
2369
+ }
2370
+ return;
2371
+ }
2372
+ for await (const item of streamSource) {
2373
+ checkDeadline();
2374
+ const res = interpreter.visit(right, item);
2375
+ if (res !== null && res !== void 0) {
2376
+ yield res;
2377
+ }
2378
+ }
2379
+ return;
2380
+ }
2381
+ case "IndexExpression": {
2382
+ if (node.right.type === "Slice" && (node.left.type === "Identity" || node.left.type === "Current")) {
2383
+ const slice = node.right;
2384
+ const start = slice.start ?? 0;
2385
+ const stop = slice.stop ?? Infinity;
2386
+ const step = slice.step ?? 1;
2387
+ if (start >= 0 && stop >= 0 && step > 0) {
2388
+ let index = 0;
2389
+ for await (const item of source) {
2390
+ checkDeadline();
2391
+ if (index >= stop) {
2392
+ break;
2393
+ }
2394
+ if (index >= start && (index - start) % step === 0) {
2395
+ yield item;
2396
+ }
2397
+ index++;
2398
+ if (index >= stop) {
2399
+ break;
2400
+ }
2401
+ }
2402
+ return;
2403
+ }
2404
+ const collected = [];
2405
+ for await (const item of source) {
2406
+ checkDeadline();
2407
+ collected.push(item);
2408
+ if (options?.maxOutputSize !== void 0 && collected.length > options.maxOutputSize) {
2409
+ throw new Error(`Output size exceeds maximum allowed size of ${options.maxOutputSize}`);
2410
+ }
2411
+ }
2412
+ const result = interpreter.search(node, collected, options);
2413
+ if (Array.isArray(result)) {
2414
+ for (const item of result) {
2415
+ yield item;
2416
+ }
2417
+ }
2418
+ return;
2419
+ }
2420
+ for await (const item of source) {
2421
+ checkDeadline();
2422
+ const res = interpreter.visit(node, item);
2423
+ if (res !== null && res !== void 0) {
2424
+ yield res;
2425
+ }
2426
+ }
2427
+ return;
2428
+ }
2429
+ case "FilterProjection": {
2430
+ const { condition, right } = node;
2431
+ if (right.type === "Identity" || right.type === "Current") {
2432
+ for await (const item of source) {
2433
+ checkDeadline();
2434
+ if (!isFalse(interpreter.visit(condition, item))) {
2435
+ yield item;
2436
+ }
2437
+ }
2438
+ return;
2439
+ }
2440
+ if (right.type === "Field") {
2441
+ const key = right.name;
2442
+ for await (const item of source) {
2443
+ checkDeadline();
2444
+ if (!isFalse(interpreter.visit(condition, item))) {
2445
+ if (item && typeof item === "object" && !Array.isArray(item)) {
2446
+ const val = item[key];
2447
+ if (val !== void 0 && val !== null) {
2448
+ yield val;
2449
+ }
2450
+ }
2451
+ }
2452
+ }
2453
+ return;
2454
+ }
2455
+ for await (const item of source) {
2456
+ checkDeadline();
2457
+ if (!isFalse(interpreter.visit(condition, item))) {
2458
+ const res = interpreter.visit(right, item);
2459
+ if (res !== null && res !== void 0) {
2460
+ yield res;
2461
+ }
2462
+ }
2463
+ }
2464
+ return;
2465
+ }
2466
+ case "Pipe": {
2467
+ const leftStream = evaluateStreamNode(source, node.left, interpreter, options);
2468
+ if (isStreamableNode(node.right)) {
2469
+ for await (const res of evaluateStreamNode(leftStream, node.right, interpreter, options)) {
2470
+ yield res;
2471
+ }
2472
+ } else {
2473
+ const collected = [];
2474
+ for await (const item of leftStream) {
2475
+ checkDeadline();
2476
+ collected.push(item);
2477
+ if (options?.maxOutputSize !== void 0 && collected.length > options.maxOutputSize) {
2478
+ throw new Error(`Output size exceeds maximum allowed size of ${options.maxOutputSize}`);
2479
+ }
2480
+ }
2481
+ const result = interpreter.search(node.right, collected, options);
2482
+ if (result !== null && result !== void 0) {
2483
+ yield result;
2484
+ }
2485
+ }
2486
+ return;
2487
+ }
2488
+ case "Identity":
2489
+ case "Current": {
2490
+ for await (const item of source) {
2491
+ checkDeadline();
2492
+ yield item;
2493
+ }
2494
+ return;
2495
+ }
2496
+ case "Field": {
2497
+ const key = node.name;
2498
+ for await (const item of source) {
2499
+ checkDeadline();
2500
+ if (item && typeof item === "object" && !Array.isArray(item)) {
2501
+ const val = item[key];
2502
+ if (val !== void 0 && val !== null) {
2503
+ yield val;
2504
+ }
2505
+ }
2506
+ }
2507
+ return;
2508
+ }
2509
+ default: {
2510
+ if (isStreamableNode(node)) {
2511
+ for await (const item of source) {
2512
+ checkDeadline();
2513
+ const res = interpreter.visit(node, item);
2514
+ if (res !== null && res !== void 0) {
2515
+ yield res;
2516
+ }
2517
+ }
2518
+ return;
2519
+ }
2520
+ const collected = [];
2521
+ for await (const item of source) {
2522
+ checkDeadline();
2523
+ collected.push(item);
2524
+ if (options?.maxOutputSize !== void 0 && collected.length > options.maxOutputSize) {
2525
+ throw new Error(`Output size exceeds maximum allowed size of ${options.maxOutputSize}`);
2526
+ }
2527
+ }
2528
+ const result = interpreter.search(node, collected, options);
2529
+ if (result !== null && result !== void 0) {
2530
+ yield result;
2531
+ }
2532
+ return;
2533
+ }
2534
+ }
2535
+ }
2536
+ function isExpressionNode(val) {
2537
+ return typeof val === "object" && val !== null && "type" in val && typeof val.type === "string" && !(Symbol.iterator in val) && !(Symbol.asyncIterator in val);
2538
+ }
2539
+ async function* searchStream(sourceOrExpression, expressionOrSource, options) {
2540
+ let expression2;
2541
+ let source;
2542
+ if (typeof sourceOrExpression === "string" || isExpressionNode(sourceOrExpression)) {
2543
+ expression2 = sourceOrExpression;
2544
+ source = expressionOrSource;
2545
+ } else {
2546
+ source = sourceOrExpression;
2547
+ expression2 = expressionOrSource;
2548
+ }
2549
+ if (typeof expression2 !== "string" && !isExpressionNode(expression2)) {
2550
+ throw new TypeError("Expression must be a string or AST ExpressionNode");
2551
+ }
2552
+ const ast = typeof expression2 === "string" ? Parser_default.parse(expression2, options) : expression2;
2553
+ if (options) {
2554
+ const fnError = findDisallowedFunction(ast, options);
2555
+ if (fnError) {
2556
+ throw new Error(fnError);
2557
+ }
2558
+ }
2559
+ const interpreter = new TreeInterpreter(options);
2560
+ interpreter.runtime._functionTable = TreeInterpreterInstance.runtime._functionTable;
2561
+ const items = normalizeSource(source, options);
2562
+ const results = evaluateStreamNode(items, ast, interpreter, options);
2563
+ const limit = options?.limit;
2564
+ const maxOutputSize = options?.maxOutputSize;
2565
+ let count = 0;
2566
+ for await (const result of results) {
2567
+ yield result;
2568
+ count++;
2569
+ if (limit !== void 0 && count >= limit) {
2570
+ break;
2571
+ }
2572
+ if (maxOutputSize !== void 0 && count > maxOutputSize) {
2573
+ throw new Error(`Output size exceeds maximum allowed size of ${maxOutputSize}`);
2574
+ }
2575
+ }
2576
+ }
2577
+
2023
2578
  // src/index.ts
2024
2579
  var TYPE_ANY = 1 /* TYPE_ANY */;
2025
2580
  var TYPE_ARRAY = 3 /* TYPE_ARRAY */;
2581
+ var TYPE_ARRAY_ARRAY = 11 /* TYPE_ARRAY_ARRAY */;
2026
2582
  var TYPE_ARRAY_NUMBER = 8 /* TYPE_ARRAY_NUMBER */;
2583
+ var TYPE_ARRAY_OBJECT = 10 /* TYPE_ARRAY_OBJECT */;
2027
2584
  var TYPE_ARRAY_STRING = 9 /* TYPE_ARRAY_STRING */;
2028
2585
  var TYPE_BOOLEAN = 5 /* TYPE_BOOLEAN */;
2029
2586
  var TYPE_EXPREF = 6 /* TYPE_EXPREF */;
@@ -2032,8 +2589,37 @@ var TYPE_NUMBER = 0 /* TYPE_NUMBER */;
2032
2589
  var TYPE_OBJECT = 4 /* TYPE_OBJECT */;
2033
2590
  var TYPE_STRING = 2 /* TYPE_STRING */;
2034
2591
  function compile(expression2, options) {
2592
+ return Parser_default.parse(expression2, options);
2593
+ }
2594
+ function compileQuery(expression2, options) {
2035
2595
  const nodeTree = Parser_default.parse(expression2, options);
2036
- return nodeTree;
2596
+ const fn = function(data) {
2597
+ return TreeInterpreter_default.search(nodeTree, data, options);
2598
+ };
2599
+ fn.search = (data) => TreeInterpreter_default.search(nodeTree, data, options);
2600
+ fn.searchStream = (source, streamOptions) => searchStream(source, nodeTree, { ...options, ...streamOptions });
2601
+ fn.ast = nodeTree;
2602
+ return fn;
2603
+ }
2604
+ function validate(expression2, options) {
2605
+ if (typeof expression2 !== "string") {
2606
+ return { valid: false, error: "Expression must be a string" };
2607
+ }
2608
+ try {
2609
+ const ast = Parser_default.parse(expression2, options);
2610
+ if (options) {
2611
+ const fnError = findDisallowedFunction(ast, options);
2612
+ if (fnError) {
2613
+ return { valid: false, error: fnError };
2614
+ }
2615
+ }
2616
+ return { valid: true, ast };
2617
+ } catch (err) {
2618
+ return {
2619
+ valid: false,
2620
+ error: err instanceof Error ? err.message : String(err)
2621
+ };
2622
+ }
2037
2623
  }
2038
2624
  function tokenize(expression2, options) {
2039
2625
  return Lexer_default.tokenize(expression2, options);
@@ -2059,13 +2645,36 @@ var getCustomFunctions = () => {
2059
2645
  var clearCustomFunctions = () => {
2060
2646
  TreeInterpreter_default.runtime.clearCustomFunctions();
2061
2647
  };
2648
+ var MAX_CACHE_SIZE = 1e3;
2649
+ var astCache = /* @__PURE__ */ new Map();
2062
2650
  function search(data, expression2, options) {
2063
- const nodeTree = Parser_default.parse(expression2, options);
2064
- return TreeInterpreter_default.search(nodeTree, data);
2651
+ let nodeTree;
2652
+ if (!options) {
2653
+ nodeTree = astCache.get(expression2);
2654
+ if (!nodeTree) {
2655
+ nodeTree = Parser_default.parse(expression2);
2656
+ if (astCache.size >= MAX_CACHE_SIZE) {
2657
+ const firstKey = astCache.keys().next().value;
2658
+ if (firstKey !== void 0) {
2659
+ astCache.delete(firstKey);
2660
+ }
2661
+ }
2662
+ astCache.set(expression2, nodeTree);
2663
+ }
2664
+ } else {
2665
+ nodeTree = Parser_default.parse(expression2, options);
2666
+ }
2667
+ return TreeInterpreter_default.search(nodeTree, data, options);
2668
+ }
2669
+ function Scope() {
2670
+ return new ScopeChain();
2065
2671
  }
2066
2672
  var TreeInterpreter2 = TreeInterpreter_default;
2067
2673
  var jmespath = {
2068
2674
  compile,
2675
+ compileQuery,
2676
+ searchStream,
2677
+ validate,
2069
2678
  registerFunction,
2070
2679
  register,
2071
2680
  unregisterFunction,
@@ -2085,8 +2694,12 @@ var jmespath = {
2085
2694
  TYPE_NULL,
2086
2695
  TYPE_NUMBER,
2087
2696
  TYPE_OBJECT,
2088
- TYPE_STRING
2697
+ TYPE_STRING,
2698
+ TYPE_ARRAY_ARRAY,
2699
+ TYPE_ARRAY_OBJECT,
2700
+ Scope
2089
2701
  };
2702
+ var index_default = jmespath;
2090
2703
 
2091
2704
  // src/cli.ts
2092
2705
  var args = getArgs();
@@ -2172,7 +2785,7 @@ function printResult(inputJSON2, expression2, compact = false) {
2172
2785
  throw e;
2173
2786
  }
2174
2787
  try {
2175
- console.log(JSON.stringify(jmespath.search(parsedInput, expression2, void 0), null, compact ? 0 : 2));
2788
+ console.log(JSON.stringify(index_default.search(parsedInput, expression2, void 0), null, compact ? 0 : 2));
2176
2789
  } catch (e) {
2177
2790
  throw e;
2178
2791
  }