@jbrowse/jexl 2.3.1

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.
Files changed (89) hide show
  1. package/CHANGELOG.md +222 -0
  2. package/LICENSE.txt +19 -0
  3. package/README.md +216 -0
  4. package/dist/Expression.d.ts +38 -0
  5. package/dist/Expression.js +75 -0
  6. package/dist/Expression.js.map +1 -0
  7. package/dist/Jexl.d.ts +148 -0
  8. package/dist/Jexl.js +208 -0
  9. package/dist/Jexl.js.map +1 -0
  10. package/dist/Lexer.d.ts +130 -0
  11. package/dist/Lexer.js +321 -0
  12. package/dist/Lexer.js.map +1 -0
  13. package/dist/PromiseSync.d.ts +13 -0
  14. package/dist/PromiseSync.js +80 -0
  15. package/dist/PromiseSync.js.map +1 -0
  16. package/dist/evaluator/Evaluator.d.ts +92 -0
  17. package/dist/evaluator/Evaluator.js +153 -0
  18. package/dist/evaluator/Evaluator.js.map +1 -0
  19. package/dist/evaluator/handlers.d.ts +111 -0
  20. package/dist/evaluator/handlers.js +216 -0
  21. package/dist/evaluator/handlers.js.map +1 -0
  22. package/dist/grammar.d.ts +25 -0
  23. package/dist/grammar.js +179 -0
  24. package/dist/grammar.js.map +1 -0
  25. package/dist/index.d.ts +5 -0
  26. package/dist/index.js +20 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/package.json +1 -0
  29. package/dist/parser/Parser.d.ts +112 -0
  30. package/dist/parser/Parser.js +233 -0
  31. package/dist/parser/Parser.js.map +1 -0
  32. package/dist/parser/handlers.d.ts +112 -0
  33. package/dist/parser/handlers.js +302 -0
  34. package/dist/parser/handlers.js.map +1 -0
  35. package/dist/parser/states.d.ts +47 -0
  36. package/dist/parser/states.js +195 -0
  37. package/dist/parser/states.js.map +1 -0
  38. package/dist/types.d.ts +77 -0
  39. package/dist/types.js +7 -0
  40. package/dist/types.js.map +1 -0
  41. package/esm/Expression.d.ts +38 -0
  42. package/esm/Expression.js +70 -0
  43. package/esm/Expression.js.map +1 -0
  44. package/esm/Jexl.d.ts +148 -0
  45. package/esm/Jexl.js +202 -0
  46. package/esm/Jexl.js.map +1 -0
  47. package/esm/Lexer.d.ts +130 -0
  48. package/esm/Lexer.js +319 -0
  49. package/esm/Lexer.js.map +1 -0
  50. package/esm/PromiseSync.d.ts +13 -0
  51. package/esm/PromiseSync.js +78 -0
  52. package/esm/PromiseSync.js.map +1 -0
  53. package/esm/evaluator/Evaluator.d.ts +92 -0
  54. package/esm/evaluator/Evaluator.js +118 -0
  55. package/esm/evaluator/Evaluator.js.map +1 -0
  56. package/esm/evaluator/handlers.d.ts +111 -0
  57. package/esm/evaluator/handlers.js +202 -0
  58. package/esm/evaluator/handlers.js.map +1 -0
  59. package/esm/grammar.d.ts +25 -0
  60. package/esm/grammar.js +175 -0
  61. package/esm/grammar.js.map +1 -0
  62. package/esm/index.d.ts +5 -0
  63. package/esm/index.js +9 -0
  64. package/esm/index.js.map +1 -0
  65. package/esm/parser/Parser.d.ts +112 -0
  66. package/esm/parser/Parser.js +198 -0
  67. package/esm/parser/Parser.js.map +1 -0
  68. package/esm/parser/handlers.d.ts +112 -0
  69. package/esm/parser/handlers.js +280 -0
  70. package/esm/parser/handlers.js.map +1 -0
  71. package/esm/parser/states.d.ts +47 -0
  72. package/esm/parser/states.js +159 -0
  73. package/esm/parser/states.js.map +1 -0
  74. package/esm/types.d.ts +77 -0
  75. package/esm/types.js +6 -0
  76. package/esm/types.js.map +1 -0
  77. package/package.json +67 -0
  78. package/src/Expression.ts +95 -0
  79. package/src/Jexl.ts +232 -0
  80. package/src/Lexer.ts +344 -0
  81. package/src/PromiseSync.ts +86 -0
  82. package/src/evaluator/Evaluator.ts +153 -0
  83. package/src/evaluator/handlers.ts +226 -0
  84. package/src/grammar.ts +200 -0
  85. package/src/index.ts +10 -0
  86. package/src/parser/Parser.ts +235 -0
  87. package/src/parser/handlers.ts +309 -0
  88. package/src/parser/states.ts +177 -0
  89. package/src/types.ts +107 -0
