fig-tree-evaluator 2.2.1 → 2.2.3
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/README.md +27 -17
- package/build/evaluate.js +138 -50
- package/build/helpers.d.ts +1 -0
- package/build/helpers.js +132 -46
- package/build/index.d.ts +0 -1
- package/build/index.js +91 -32
- package/build/operators/_operatorAliases.json +3 -0
- package/build/operators/_operatorUtils.js +109 -48
- package/build/operators/buildObject.js +84 -26
- package/build/operators/conditional.js +70 -18
- package/build/operators/count.js +48 -14
- package/build/operators/customFunctions.js +76 -21
- package/build/operators/divide.js +63 -26
- package/build/operators/equal.js +57 -23
- package/build/operators/getRequest.js +85 -31
- package/build/operators/graphQL.js +90 -40
- package/build/operators/greaterThan.js +54 -20
- package/build/operators/lessThan.js +54 -20
- package/build/operators/logicalAnd.js +61 -16
- package/build/operators/logicalOr.js +48 -14
- package/build/operators/match.js +101 -38
- package/build/operators/multiply.js +48 -14
- package/build/operators/notEqual.js +57 -23
- package/build/operators/objectProperties.d.ts +1 -1
- package/build/operators/objectProperties.js +78 -23
- package/build/operators/passThru.js +58 -15
- package/build/operators/pgSQL.js +118 -50
- package/build/operators/plus.js +70 -24
- package/build/operators/postRequest.js +70 -23
- package/build/operators/regex.js +70 -24
- package/build/operators/split.js +74 -29
- package/build/operators/stringSubstitution.js +79 -25
- package/build/operators/subtract.js +50 -16
- package/build/typeCheck.js +27 -22
- package/build/types.d.ts +2 -0
- package/package.json +2 -2
- package/build/.DS_Store +0 -0
- package/build/FigTreeEvaluator.d.ts +0 -13
- package/build/FigTreeEvaluator.js +0 -75
- package/build/evaluator.d.ts +0 -13
- package/build/evaluator.js +0 -75
- package/build/operators/objectFunctions.d.ts +0 -9
- package/build/operators/objectFunctions.js +0 -38
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**FigTree Evaluator** is a module to evaluate JSON-structured expression trees.
|
|
6
6
|
|
|
7
|
-
A typical use case would be for evaluating **configuration** files, where you need to store dynamic values or arbitrary logic without allowing users to inject executable code. For example, a [form-builder app](https://github.com/openmsupply/conforma-web-app) might need to allow complex conditional logic for form element visibility based on previous responses, or for validation beyond what is available in standard validation libraries.
|
|
7
|
+
A typical use case would be for evaluating **configuration** files, where you need to store dynamic values or arbitrary logic without allowing users to inject executable code (perhaps in a .json file, say). For example, a [form-builder app](https://github.com/openmsupply/conforma-web-app) might need to allow complex conditional logic for form element visibility based on previous responses, or for validation beyond what is available in standard validation libraries.
|
|
8
8
|
|
|
9
9
|
Another example would be to configure a [decision tree](https://en.wikipedia.org/wiki/Decision_tree) to implement branching logic.
|
|
10
10
|
|
|
@@ -135,7 +135,7 @@ const result = await exp.evaluate(expression, [options])
|
|
|
135
135
|
|
|
136
136
|
The `options` parameter is an object with the following available properties (all optional):
|
|
137
137
|
|
|
138
|
-
- `
|
|
138
|
+
- `data` -- a single object containing any *objects* in your application that may wish to be inspected using the [objectProperties](#object_properties) operator. (See [playground](LINK) for examples). If these objects are regularly changing, you'll probably want to pass them into each separate evaluation rather than with the initial constructor.
|
|
139
139
|
- `functions` -- a single object containing any *custom functions* available for use by the [customFunctions](#custom_functions) operator.
|
|
140
140
|
- `pgConnection` -- if you wish to make calls to a Postgres database using the [`pgSQL` operator](#pg_sql), pass a [node-postres](https://node-postgres.com/) connection object here.
|
|
141
141
|
- `graphQLConnection` -- a GraphQL connection object, if using the [`graphQL` operator](#graphql). See operator details below.
|
|
@@ -143,10 +143,11 @@ The `options` parameter is an object with the following available properties (al
|
|
|
143
143
|
- `headers` -- A general http headers object that will be passed to *all* http-based operators. Useful for authenticatian headers, for example. Each operator and instance can have its own headers, though, so see specific operator reference for details.
|
|
144
144
|
- `returnErrorAsString` -- by default the evaluator will throw errors with invalid evaluation expressions (with helpful error messages indicating the node which threw the error and what the problem was). But if you have `returnErrorAsString: true` set, the evaluator will never throw, but instead return error messages as a valid string output. (See also the [`fallback`](#other-common-properties) parameter below)
|
|
145
145
|
- `allowJSONStringInput` -- the evaluator is expecting the input expression to be a javascript object. However, it will also accept JSON strings if this option is set to `true`. We have to perform additional logic on every evaluation input to determine if a string is a JSON expression or a standard string, so this is skipped by default for performance reasons. However, if you want to send (for example) user input directly to the evaluator without running it through your own `JSON.parse()`, then enable this option.
|
|
146
|
-
- `skipRuntimeTypeCheck` -- we perform comprehensive type checking at runtime to ensure that each operator only performs its operation on valid inputs. If type checking fails, we throw an error detailing the explicit problem. However, if `skipRuntimeTypeCheck` is set to `true`, then all inputs are passed to the operator regardless, and any errors will come from whatever standard javascript errors might be
|
|
146
|
+
- `skipRuntimeTypeCheck` -- we perform comprehensive type checking at runtime to ensure that each operator only performs its operation on valid inputs. If type checking fails, we throw an error detailing the explicit problem. However, if `skipRuntimeTypeCheck` is set to `true`, then all inputs are passed to the operator regardless, and any errors will come from whatever standard javascript errors might be encountered (e.g. trying to pass a primitive value when an array is expected => `.map is not a function`)
|
|
147
147
|
- `nullEqualsUndefined` -- this only affects the [`equal`/`notEqual` operators](#equal) (see there for more detail).
|
|
148
|
+
- `evaluateFullObject` -- by default, FigTree expects the root of an input expression to be an [Operator Node](#operator-nodes), and if not, will return the input unmodified. However, you may have cases where the evaluation expressions are deep within a larger structure (such as a JSON schema, for example). In this case, you can set `evaluateFullObject` to `true` and the evaluator will find *any* operator nodes within the structure and evaluate them in place.
|
|
148
149
|
|
|
149
|
-
As mentioned above, `options` can be provided as part of the constructor as part of each
|
|
150
|
+
As mentioned above, `options` can be provided as part of the constructor as part of each separate evaluation. You can also change the options permanently for a given evaluator instance with:
|
|
150
151
|
|
|
151
152
|
`exp.updateOptions(options)`
|
|
152
153
|
|
|
@@ -658,16 +659,16 @@ e.g.
|
|
|
658
659
|
----
|
|
659
660
|
### OBJECT_PROPERTIES
|
|
660
661
|
|
|
661
|
-
*Extracts values from objects in your application*
|
|
662
|
+
*Extracts values from data objects in your application*
|
|
662
663
|
|
|
663
|
-
Aliases: `objectProperties`, `objProps`, `getProperty`, `getObjProp`
|
|
664
|
+
Aliases: `objectProperties`, `dataProperties`,`data`, `getData`, `objProps`, `getProperty`, `getObjProp`
|
|
664
665
|
|
|
665
666
|
#### Properties
|
|
666
667
|
|
|
667
668
|
- `property` (or `path`, `propertyName`)<sup>*</sup>: (string) -- the path to the required property in the object
|
|
668
|
-
- `
|
|
669
|
+
- `additionalData` (or `additionalObjects`, `additional`, `data`): (object) -- any other objects whose properties can be referenced in `property` (see below)
|
|
669
670
|
|
|
670
|
-
|
|
671
|
+
Data objects are normally expected to be passed in to the evaluator as part of the [options](#available-options), not as part of the expression itself. This is because the source objects are expected to be values internal to your application, whereas the evaluator provides an externally configurable mechanism to extract (and process) application data. (However, it is possible to pass data objects directly as part of the expression using the `additionalObjects` property, so (in theory) data objects could be dynamically generated from other expressions.)
|
|
671
672
|
|
|
672
673
|
For example, consider a `user` object and an fig-tree evaluator instance:
|
|
673
674
|
|
|
@@ -687,7 +688,7 @@ const exp = new FigTreeEvaluator()
|
|
|
687
688
|
|
|
688
689
|
const expression = getExpressionFromConfig()
|
|
689
690
|
|
|
690
|
-
exp.evaluate(expression, {
|
|
691
|
+
exp.evaluate(expression, { data: { user } })
|
|
691
692
|
```
|
|
692
693
|
|
|
693
694
|
Here is the result of various values of `expression:`
|
|
@@ -700,7 +701,7 @@ Here is the result of various values of `expression:`
|
|
|
700
701
|
// => "Peter"
|
|
701
702
|
|
|
702
703
|
{
|
|
703
|
-
operator: '
|
|
704
|
+
operator: 'getData',
|
|
704
705
|
path: 'user.friends[1]',
|
|
705
706
|
}
|
|
706
707
|
// => "MJ"
|
|
@@ -720,7 +721,7 @@ result.map((e) => e.name)
|
|
|
720
721
|
|
|
721
722
|
The "objectProperties" operator uses [`object-property-extractor`](https://www.npmjs.com/package/object-property-extractor) internally, so please see the documentation of that package for more information.
|
|
722
723
|
|
|
723
|
-
The "objectProperties" operator will throw an error if an invalid path is provided, so it is recommended to provide a `fallback` value for the expression:
|
|
724
|
+
The "objectProperties" operator will throw an error if an invalid path is provided, so it is recommended to provide a [`fallback`](#other-common-properties) value for the expression:
|
|
724
725
|
```js
|
|
725
726
|
{
|
|
726
727
|
operator: 'objectProperties',
|
|
@@ -733,13 +734,13 @@ The "objectProperties" operator will throw an error if an invalid path is provid
|
|
|
733
734
|
`children` array: `[property]`
|
|
734
735
|
|
|
735
736
|
|
|
736
|
-
Example using "
|
|
737
|
+
Example using "data" passed in dynamically as part of expression:
|
|
737
738
|
|
|
738
739
|
```js
|
|
739
740
|
{
|
|
740
741
|
operator: 'objectProperties',
|
|
741
742
|
property: 'user.name',
|
|
742
|
-
|
|
743
|
+
additionalData: {
|
|
743
744
|
operator: '?',
|
|
744
745
|
condition: { operator: '=', values: [{ operator: '+', values: [7, 8, 9] }, 25] },
|
|
745
746
|
valueIfTrue: { user: { name: 'Bilbo' } },
|
|
@@ -1177,8 +1178,8 @@ e.g.
|
|
|
1177
1178
|
},
|
|
1178
1179
|
}
|
|
1179
1180
|
// With:
|
|
1180
|
-
//
|
|
1181
|
-
//
|
|
1181
|
+
// data = { weather: "sunny", humidity: "high" } => "NO"
|
|
1182
|
+
// data = { weather: "rainy", wind: "weak" } => "YES"
|
|
1182
1183
|
|
|
1183
1184
|
```
|
|
1184
1185
|
|
|
@@ -1410,8 +1411,17 @@ Please open an issue: https://github.com/CarlosNZ/fig-tree-evaluator/issues
|
|
|
1410
1411
|
|
|
1411
1412
|
## Changelog
|
|
1412
1413
|
|
|
1414
|
+
- **v2.2.3**: Change option `objects` name to `data` (but keep backward compatibility) (#66)
|
|
1415
|
+
- **v2.2.2**: Option to evaluate whole object if operator nodes are deep within it (#64)
|
|
1416
|
+
- **v2.2.1**: More efficient branch evaluation for condition/match operators (#63)
|
|
1417
|
+
- **v2.2.0**:
|
|
1418
|
+
- New "[Match](#match) operator (#61)
|
|
1419
|
+
- Fix for regex incompatibility with Safari (#60)
|
|
1420
|
+
- **v2.1.5**: Demo updates (no changes to core evaluator)
|
|
1421
|
+
- **v2.1.4**: Upgrade dependencies
|
|
1422
|
+
- **v2.1.0**: [Alias nodes](#alias-nodes) (#57)
|
|
1413
1423
|
- **v2.0.4**: Backwards compatibility for customFunctions (#53)
|
|
1414
|
-
- **v2.0.1**: Add deep equality comparison for objects/
|
|
1424
|
+
- **v2.0.1**: Add deep equality comparison for objects/arrays in `=`/`!=` operators
|
|
1415
1425
|
- **v2.0.0**: Re-write as stand-alone package. Major improvements include:
|
|
1416
1426
|
- more [operators](#operator-reference)
|
|
1417
1427
|
- operator (and property) [aliases](#operator--property-aliases)
|
|
@@ -1421,7 +1431,7 @@ Please open an issue: https://github.com/CarlosNZ/fig-tree-evaluator/issues
|
|
|
1421
1431
|
- better error handling and error reporting
|
|
1422
1432
|
- more flexible output conversion
|
|
1423
1433
|
- more well-organised codebase
|
|
1424
|
-
- **v1.x.x**: created specifically for [Conforma](https://github.com/openmsupply/conforma-server/wiki/Query-Syntax) application manager by [mSupplyFoundation](https://github.com/openmsupply). v2 is a complete re-write with numerous
|
|
1434
|
+
- **v1.x.x**: created specifically for [Conforma](https://github.com/openmsupply/conforma-server/wiki/Query-Syntax) application manager by [mSupplyFoundation](https://github.com/openmsupply). v2 is a complete re-write with numerous improvements, but should be 99% backwards compatible.
|
|
1425
1435
|
|
|
1426
1436
|
|
|
1427
1437
|
## Credit
|
package/build/evaluate.js
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
2
13
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
14
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
15
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,57 +19,134 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
19
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
20
|
});
|
|
10
21
|
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
11
49
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
50
|
exports.evaluatorFunction = void 0;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
var _a, _b;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
51
|
+
var _operatorUtils_1 = require("./operators/_operatorUtils");
|
|
52
|
+
var helpers_1 = require("./helpers");
|
|
53
|
+
var evaluatorFunction = function (input, config) { return __awaiter(void 0, void 0, void 0, function () {
|
|
54
|
+
var options, operators, operatorAliases, expression, fallback, returnErrorAsString, operator, _a, _b, requiredProperties, propertyAliases, evaluate, parseChildren, _c, _d, validationError, _e, _f, _g, result, err_1, _h, outputType, evaluatedOutputType, _j, err_2, _k;
|
|
55
|
+
var _l, _m;
|
|
56
|
+
return __generator(this, function (_o) {
|
|
57
|
+
switch (_o.label) {
|
|
58
|
+
case 0:
|
|
59
|
+
options = config.options, operators = config.operators, operatorAliases = config.operatorAliases;
|
|
60
|
+
expression = (options === null || options === void 0 ? void 0 : options.allowJSONStringInput) ? (0, helpers_1.parseIfJson)(input) : input;
|
|
61
|
+
if (!Array.isArray(expression)) return [3, 2];
|
|
62
|
+
return [4, (0, _operatorUtils_1.evaluateArray)(expression, config)];
|
|
63
|
+
case 1:
|
|
64
|
+
expression = _o.sent();
|
|
65
|
+
_o.label = 2;
|
|
66
|
+
case 2:
|
|
67
|
+
if (!(options.evaluateFullObject && !(0, helpers_1.isOperatorNode)(expression))) return [3, 4];
|
|
68
|
+
return [4, (0, helpers_1.evaluateObject)(expression, config)];
|
|
69
|
+
case 3: return [2, _o.sent()];
|
|
70
|
+
case 4:
|
|
71
|
+
if (!(0, helpers_1.isOperatorNode)(expression))
|
|
72
|
+
return [2, (0, helpers_1.replaceAliasNodeValues)(expression, config)];
|
|
73
|
+
fallback = expression.fallback;
|
|
74
|
+
returnErrorAsString = (_l = options === null || options === void 0 ? void 0 : options.returnErrorAsString) !== null && _l !== void 0 ? _l : false;
|
|
75
|
+
_o.label = 5;
|
|
76
|
+
case 5:
|
|
77
|
+
_o.trys.push([5, 26, , 28]);
|
|
78
|
+
operator = (0, helpers_1.getOperatorName)(expression.operator, operatorAliases);
|
|
79
|
+
if (!!operator) return [3, 7];
|
|
80
|
+
_a = helpers_1.fallbackOrError;
|
|
81
|
+
return [4, (0, exports.evaluatorFunction)(fallback, config)];
|
|
82
|
+
case 6: return [2, _a.apply(void 0, [_o.sent(), "Invalid operator: ".concat(expression.operator), returnErrorAsString])];
|
|
83
|
+
case 7:
|
|
84
|
+
_b = operators[operator], requiredProperties = _b.requiredProperties, propertyAliases = _b.propertyAliases, evaluate = _b.evaluate, parseChildren = _b.parseChildren;
|
|
85
|
+
expression = (0, helpers_1.mapPropertyAliases)(propertyAliases, expression);
|
|
86
|
+
_c = config;
|
|
87
|
+
_d = [__assign({}, config.resolvedAliasNodes)];
|
|
88
|
+
return [4, (0, helpers_1.evaluateNodeAliases)(expression, config)];
|
|
89
|
+
case 8:
|
|
90
|
+
_c.resolvedAliasNodes = __assign.apply(void 0, _d.concat([(_o.sent())]));
|
|
91
|
+
validationError = (0, helpers_1.checkRequiredNodes)(requiredProperties, expression);
|
|
92
|
+
if (!validationError) return [3, 10];
|
|
93
|
+
_e = helpers_1.fallbackOrError;
|
|
94
|
+
return [4, (0, exports.evaluatorFunction)(fallback, config)];
|
|
95
|
+
case 9: return [2, _e.apply(void 0, [_o.sent(), "Operator: ".concat(operator, "\n- ").concat(validationError), returnErrorAsString])];
|
|
96
|
+
case 10:
|
|
97
|
+
if (!('children' in expression)) return [3, 16];
|
|
98
|
+
if (!!Array.isArray(expression.children)) return [3, 12];
|
|
99
|
+
_f = expression;
|
|
100
|
+
return [4, (0, exports.evaluatorFunction)(expression.children, config)];
|
|
101
|
+
case 11:
|
|
102
|
+
_f.children = _o.sent();
|
|
103
|
+
_o.label = 12;
|
|
104
|
+
case 12:
|
|
105
|
+
if (!!Array.isArray(expression.children)) return [3, 14];
|
|
106
|
+
_g = helpers_1.fallbackOrError;
|
|
107
|
+
return [4, (0, exports.evaluatorFunction)(fallback, config)];
|
|
108
|
+
case 13: return [2, _g.apply(void 0, [_o.sent(), "Operator: ".concat(operator, "\n- Property \"children\" is not of type: array"), returnErrorAsString])];
|
|
109
|
+
case 14: return [4, parseChildren(expression, config)];
|
|
110
|
+
case 15:
|
|
111
|
+
expression = _o.sent();
|
|
112
|
+
_o.label = 16;
|
|
113
|
+
case 16:
|
|
114
|
+
result = void 0;
|
|
115
|
+
_o.label = 17;
|
|
116
|
+
case 17:
|
|
117
|
+
_o.trys.push([17, 19, , 21]);
|
|
118
|
+
return [4, evaluate(expression, config)];
|
|
119
|
+
case 18:
|
|
120
|
+
result = _o.sent();
|
|
121
|
+
return [3, 21];
|
|
122
|
+
case 19:
|
|
123
|
+
err_1 = _o.sent();
|
|
124
|
+
_h = helpers_1.fallbackOrError;
|
|
125
|
+
return [4, (0, exports.evaluatorFunction)(fallback, config)];
|
|
126
|
+
case 20:
|
|
127
|
+
result = _h.apply(void 0, [_o.sent(), "Operator: ".concat(operator, "\n").concat((0, helpers_1.errorMessage)(err_1)), returnErrorAsString]);
|
|
128
|
+
return [3, 21];
|
|
129
|
+
case 21:
|
|
130
|
+
outputType = (_m = expression === null || expression === void 0 ? void 0 : expression.outputType) !== null && _m !== void 0 ? _m : expression === null || expression === void 0 ? void 0 : expression.type;
|
|
131
|
+
if (!outputType)
|
|
132
|
+
return [2, result];
|
|
133
|
+
return [4, (0, exports.evaluatorFunction)(outputType, config)];
|
|
134
|
+
case 22:
|
|
135
|
+
evaluatedOutputType = (_o.sent());
|
|
136
|
+
if (!!(evaluatedOutputType in helpers_1.convertOutputMethods)) return [3, 24];
|
|
137
|
+
_j = helpers_1.fallbackOrError;
|
|
138
|
+
return [4, (0, exports.evaluatorFunction)(fallback, config)];
|
|
139
|
+
case 23: return [2, _j.apply(void 0, [_o.sent(), "Operator: ".concat(operator, "\n- Invalid output type: ").concat(evaluatedOutputType), returnErrorAsString])];
|
|
140
|
+
case 24: return [2, helpers_1.convertOutputMethods[evaluatedOutputType](result)];
|
|
141
|
+
case 25: return [3, 28];
|
|
142
|
+
case 26:
|
|
143
|
+
err_2 = _o.sent();
|
|
144
|
+
_k = helpers_1.fallbackOrError;
|
|
145
|
+
return [4, (0, exports.evaluatorFunction)(fallback, config)];
|
|
146
|
+
case 27: return [2, _k.apply(void 0, [_o.sent(), (0, helpers_1.errorMessage)(err_2),
|
|
147
|
+
returnErrorAsString])];
|
|
148
|
+
case 28: return [2];
|
|
46
149
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
const outputType = (_b = expression === null || expression === void 0 ? void 0 : expression.outputType) !== null && _b !== void 0 ? _b : expression === null || expression === void 0 ? void 0 : expression.type;
|
|
51
|
-
if (!outputType)
|
|
52
|
-
return result;
|
|
53
|
-
const evaluatedOutputType = (yield (0, exports.evaluatorFunction)(outputType, config));
|
|
54
|
-
if (!(evaluatedOutputType in helpers_1.convertOutputMethods))
|
|
55
|
-
return (0, helpers_1.fallbackOrError)(yield (0, exports.evaluatorFunction)(fallback, config), `Operator: ${operator}\n- Invalid output type: ${evaluatedOutputType}`, returnErrorAsString);
|
|
56
|
-
else {
|
|
57
|
-
return helpers_1.convertOutputMethods[evaluatedOutputType](result);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
catch (err) {
|
|
61
|
-
return (0, helpers_1.fallbackOrError)(yield (0, exports.evaluatorFunction)(fallback, config), (0, helpers_1.errorMessage)(err), returnErrorAsString);
|
|
62
|
-
}
|
|
63
|
-
});
|
|
150
|
+
});
|
|
151
|
+
}); };
|
|
64
152
|
exports.evaluatorFunction = evaluatorFunction;
|
package/build/helpers.d.ts
CHANGED
|
@@ -19,3 +19,4 @@ export declare const convertOutputMethods: {
|
|
|
19
19
|
[key in OutputType]: (value: EvaluatorOutput) => EvaluatorOutput | EvaluatorOutput[];
|
|
20
20
|
};
|
|
21
21
|
export declare const errorMessage: (err: unknown) => string;
|
|
22
|
+
export declare const evaluateObject: (input: EvaluatorNode, config: FigTreeConfig) => Promise<EvaluatorOutput>;
|
package/build/helpers.js
CHANGED
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
2
13
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
14
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
15
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -8,16 +19,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
19
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
20
|
});
|
|
10
21
|
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
11
49
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.errorMessage = exports.convertOutputMethods = exports.mergeOptions = exports.checkRequiredNodes = exports.replaceAliasNodeValues = exports.evaluateNodeAliases = exports.mapPropertyAliases = exports.fallbackOrError = exports.truncateString = exports.getOperatorName = exports.isOperatorNode = exports.parseIfJson = void 0;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
50
|
+
exports.evaluateObject = exports.errorMessage = exports.convertOutputMethods = exports.mergeOptions = exports.checkRequiredNodes = exports.replaceAliasNodeValues = exports.evaluateNodeAliases = exports.mapPropertyAliases = exports.fallbackOrError = exports.truncateString = exports.getOperatorName = exports.isOperatorNode = exports.parseIfJson = void 0;
|
|
51
|
+
var change_case_1 = require("change-case");
|
|
52
|
+
var evaluate_1 = require("./evaluate");
|
|
53
|
+
var _operatorUtils_1 = require("./operators/_operatorUtils");
|
|
54
|
+
var parseIfJson = function (input) {
|
|
17
55
|
if (typeof input !== 'string')
|
|
18
56
|
return input;
|
|
19
57
|
try {
|
|
20
|
-
|
|
58
|
+
var parsedInput = JSON.parse(input);
|
|
21
59
|
return (0, exports.isOperatorNode)(parsedInput) ? parsedInput : input;
|
|
22
60
|
}
|
|
23
61
|
catch (err) {
|
|
@@ -25,17 +63,25 @@ const parseIfJson = (input) => {
|
|
|
25
63
|
}
|
|
26
64
|
};
|
|
27
65
|
exports.parseIfJson = parseIfJson;
|
|
28
|
-
|
|
66
|
+
var isOperatorNode = function (input) {
|
|
67
|
+
return input instanceof Object && 'operator' in input;
|
|
68
|
+
};
|
|
29
69
|
exports.isOperatorNode = isOperatorNode;
|
|
30
|
-
|
|
31
|
-
|
|
70
|
+
var standardiseOperatorName = function (name) {
|
|
71
|
+
var camelCaseName = (0, change_case_1.camelCase)(name);
|
|
32
72
|
return camelCaseName ? camelCaseName : name;
|
|
33
73
|
};
|
|
34
|
-
|
|
74
|
+
var getOperatorName = function (operator, operatorAliases) {
|
|
75
|
+
return operatorAliases[standardiseOperatorName(operator)];
|
|
76
|
+
};
|
|
35
77
|
exports.getOperatorName = getOperatorName;
|
|
36
|
-
|
|
78
|
+
var truncateString = function (string, length) {
|
|
79
|
+
if (length === void 0) { length = 200; }
|
|
80
|
+
return string.length < length ? string : "".concat(string.slice(0, length - 2).trim(), "...");
|
|
81
|
+
};
|
|
37
82
|
exports.truncateString = truncateString;
|
|
38
|
-
|
|
83
|
+
var fallbackOrError = function (fallback, errorMessage, returnErrorAsString) {
|
|
84
|
+
if (returnErrorAsString === void 0) { returnErrorAsString = false; }
|
|
39
85
|
if (fallback !== undefined)
|
|
40
86
|
return fallback;
|
|
41
87
|
if (returnErrorAsString)
|
|
@@ -44,65 +90,105 @@ const fallbackOrError = (fallback, errorMessage, returnErrorAsString = false) =>
|
|
|
44
90
|
throw new Error((0, exports.truncateString)(errorMessage));
|
|
45
91
|
};
|
|
46
92
|
exports.fallbackOrError = fallbackOrError;
|
|
47
|
-
|
|
93
|
+
var mapPropertyAliases = function (propertyAliases, expression) {
|
|
94
|
+
return mapObjectKeys(expression, function (key) {
|
|
95
|
+
return key in propertyAliases ? propertyAliases[key] : key;
|
|
96
|
+
});
|
|
97
|
+
};
|
|
48
98
|
exports.mapPropertyAliases = mapPropertyAliases;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
99
|
+
var mapObjectKeys = function (inputObj, mapFunction) {
|
|
100
|
+
var keyVals = Object.entries(inputObj);
|
|
101
|
+
var mappedKeys = keyVals.map(function (_a) {
|
|
102
|
+
var key = _a[0], value = _a[1];
|
|
103
|
+
return [mapFunction(key), value];
|
|
104
|
+
});
|
|
52
105
|
return Object.fromEntries(mappedKeys);
|
|
53
106
|
};
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
107
|
+
var isAliasString = function (value) { return /^\$.+/.test(value); };
|
|
108
|
+
var evaluateNodeAliases = function (expression, config) { return __awaiter(void 0, void 0, void 0, function () {
|
|
109
|
+
var aliasKeys, evaluations, _a, _b;
|
|
110
|
+
return __generator(this, function (_c) {
|
|
111
|
+
switch (_c.label) {
|
|
112
|
+
case 0:
|
|
113
|
+
aliasKeys = Object.keys(expression).filter(isAliasString);
|
|
114
|
+
if (aliasKeys.length === 0)
|
|
115
|
+
return [2, expression];
|
|
116
|
+
evaluations = [];
|
|
117
|
+
aliasKeys.forEach(function (alias) { return evaluations.push((0, evaluate_1.evaluatorFunction)(expression[alias], config)); });
|
|
118
|
+
_a = _operatorUtils_1.zipArraysToObject;
|
|
119
|
+
_b = [aliasKeys];
|
|
120
|
+
return [4, Promise.all(evaluations)];
|
|
121
|
+
case 1: return [2, _a.apply(void 0, _b.concat([_c.sent()]))];
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
}); };
|
|
63
125
|
exports.evaluateNodeAliases = evaluateNodeAliases;
|
|
64
|
-
|
|
65
|
-
var
|
|
126
|
+
var replaceAliasNodeValues = function (value, _a) {
|
|
127
|
+
var _b;
|
|
128
|
+
var resolvedAliasNodes = _a.resolvedAliasNodes;
|
|
66
129
|
if (typeof value !== 'string' || !isAliasString(value))
|
|
67
130
|
return value;
|
|
68
|
-
return (
|
|
131
|
+
return (_b = resolvedAliasNodes === null || resolvedAliasNodes === void 0 ? void 0 : resolvedAliasNodes[value]) !== null && _b !== void 0 ? _b : value;
|
|
69
132
|
};
|
|
70
133
|
exports.replaceAliasNodeValues = replaceAliasNodeValues;
|
|
71
|
-
|
|
72
|
-
|
|
134
|
+
var checkRequiredNodes = function (requiredProps, expression) {
|
|
135
|
+
var missingProps = requiredProps.filter(function (prop) { return !(prop in expression); });
|
|
73
136
|
if (missingProps.length === 0)
|
|
74
137
|
return false;
|
|
75
138
|
if (!('children' in expression))
|
|
76
|
-
return
|
|
139
|
+
return "Missing properties: ".concat(missingProps);
|
|
77
140
|
return false;
|
|
78
141
|
};
|
|
79
142
|
exports.checkRequiredNodes = checkRequiredNodes;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (origOptions.
|
|
83
|
-
combinedOptions.
|
|
143
|
+
var mergeOptions = function (origOptions, newOptions) {
|
|
144
|
+
var combinedOptions = __assign(__assign({}, origOptions), newOptions);
|
|
145
|
+
if (origOptions.data || newOptions.data)
|
|
146
|
+
combinedOptions.data = __assign(__assign({}, origOptions.data), newOptions.data);
|
|
84
147
|
if (origOptions.functions || newOptions.functions)
|
|
85
|
-
combinedOptions.functions =
|
|
148
|
+
combinedOptions.functions = __assign(__assign({}, origOptions.functions), newOptions.functions);
|
|
86
149
|
if (origOptions.headers || newOptions.headers)
|
|
87
|
-
combinedOptions.headers =
|
|
150
|
+
combinedOptions.headers = __assign(__assign({}, origOptions.headers), newOptions.headers);
|
|
88
151
|
return combinedOptions;
|
|
89
152
|
};
|
|
90
153
|
exports.mergeOptions = mergeOptions;
|
|
91
154
|
exports.convertOutputMethods = {
|
|
92
|
-
number: (value)
|
|
93
|
-
string: (value)
|
|
94
|
-
array: (value)
|
|
95
|
-
boolean: (value)
|
|
96
|
-
bool: (value)
|
|
155
|
+
number: function (value) { return extractNumber(value); },
|
|
156
|
+
string: function (value) { return String(value); },
|
|
157
|
+
array: function (value) { return (Array.isArray(value) ? value : [value]); },
|
|
158
|
+
boolean: function (value) { return Boolean(value); },
|
|
159
|
+
bool: function (value) { return Boolean(value); },
|
|
97
160
|
};
|
|
98
|
-
|
|
161
|
+
var errorMessage = function (err) { return err.message; };
|
|
99
162
|
exports.errorMessage = errorMessage;
|
|
100
|
-
|
|
163
|
+
var extractNumber = function (input) {
|
|
101
164
|
if (typeof input !== 'string')
|
|
102
165
|
return Number.isNaN(Number(input)) ? input : Number(input);
|
|
103
|
-
|
|
104
|
-
|
|
166
|
+
var pattern = new RegExp(/-?\d*\.?\d+/gm);
|
|
167
|
+
var numberMatch = input.match(pattern);
|
|
105
168
|
if (!numberMatch)
|
|
106
169
|
return 0;
|
|
107
170
|
return Number(numberMatch[0]);
|
|
108
171
|
};
|
|
172
|
+
var isObject = function (input) {
|
|
173
|
+
return typeof input === 'object' && input !== null && !Array.isArray(input);
|
|
174
|
+
};
|
|
175
|
+
var evaluateObject = function (input, config) { return __awaiter(void 0, void 0, void 0, function () {
|
|
176
|
+
var newObjectEntries, result;
|
|
177
|
+
return __generator(this, function (_a) {
|
|
178
|
+
switch (_a.label) {
|
|
179
|
+
case 0:
|
|
180
|
+
if (!isObject(input))
|
|
181
|
+
return [2, input];
|
|
182
|
+
newObjectEntries = [];
|
|
183
|
+
Object.entries(input).forEach(function (_a) {
|
|
184
|
+
var key = _a[0], value = _a[1];
|
|
185
|
+
return newObjectEntries.push(key, (0, evaluate_1.evaluatorFunction)(value, config));
|
|
186
|
+
});
|
|
187
|
+
return [4, Promise.all(newObjectEntries)];
|
|
188
|
+
case 1:
|
|
189
|
+
result = _a.sent();
|
|
190
|
+
return [2, (0, _operatorUtils_1.singleArrayToObject)(result)];
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
}); };
|
|
194
|
+
exports.evaluateObject = evaluateObject;
|