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