package/dist/Lexer.js ADDED
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+ /*
3
+ * Jexl
4
+ * Copyright 2020 Tom Shawver
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const numericRegex = /^-?(?:(?:[0-9]*\.[0-9]+)|[0-9]+)$/;
8
+ const identRegex = /^[a-zA-Zа-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$][a-zA-Zа-яА-Я0-9_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF$]*$/;
9
+ const escEscRegex = /\\\\/;
10
+ const whitespaceRegex = /^\s*$/;
11
+ const preOpRegexElems = [
12
+ // Template strings
13
+ '`(?:[^`\\\\]|\\\\.)*`',
14
+ // Strings
15
+ String.raw `'(?:(?:\\')|[^'])*'`,
16
+ String.raw `"(?:(?:\\")|[^"])*"`,
17
+ // Whitespace
18
+ String.raw `\s+`,
19
+ // Booleans
20
+ String.raw `\btrue\b`,
21
+ String.raw `\bfalse\b`
22
+ ];
23
+ const postOpRegexElems = [
24
+ // Identifiers
25
+ '[a-zA-Zа-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\\$][a-zA-Z0-9а-яА-Я_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\\$]*',
26
+ // Numerics (without negative symbol)
27
+ String.raw `(?:(?:[0-9]*\.[0-9]+)|[0-9]+)`
28
+ ];
29
+ const minusNegatesAfter = new Set([
30
+ 'binaryOp',
31
+ 'unaryOp',
32
+ 'openParen',
33
+ 'openBracket',
34
+ 'question',
35
+ 'colon'
36
+ ]);
37
+ /**
38
+ * Lexer is a collection of stateless, statically-accessed functions for the
39
+ * lexical parsing of a Jexl string. Its responsibility is to identify the
40
+ * "parts of speech" of a Jexl expression, and tokenize and label each, but
41
+ * to do only the most minimal syntax checking; the only errors the Lexer
42
+ * should be concerned with are if it's unable to identify the utility of
43
+ * any of its tokens. Errors stemming from these tokens not being in a
44
+ * sensible configuration should be left for the Parser to handle.
45
+ * @type {{}}
46
+ */
47
+ class Lexer {
48
+ constructor(grammar) {
49
+ this._escQuoteRegexCache = new Map();
50
+ this._grammar = grammar;
51
+ }
52
+ /**
53
+ * Splits a Jexl expression string into an array of expression elements.
54
+ * @param {string} str A Jexl expression string
55
+ * @returns {Array<string>} An array of substrings defining the functional
56
+ * elements of the expression.
57
+ */
58
+ getElements(str) {
59
+ const regex = this._getSplitRegex();
60
+ return str.split(regex).filter(Boolean);
61
+ }
62
+ /**
63
+ * Converts an array of expression elements into an array of tokens. Note that
64
+ * the resulting array may not equal the element array in length, as any
65
+ * elements that consist only of whitespace get appended to the previous
66
+ * token's "raw" property. For the structure of a token object, please see
67
+ * {@link Lexer#tokenize}.
68
+ * @param {Array<string>} elements An array of Jexl expression elements to be
69
+ * converted to tokens
70
+ * @returns {Array<{type, value, raw}>} an array of token objects.
71
+ */
72
+ getTokens(elements) {
73
+ const tokens = [];
74
+ let negate = false;
75
+ for (let i = 0; i < elements.length; i++) {
76
+ if (this._isWhitespace(elements[i])) {
77
+ if (tokens.length) {
78
+ tokens[tokens.length - 1].raw += elements[i];
79
+ }
80
+ }
81
+ else if (elements[i] === '-' && this._isNegative(tokens)) {
82
+ negate = true;
83
+ }
84
+ else {
85
+ if (negate) {
86
+ elements[i] = '-' + elements[i];
87
+ negate = false;
88
+ }
89
+ tokens.push(this._createToken(elements[i]));
90
+ }
91
+ }
92
+ // Catch a - at the end of the string. Let the parser handle that issue.
93
+ if (negate) {
94
+ tokens.push(this._createToken('-'));
95
+ }
96
+ return tokens;
97
+ }
98
+ /**
99
+ * Converts a Jexl string into an array of tokens. Each token is an object
100
+ * in the following format:
101
+ *
102
+ * {
103
+ * type: <string>,
104
+ * [name]: <string>,
105
+ * value: <boolean|number|string>,
106
+ * raw: <string>
107
+ * }
108
+ *
109
+ * Type is one of the following:
110
+ *
111
+ * literal, identifier, binaryOp, unaryOp
112
+ *
113
+ * OR, if the token is a control character its type is the name of the element
114
+ * defined in the Grammar.
115
+ *
116
+ * Name appears only if the token is a control string found in
117
+ * {@link grammar#elements}, and is set to the name of the element.
118
+ *
119
+ * Value is the value of the token in the correct type (boolean or numeric as
120
+ * appropriate). Raw is the string representation of this value taken directly
121
+ * from the expression string, including any trailing spaces.
122
+ * @param {string} str The Jexl string to be tokenized
123
+ * @returns {Array<{type, value, raw}>} an array of token objects.
124
+ * @throws {Error} if the provided string contains an invalid token.
125
+ */
126
+ tokenize(str) {
127
+ const elements = this.getElements(str);
128
+ return this.getTokens(elements);
129
+ }
130
+ /**
131
+ * Creates a new token object from an element of a Jexl string. See
132
+ * {@link Lexer#tokenize} for a description of the token object.
133
+ * @param {string} element The element from which a token should be made
134
+ * @returns {{value: number|boolean|string, [name]: string, type: string,
135
+ * raw: string}} a token object describing the provided element.
136
+ * @throws {Error} if the provided string is not a valid expression element.
137
+ * @private
138
+ */
139
+ _createToken(element) {
140
+ const token = {
141
+ type: 'literal',
142
+ value: element,
143
+ raw: element
144
+ };
145
+ if (element.startsWith('`')) {
146
+ token.type = 'templateString';
147
+ token.value = this._parseTemplateString(element);
148
+ return token;
149
+ }
150
+ else if (element.startsWith('"') || element.startsWith("'")) {
151
+ token.value = this._unquote(element);
152
+ }
153
+ else if (numericRegex.exec(element)) {
154
+ token.value = parseFloat(element);
155
+ }
156
+ else if (element === 'true' || element === 'false') {
157
+ token.value = element === 'true';
158
+ }
159
+ else if (this._grammar.elements[element]) {
160
+ token.type = this._grammar.elements[element].type;
161
+ }
162
+ else if (identRegex.exec(element)) {
163
+ token.type = 'identifier';
164
+ }
165
+ else {
166
+ throw new Error(`Invalid expression token: ${element}`);
167
+ }
168
+ return token;
169
+ }
170
+ /**
171
+ * Escapes a string so that it can be treated as a string literal within a
172
+ * regular expression.
173
+ * @param {string} str The string to be escaped
174
+ * @returns {string} the RegExp-escaped string.
175
+ * @see https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions
176
+ * @private
177
+ */
178
+ _escapeRegExp(str) {
179
+ str = str.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw `\$&`);
180
+ if (identRegex.exec(str)) {
181
+ str = String.raw `\b` + str + String.raw `\b`;
182
+ }
183
+ return str;
184
+ }
185
+ /**
186
+ * Gets a RegEx object appropriate for splitting a Jexl string into its core
187
+ * elements.
188
+ * @returns {RegExp} An element-splitting RegExp object
189
+ * @private
190
+ */
191
+ _getSplitRegex() {
192
+ if (!this._splitRegex) {
193
+ // Sort by most characters to least, then regex escape each
194
+ const elemArray = Object.keys(this._grammar.elements)
195
+ .sort((a, b) => {
196
+ return b.length - a.length;
197
+ })
198
+ .map((elem) => {
199
+ return this._escapeRegExp(elem);
200
+ });
201
+ this._splitRegex = new RegExp('(' +
202
+ [
203
+ preOpRegexElems.join('|'),
204
+ elemArray.join('|'),
205
+ postOpRegexElems.join('|')
206
+ ].join('|') +
207
+ ')');
208
+ }
209
+ return this._splitRegex;
210
+ }
211
+ /**
212
+ * Determines whether the addition of a '-' token should be interpreted as a
213
+ * negative symbol for an upcoming number, given an array of tokens already
214
+ * processed.
215
+ * @param {Array<Object>} tokens An array of tokens already processed
216
+ * @returns {boolean} true if adding a '-' should be considered a negative
217
+ * symbol; false otherwise
218
+ * @private
219
+ */
220
+ _isNegative(tokens) {
221
+ if (!tokens.length) {
222
+ return true;
223
+ }
224
+ return minusNegatesAfter.has(tokens[tokens.length - 1].type);
225
+ }
226
+ /**
227
+ * A utility function to determine if a string consists of only space
228
+ * characters.
229
+ * @param {string} str A string to be tested
230
+ * @returns {boolean} true if the string is empty or consists of only spaces;
231
+ * false otherwise.
232
+ * @private
233
+ */
234
+ _isWhitespace(str) {
235
+ return !!whitespaceRegex.exec(str);
236
+ }
237
+ /**
238
+ * Removes the beginning and trailing quotes from a string, unescapes any
239
+ * escaped quotes on its interior, and unescapes any escaped escape
240
+ * characters. Note that this function is not defensive; it assumes that the
241
+ * provided string is not empty, and that its first and last characters are
242
+ * actually quotes.
243
+ * @param {string} str A string whose first and last characters are quotes
244
+ * @returns {string} a string with the surrounding quotes stripped and escapes
245
+ * properly processed.
246
+ * @private
247
+ */
248
+ _unquote(str) {
249
+ const quote = str[0];
250
+ let escQuoteRegex = this._escQuoteRegexCache.get(quote);
251
+ if (!escQuoteRegex) {
252
+ escQuoteRegex = new RegExp('\\\\' + quote, 'g');
253
+ this._escQuoteRegexCache.set(quote, escQuoteRegex);
254
+ }
255
+ return str
256
+ .slice(1, -1)
257
+ .replace(escQuoteRegex, quote)
258
+ .replace(escEscRegex, '\\');
259
+ }
260
+ _parseTemplateString(str) {
261
+ const parts = [];
262
+ let current = 1;
263
+ let staticStart = 1;
264
+ while (current < str.length - 1) {
265
+ if (str[current] === '\\') {
266
+ current += 2;
267
+ continue;
268
+ }
269
+ if (str[current] === '$' && str[current + 1] === '{') {
270
+ if (current > staticStart) {
271
+ parts.push({
272
+ type: 'static',
273
+ value: str.slice(staticStart, current)
274
+ });
275
+ }
276
+ let braceDepth = 1;
277
+ const interpStart = current + 2;
278
+ current += 2;
279
+ while (current < str.length && braceDepth > 0) {
280
+ if (str[current] === '\\') {
281
+ current += 2;
282
+ continue;
283
+ }
284
+ if (str[current] === '{') {
285
+ braceDepth++;
286
+ }
287
+ if (str[current] === '}') {
288
+ braceDepth--;
289
+ }
290
+ current++;
291
+ }
292
+ if (braceDepth !== 0) {
293
+ throw new Error(`Unclosed interpolation in template string: ${str}`);
294
+ }
295
+ parts.push({
296
+ type: 'interpolation',
297
+ value: str.slice(interpStart, current - 1)
298
+ });
299
+ staticStart = current;
300
+ }
301
+ else {
302
+ current++;
303
+ }
304
+ }
305
+ if (current > staticStart) {
306
+ parts.push({
307
+ type: 'static',
308
+ value: str.slice(staticStart, current)
309
+ });
310
+ }
311
+ return parts;
312
+ }
313
+ _unescapeTemplateString(str) {
314
+ return str
315
+ .replaceAll('\\`', '`')
316
+ .replaceAll(String.raw `\$`, '$')
317
+ .replaceAll('\\\\', '\\');
318
+ }
319
+ }
320
+ exports.default = Lexer;
321
+ //# sourceMappingURL=Lexer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Lexer.js","sourceRoot":"","sources":["../src/Lexer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ declare class PromiseSync<T = unknown> {
2
+ value?: T;
3
+ error?: unknown;
4
+ constructor(fn: (resolve: (val: T) => void, reject: (error: unknown) => void) => void);
5
+ catch<TResult = never>(rejected: (error: unknown) => TResult): PromiseSync<T | TResult>;
6
+ then<TResult1 = T, TResult2 = never>(resolved: (val: T) => TResult1, rejected?: (error: unknown) => TResult2): PromiseSync<TResult1 | TResult2>;
7
+ _reject(error: unknown): void;
8
+ _resolve(val: any): void;
9
+ static all<T>(vals: (PromiseSync<T> | T)[]): PromiseSync<T[]>;
10
+ static resolve<T>(val?: T): PromiseSync<T>;
11
+ static reject(error: unknown): PromiseSync<never>;
12
+ }
13
+ export default PromiseSync;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /*
3
+ * Jexl
4
+ * Copyright 2020 Tom Shawver
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ class PromiseSync {
8
+ constructor(fn) {
9
+ fn(this._resolve.bind(this), this._reject.bind(this));
10
+ }
11
+ catch(rejected) {
12
+ if (this.error) {
13
+ try {
14
+ this._resolve(rejected(this.error));
15
+ }
16
+ catch (e) {
17
+ this._reject(e);
18
+ }
19
+ }
20
+ return this;
21
+ }
22
+ // eslint-disable-next-line unicorn/no-thenable
23
+ then(resolved, rejected) {
24
+ if (!this.error) {
25
+ try {
26
+ this._resolve(resolved(this.value));
27
+ }
28
+ catch (e) {
29
+ this._reject(e);
30
+ }
31
+ }
32
+ if (rejected) {
33
+ this.catch(rejected);
34
+ }
35
+ return this;
36
+ }
37
+ _reject(error) {
38
+ this.value = undefined;
39
+ this.error = error;
40
+ }
41
+ _resolve(val) {
42
+ if (val instanceof PromiseSync) {
43
+ if (val.error) {
44
+ this._reject(val.error);
45
+ }
46
+ else {
47
+ this._resolve(val.value);
48
+ }
49
+ }
50
+ else {
51
+ this.value = val;
52
+ this.error = undefined;
53
+ }
54
+ }
55
+ static all(vals) {
56
+ return new PromiseSync((resolve) => {
57
+ const resolved = vals.map((val) => {
58
+ while (val instanceof PromiseSync) {
59
+ if (val.error) {
60
+ if (val.error instanceof Error) {
61
+ throw val.error;
62
+ }
63
+ throw new Error(typeof val.error === 'string' ? val.error : JSON.stringify(val.error));
64
+ }
65
+ val = val.value;
66
+ }
67
+ return val;
68
+ });
69
+ resolve(resolved);
70
+ });
71
+ }
72
+ static resolve(val) {
73
+ return new PromiseSync((resolve) => { resolve(val); });
74
+ }
75
+ static reject(error) {
76
+ return new PromiseSync((_, reject) => { reject(error); });
77
+ }
78
+ }
79
+ exports.default = PromiseSync;
80
+ //# sourceMappingURL=PromiseSync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PromiseSync.js","sourceRoot":"","sources":["../src/PromiseSync.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAEH,MAAM,WAAW;IAIf,YAAY,EAAyE;QACnF,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACvD,CAAC;IAED,KAAK,CAAkB,QAAqC;QAC1D,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC;gBACH,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAQ,CAAC,CAAA;YAC5C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;QACH,CAAC;QACD,OAAO,IAAW,CAAA;IACpB,CAAC;IAED,+CAA+C;IAC/C,IAAI,CACF,QAA8B,EAC9B,QAAuC;QAEvC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC;gBACH,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAU,CAAQ,CAAC,CAAA;YACjD,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC;QACH,CAAC;QACD,IAAI,QAAQ,EAAE,CAAC;YAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;QAAA,CAAC;QACpC,OAAO,IAAW,CAAA;IACpB,CAAC;IAED,OAAO,CAAC,KAAc;QACpB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;QACtB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACpB,CAAC;IAED,QAAQ,CAAC,GAAQ;QACf,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;YAC/B,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;gBACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YACzB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YAC1B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,GAAG,GAAG,CAAA;YAChB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAA;QACxB,CAAC;IACH,CAAC;IAED,MAAM,CAAC,GAAG,CAAI,IAA4B;QACxC,OAAO,IAAI,WAAW,CAAC,CAAC,OAAO,EAAE,EAAE;YACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;gBAChC,OAAO,GAAG,YAAY,WAAW,EAAE,CAAC;oBAClC,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;wBACd,IAAI,GAAG,CAAC,KAAK,YAAY,KAAK,EAAE,CAAC;4BAC/B,MAAM,GAAG,CAAC,KAAK,CAAA;wBACjB,CAAC;wBACD,MAAM,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;oBACxF,CAAC;oBACD,GAAG,GAAG,GAAG,CAAC,KAAU,CAAA;gBACtB,CAAC;gBACD,OAAO,GAAG,CAAA;YACZ,CAAC,CAAC,CAAA;YACF,OAAO,CAAC,QAAQ,CAAC,CAAA;QACnB,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,CAAC,OAAO,CAAI,GAAO;QACvB,OAAO,IAAI,WAAW,CAAI,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,GAAQ,CAAC,CAAA,CAAC,CAAC,CAAC,CAAA;IAC/D,CAAC;IAED,MAAM,CAAC,MAAM,CAAC,KAAc;QAC1B,OAAO,IAAI,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA,CAAC,CAAC,CAAC,CAAA;IAC1D,CAAC;CACF;AAED,kBAAe,WAAW,CAAA"}
@@ -0,0 +1,92 @@
1
+ import type { AstNode } from '../types.ts';
2
+ interface Grammar {
3
+ elements: Record<string, any>;
4
+ [key: string]: any;
5
+ }
6
+ type PromiseConstructor = typeof Promise | any;
7
+ /**
8
+ * The Evaluator takes a Jexl expression tree as generated by the
9
+ * {@link Parser} and calculates its value within a given context. The
10
+ * collection of transforms, context, and a relative context to be used as the
11
+ * root for relative identifiers, are all specific to an Evaluator instance.
12
+ * When any of these things change, a new instance is required. However, a
13
+ * single instance can be used to simultaneously evaluate many different
14
+ * expressions, and does not have to be reinstantiated for each.
15
+ * @param {{}} grammar A grammar object against which to evaluate the expression
16
+ * tree
17
+ * @param {{}} [context] A map of variable keys to their values. This will be
18
+ * accessed to resolve the value of each non-relative identifier. Any
19
+ * Promise values will be passed to the expression as their resolved
20
+ * value.
21
+ * @param {{}|Array<{}|Array>} [relativeContext] A map or array to be accessed
22
+ * to resolve the value of a relative identifier.
23
+ * @param {function} promise A constructor for the Promise class to be used;
24
+ * probably either Promise or PromiseSync.
25
+ */
26
+ declare class Evaluator {
27
+ _grammar: Grammar;
28
+ _context: any;
29
+ _relContext: any;
30
+ Promise: PromiseConstructor;
31
+ constructor(grammar: Grammar, context?: any, relativeContext?: any, promise?: PromiseConstructor);
32
+ /**
33
+ * Evaluates an expression tree within the configured context.
34
+ * @param {{}} ast An expression tree object
35
+ * @returns {Promise<*>} resolves with the resulting value of the expression.
36
+ */
37
+ eval(ast: AstNode): any;
38
+ /**
39
+ * Simultaneously evaluates each expression within an array, and delivers the
40
+ * response as an array with the resulting values at the same indexes as their
41
+ * originating expressions.
42
+ * @param {Array<string>} arr An array of expression strings to be evaluated
43
+ * @returns {Promise<Array<{}>>} resolves with the result array
44
+ */
45
+ evalArray(arr: AstNode[]): any;
46
+ /**
47
+ * Simultaneously evaluates each expression within a map, and delivers the
48
+ * response as a map with the same keys, but with the evaluated result for each
49
+ * as their value.
50
+ * @param {{}} map A map of expression names to expression trees to be
51
+ * evaluated
52
+ * @returns {Promise<{}>} resolves with the result map.
53
+ */
54
+ evalMap(map: Record<string, AstNode>): any;
55
+ /**
56
+ * Applies a filter expression with relative identifier elements to a subject.
57
+ * The intent is for the subject to be an array of subjects that will be
58
+ * individually used as the relative context against the provided expression
59
+ * tree. Only the elements whose expressions result in a truthy value will be
60
+ * included in the resulting array.
61
+ *
62
+ * If the subject is not an array of values, it will be converted to a single-
63
+ * element array before running the filter.
64
+ * @param {*} subject The value to be filtered usually an array. If this value is
65
+ * not an array, it will be converted to an array with this value as the
66
+ * only element.
67
+ * @param {{}} expr The expression tree to run against each subject. If the
68
+ * tree evaluates to a truthy result, then the value will be included in
69
+ * the returned array otherwise, it will be eliminated.
70
+ * @returns {Promise<Array>} resolves with an array of values that passed the
71
+ * expression filter.
72
+ * @private
73
+ */
74
+ _filterRelative(subject: any, expr: AstNode): any;
75
+ /**
76
+ * Applies a static filter expression to a subject value. If the filter
77
+ * expression evaluates to boolean true, the subject is returned if false,
78
+ * undefined.
79
+ *
80
+ * For any other resulting value of the expression, this function will attempt
81
+ * to respond with the property at that name or index of the subject.
82
+ * @param {*} subject The value to be filtered. Usually an Array (for which
83
+ * the expression would generally resolve to a numeric index) or an
84
+ * Object (for which the expression would generally resolve to a string
85
+ * indicating a property name)
86
+ * @param {{}} expr The expression tree to run against the subject
87
+ * @returns {Promise<*>} resolves with the value of the drill-down.
88
+ * @private
89
+ */
90
+ _filterStatic(subject: any, expr: AstNode): any;
91
+ }
92
+ export default Evaluator;
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ /*
3
+ * Jexl
4
+ * Copyright 2020 Tom Shawver
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const handlers = __importStar(require("./handlers.js"));
41
+ /**
42
+ * The Evaluator takes a Jexl expression tree as generated by the
43
+ * {@link Parser} and calculates its value within a given context. The
44
+ * collection of transforms, context, and a relative context to be used as the
45
+ * root for relative identifiers, are all specific to an Evaluator instance.
46
+ * When any of these things change, a new instance is required. However, a
47
+ * single instance can be used to simultaneously evaluate many different
48
+ * expressions, and does not have to be reinstantiated for each.
49
+ * @param {{}} grammar A grammar object against which to evaluate the expression
50
+ * tree
51
+ * @param {{}} [context] A map of variable keys to their values. This will be
52
+ * accessed to resolve the value of each non-relative identifier. Any
53
+ * Promise values will be passed to the expression as their resolved
54
+ * value.
55
+ * @param {{}|Array<{}|Array>} [relativeContext] A map or array to be accessed
56
+ * to resolve the value of a relative identifier.
57
+ * @param {function} promise A constructor for the Promise class to be used;
58
+ * probably either Promise or PromiseSync.
59
+ */
60
+ class Evaluator {
61
+ constructor(grammar, context, relativeContext, promise = Promise) {
62
+ this._grammar = grammar;
63
+ this._context = context || {};
64
+ this._relContext = relativeContext || this._context;
65
+ this.Promise = promise;
66
+ }
67
+ /**
68
+ * Evaluates an expression tree within the configured context.
69
+ * @param {{}} ast An expression tree object
70
+ * @returns {Promise<*>} resolves with the resulting value of the expression.
71
+ */
72
+ eval(ast) {
73
+ return this.Promise.resolve().then(() => {
74
+ return handlers[ast.type].call(this, ast);
75
+ });
76
+ }
77
+ /**
78
+ * Simultaneously evaluates each expression within an array, and delivers the
79
+ * response as an array with the resulting values at the same indexes as their
80
+ * originating expressions.
81
+ * @param {Array<string>} arr An array of expression strings to be evaluated
82
+ * @returns {Promise<Array<{}>>} resolves with the result array
83
+ */
84
+ evalArray(arr) {
85
+ return this.Promise.all(arr.map((elem) => this.eval(elem)));
86
+ }
87
+ /**
88
+ * Simultaneously evaluates each expression within a map, and delivers the
89
+ * response as a map with the same keys, but with the evaluated result for each
90
+ * as their value.
91
+ * @param {{}} map A map of expression names to expression trees to be
92
+ * evaluated
93
+ * @returns {Promise<{}>} resolves with the result map.
94
+ */
95
+ evalMap(map) {
96
+ const entries = Object.entries(map);
97
+ const promises = entries.map(([_, ast]) => this.eval(ast));
98
+ return this.Promise.all(promises).then((vals) => Object.fromEntries(entries.map(([key], idx) => [key, vals[idx]])));
99
+ }
100
+ /**
101
+ * Applies a filter expression with relative identifier elements to a subject.
102
+ * The intent is for the subject to be an array of subjects that will be
103
+ * individually used as the relative context against the provided expression
104
+ * tree. Only the elements whose expressions result in a truthy value will be
105
+ * included in the resulting array.
106
+ *
107
+ * If the subject is not an array of values, it will be converted to a single-
108
+ * element array before running the filter.
109
+ * @param {*} subject The value to be filtered usually an array. If this value is
110
+ * not an array, it will be converted to an array with this value as the
111
+ * only element.
112
+ * @param {{}} expr The expression tree to run against each subject. If the
113
+ * tree evaluates to a truthy result, then the value will be included in
114
+ * the returned array otherwise, it will be eliminated.
115
+ * @returns {Promise<Array>} resolves with an array of values that passed the
116
+ * expression filter.
117
+ * @private
118
+ */
119
+ _filterRelative(subject, expr) {
120
+ const arr = Array.isArray(subject)
121
+ ? subject
122
+ : subject == null
123
+ ? []
124
+ : [subject];
125
+ const promises = arr.map((elem) => new Evaluator(this._grammar, this._context, elem, this.Promise).eval(expr));
126
+ return this.Promise.all(promises).then((values) => arr.filter((_, idx) => values[idx]));
127
+ }
128
+ /**
129
+ * Applies a static filter expression to a subject value. If the filter
130
+ * expression evaluates to boolean true, the subject is returned if false,
131
+ * undefined.
132
+ *
133
+ * For any other resulting value of the expression, this function will attempt
134
+ * to respond with the property at that name or index of the subject.
135
+ * @param {*} subject The value to be filtered. Usually an Array (for which
136
+ * the expression would generally resolve to a numeric index) or an
137
+ * Object (for which the expression would generally resolve to a string
138
+ * indicating a property name)
139
+ * @param {{}} expr The expression tree to run against the subject
140
+ * @returns {Promise<*>} resolves with the value of the drill-down.
141
+ * @private
142
+ */
143
+ _filterStatic(subject, expr) {
144
+ return this.eval(expr).then((res) => {
145
+ if (typeof res === 'boolean') {
146
+ return res ? subject : undefined;
147
+ }
148
+ return subject?.[res];
149
+ });
150
+ }
151
+ }
152
+ exports.default = Evaluator;
153
+ //# sourceMappingURL=Evaluator.js.map