fig-tree-evaluator 2.5.2 → 2.7.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/README.md +3 -0
- package/build/FigTreeEvaluator.js +9 -3
- package/build/evaluate.js +2 -0
- package/build/helpers.d.ts +28 -4
- package/build/helpers.js +26 -4
- package/build/types.d.ts +5 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -157,6 +157,7 @@ The `options` parameter is an object with the following available properties (al
|
|
|
157
157
|
- `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`)
|
|
158
158
|
- `nullEqualsUndefined` -- this only affects the [`equal`/`notEqual` operators](#equal) (see there for more detail).
|
|
159
159
|
- `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 within the object tree.
|
|
160
|
+
- `excludeOperators` -- an array of operator names (or [aliases](#operator--property-aliases)) to prohibit from being used in expressions. You may wish to restrict (for example) database access via FigTree configurations, in which case these exclusions can be defined when instantiating the FigTree instance (or updated on the fly).
|
|
160
161
|
- `useCache` -- caches the results from certain operators to avoid repeated network requests with the same input values. By default, this is set to `true`, and it can be overridden for specific nodes. See [Memoization/Caching section](#caching-memoization) for more detail
|
|
161
162
|
- `maxCacheSize` -- the maximum number of results that will be held in the aforementioned cache (default: `50`)
|
|
162
163
|
|
|
@@ -1510,6 +1511,8 @@ Please open an issue: https://github.com/CarlosNZ/fig-tree-evaluator/issues
|
|
|
1510
1511
|
|
|
1511
1512
|
*Trivial upgrades (e.g. documentation, small re-factors, types, etc.) not included*
|
|
1512
1513
|
|
|
1514
|
+
- **v2.7.0**: Add `excludeOperators` option to allow certain operators to be prohibited (e.g. database lookups) (#54)
|
|
1515
|
+
- **v2.6.0**: Resolve alias nodes that are not part of an Operator node when `evaluateFullObject` is enabled (#78)
|
|
1513
1516
|
- **v2.5.0**:
|
|
1514
1517
|
- Bug fixes for edge cases (mainly related to backwards compatibility)
|
|
1515
1518
|
- More backwards compatibility for very old (pre-v1) syntax (undocumented)
|
|
@@ -43,8 +43,10 @@ const operators = __importStar(require("./operators"));
|
|
|
43
43
|
const helpers_1 = require("./helpers");
|
|
44
44
|
const cache_1 = __importDefault(require("./cache"));
|
|
45
45
|
const pkg = require('../package.json');
|
|
46
|
+
const operatorAliases = _operatorAliases_json_1.default;
|
|
46
47
|
class FigTreeEvaluator {
|
|
47
48
|
constructor(options = {}) {
|
|
49
|
+
var _a, _b;
|
|
48
50
|
this.typeChecker = (...args) => {
|
|
49
51
|
const result = (0, typeCheck_1.typeCheck)(...args);
|
|
50
52
|
if (result === true)
|
|
@@ -53,8 +55,8 @@ class FigTreeEvaluator {
|
|
|
53
55
|
};
|
|
54
56
|
this.getVersion = () => pkg.version;
|
|
55
57
|
this.options = standardiseOptionNames(options);
|
|
56
|
-
this.operators = operators;
|
|
57
|
-
this.operatorAliases =
|
|
58
|
+
this.operators = (0, helpers_1.filterOperators)(operators, (_b = (_a = this.options) === null || _a === void 0 ? void 0 : _a.excludeOperators) !== null && _b !== void 0 ? _b : [], operatorAliases);
|
|
59
|
+
this.operatorAliases = operatorAliases;
|
|
58
60
|
this.cache = new cache_1.default(options.maxCacheSize);
|
|
59
61
|
}
|
|
60
62
|
evaluate(expression, options = {}) {
|
|
@@ -64,7 +66,9 @@ class FigTreeEvaluator {
|
|
|
64
66
|
this.cache.setMax(currentOptions.maxCacheSize);
|
|
65
67
|
return yield (0, evaluate_1.evaluatorFunction)(expression, {
|
|
66
68
|
options: currentOptions,
|
|
67
|
-
operators:
|
|
69
|
+
operators: options.excludeOperators
|
|
70
|
+
? (0, helpers_1.filterOperators)(operators, options.excludeOperators, operatorAliases)
|
|
71
|
+
: this.operators,
|
|
68
72
|
operatorAliases: this.operatorAliases,
|
|
69
73
|
typeChecker: currentOptions.skipRuntimeTypeCheck ? () => { } : this.typeChecker,
|
|
70
74
|
resolvedAliasNodes: {},
|
|
@@ -77,6 +81,8 @@ class FigTreeEvaluator {
|
|
|
77
81
|
}
|
|
78
82
|
updateOptions(options) {
|
|
79
83
|
this.options = (0, helpers_1.mergeOptions)(this.options, standardiseOptionNames(options));
|
|
84
|
+
if (this.options.excludeOperators)
|
|
85
|
+
this.operators = (0, helpers_1.filterOperators)(operators, this.options.excludeOperators, operatorAliases);
|
|
80
86
|
}
|
|
81
87
|
}
|
|
82
88
|
exports.default = FigTreeEvaluator;
|
package/build/evaluate.js
CHANGED
|
@@ -45,6 +45,8 @@ const evaluatorFunction = (input, config) => __awaiter(void 0, void 0, void 0, f
|
|
|
45
45
|
const operator = (0, helpers_1.getOperatorName)(expression.operator, operatorAliases);
|
|
46
46
|
if (!operator)
|
|
47
47
|
return (0, helpers_1.fallbackOrError)(yield (0, exports.evaluatorFunction)(fallback, config), `Invalid operator: ${expression.operator}`, returnErrorAsString);
|
|
48
|
+
if (!config.operators[operator])
|
|
49
|
+
return (0, helpers_1.fallbackOrError)(yield (0, exports.evaluatorFunction)(fallback, config), `Excluded operator: ${expression.operator}`, returnErrorAsString);
|
|
48
50
|
const { requiredProperties, propertyAliases, evaluate, parseChildren } = operators[operator];
|
|
49
51
|
expression = (0, helpers_1.mapPropertyAliases)(propertyAliases, expression);
|
|
50
52
|
config.resolvedAliasNodes = Object.assign(Object.assign({}, config.resolvedAliasNodes), (yield (0, helpers_1.evaluateNodeAliases)(expression, config)));
|
package/build/helpers.d.ts
CHANGED
|
@@ -1,10 +1,34 @@
|
|
|
1
|
-
import { OutputType, EvaluatorNode, CombinedOperatorNode,
|
|
1
|
+
import { OutputType, EvaluatorNode, CombinedOperatorNode, EvaluatorOutput, FigTreeOptions, OperatorNodeUnion, FigTreeConfig, OperatorReference, OperatorAliases } from './types';
|
|
2
2
|
export declare const parseIfJson: (input: EvaluatorNode) => any;
|
|
3
3
|
export declare const isOperatorNode: (input: EvaluatorNode) => boolean;
|
|
4
4
|
export declare const isFragmentNode: (input: EvaluatorNode) => boolean;
|
|
5
|
-
export declare const getOperatorName: (operator: string, operatorAliases:
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
export declare const getOperatorName: (operator: string, operatorAliases: OperatorAliases) => "AND" | "OR" | "EQUAL" | "NOT_EQUAL" | "PLUS" | "SUBTRACT" | "MULTIPLY" | "DIVIDE" | "GREATER_THAN" | "LESS_THAN" | "CONDITIONAL" | "REGEX" | "OBJECT_PROPERTIES" | "STRING_SUBSTITUTION" | "SPLIT" | "COUNT" | "GET" | "POST" | "PG_SQL" | "GRAPHQL" | "BUILD_OBJECT" | "MATCH" | "CUSTOM_FUNCTIONS" | "PASSTHRU";
|
|
6
|
+
export declare const filterOperators: (operators: OperatorReference, exclusions: string[], operatorAliases: OperatorAliases) => {
|
|
7
|
+
AND: import("./types").OperatorObject;
|
|
8
|
+
OR: import("./types").OperatorObject;
|
|
9
|
+
EQUAL: import("./types").OperatorObject;
|
|
10
|
+
NOT_EQUAL: import("./types").OperatorObject;
|
|
11
|
+
PLUS: import("./types").OperatorObject;
|
|
12
|
+
SUBTRACT: import("./types").OperatorObject;
|
|
13
|
+
MULTIPLY: import("./types").OperatorObject;
|
|
14
|
+
DIVIDE: import("./types").OperatorObject;
|
|
15
|
+
GREATER_THAN: import("./types").OperatorObject;
|
|
16
|
+
LESS_THAN: import("./types").OperatorObject;
|
|
17
|
+
CONDITIONAL: import("./types").OperatorObject;
|
|
18
|
+
REGEX: import("./types").OperatorObject;
|
|
19
|
+
OBJECT_PROPERTIES: import("./types").OperatorObject;
|
|
20
|
+
STRING_SUBSTITUTION: import("./types").OperatorObject;
|
|
21
|
+
SPLIT: import("./types").OperatorObject;
|
|
22
|
+
COUNT: import("./types").OperatorObject;
|
|
23
|
+
GET: import("./types").OperatorObject;
|
|
24
|
+
POST: import("./types").OperatorObject;
|
|
25
|
+
PG_SQL: import("./types").OperatorObject;
|
|
26
|
+
GRAPHQL: import("./types").OperatorObject;
|
|
27
|
+
BUILD_OBJECT: import("./types").OperatorObject;
|
|
28
|
+
MATCH: import("./types").OperatorObject;
|
|
29
|
+
CUSTOM_FUNCTIONS: import("./types").OperatorObject;
|
|
30
|
+
PASSTHRU: import("./types").OperatorObject;
|
|
31
|
+
};
|
|
8
32
|
export declare const truncateString: (string: string, length?: number) => string;
|
|
9
33
|
export declare const fallbackOrError: (fallback: any, errorMessage: string, returnErrorAsString?: boolean) => any;
|
|
10
34
|
export declare const mapPropertyAliases: (propertyAliases: {
|
package/build/helpers.js
CHANGED
|
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.evaluateObject = exports.isObject = exports.errorMessage = exports.convertOutputMethods = exports.mergeOptions = exports.checkRequiredNodes = exports.replaceAliasNodeValues = exports.evaluateNodeAliases = exports.mapPropertyAliases = exports.fallbackOrError = exports.truncateString = exports.getOperatorName = exports.isFragmentNode = exports.isOperatorNode = exports.parseIfJson = void 0;
|
|
12
|
+
exports.evaluateObject = exports.isObject = exports.errorMessage = exports.convertOutputMethods = exports.mergeOptions = exports.checkRequiredNodes = exports.replaceAliasNodeValues = exports.evaluateNodeAliases = exports.mapPropertyAliases = exports.fallbackOrError = exports.truncateString = exports.filterOperators = exports.getOperatorName = exports.isFragmentNode = exports.isOperatorNode = exports.parseIfJson = void 0;
|
|
13
13
|
const change_case_1 = require("change-case");
|
|
14
14
|
const evaluate_1 = require("./evaluate");
|
|
15
15
|
const _operatorUtils_1 = require("./operators/_operatorUtils");
|
|
@@ -35,6 +35,17 @@ const standardiseOperatorName = (name) => {
|
|
|
35
35
|
};
|
|
36
36
|
const getOperatorName = (operator, operatorAliases) => operatorAliases[standardiseOperatorName(operator)];
|
|
37
37
|
exports.getOperatorName = getOperatorName;
|
|
38
|
+
const filterOperators = (operators, exclusions, operatorAliases) => {
|
|
39
|
+
const filteredOperators = Object.assign({}, operators);
|
|
40
|
+
exclusions.forEach((exclusion) => {
|
|
41
|
+
const operator = operatorAliases[standardiseOperatorName(exclusion)];
|
|
42
|
+
if (!operator)
|
|
43
|
+
console.warn(`Invalid operator exclusion: ${exclusion}`);
|
|
44
|
+
delete filteredOperators[operatorAliases[standardiseOperatorName(exclusion)]];
|
|
45
|
+
});
|
|
46
|
+
return filteredOperators;
|
|
47
|
+
};
|
|
48
|
+
exports.filterOperators = filterOperators;
|
|
38
49
|
const truncateString = (string, length = 200) => string.length < length ? string : `${string.slice(0, length - 2).trim()}...`;
|
|
39
50
|
exports.truncateString = truncateString;
|
|
40
51
|
const fallbackOrError = (fallback, errorMessage, returnErrorAsString = false) => {
|
|
@@ -116,8 +127,19 @@ const evaluateObject = (input, config) => __awaiter(void 0, void 0, void 0, func
|
|
|
116
127
|
if (!(0, exports.isObject)(input))
|
|
117
128
|
return input;
|
|
118
129
|
const newObjectEntries = [];
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
130
|
+
const newAliases = [];
|
|
131
|
+
Object.entries(input).forEach(([key, value]) => {
|
|
132
|
+
if (isAliasString(key)) {
|
|
133
|
+
newAliases.push(key, (0, evaluate_1.evaluatorFunction)(value, config));
|
|
134
|
+
delete input[key];
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
const aliasArray = yield Promise.all(newAliases);
|
|
138
|
+
config.resolvedAliasNodes = Object.assign(Object.assign({}, config.resolvedAliasNodes), (0, _operatorUtils_1.singleArrayToObject)(aliasArray));
|
|
139
|
+
Object.entries(input).forEach(([key, value]) => {
|
|
140
|
+
newObjectEntries.push(key, (0, evaluate_1.evaluatorFunction)(value, config));
|
|
141
|
+
});
|
|
142
|
+
const results = yield Promise.all(newObjectEntries);
|
|
143
|
+
return (0, exports.replaceAliasNodeValues)((0, _operatorUtils_1.singleArrayToObject)(results), config);
|
|
122
144
|
});
|
|
123
145
|
exports.evaluateObject = evaluateObject;
|
package/build/types.d.ts
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import FigTreeCache from './cache';
|
|
2
2
|
import { BasicExtendedNode, SubtractionNode, DivisionNode, ComparatorNode, ConditionalNode, RegexNode, StringSubNode, SplitNode, ObjPropNode, APINode, PGNode, GraphQLNode, BuildObjectNode, MatchNode, FunctionNode, PassThruNode, PGConnection, GraphQLConnection } from './operators';
|
|
3
|
+
import operatorAliases from './operators/_operatorAliases.json';
|
|
3
4
|
import { TypeCheckInput } from './typeCheck';
|
|
4
5
|
export declare const Operators: readonly ["AND", "OR", "EQUAL", "NOT_EQUAL", "PLUS", "SUBTRACT", "MULTIPLY", "DIVIDE", "GREATER_THAN", "LESS_THAN", "CONDITIONAL", "REGEX", "OBJECT_PROPERTIES", "STRING_SUBSTITUTION", "SPLIT", "COUNT", "GET", "POST", "PG_SQL", "GRAPHQL", "BUILD_OBJECT", "MATCH", "CUSTOM_FUNCTIONS", "PASSTHRU"];
|
|
5
6
|
export type Operator = typeof Operators[number];
|
|
6
7
|
export type GenericObject = {
|
|
7
8
|
[key: string]: any;
|
|
8
9
|
};
|
|
10
|
+
export type OperatorAlias = keyof typeof operatorAliases;
|
|
11
|
+
export type OperatorAliases = Record<OperatorAlias, Operator>;
|
|
9
12
|
export interface FigTreeOptions {
|
|
10
13
|
data?: GenericObject;
|
|
11
14
|
objects?: GenericObject;
|
|
@@ -26,6 +29,7 @@ export interface FigTreeOptions {
|
|
|
26
29
|
allowJSONStringInput?: boolean;
|
|
27
30
|
skipRuntimeTypeCheck?: boolean;
|
|
28
31
|
evaluateFullObject?: boolean;
|
|
32
|
+
excludeOperators?: string[];
|
|
29
33
|
useCache?: boolean;
|
|
30
34
|
maxCacheSize?: number;
|
|
31
35
|
supportDeprecatedValueNodes?: boolean;
|
|
@@ -33,9 +37,7 @@ export interface FigTreeOptions {
|
|
|
33
37
|
export interface FigTreeConfig {
|
|
34
38
|
options: FigTreeOptions;
|
|
35
39
|
operators: OperatorReference;
|
|
36
|
-
operatorAliases:
|
|
37
|
-
[key: string]: Operator;
|
|
38
|
-
};
|
|
40
|
+
operatorAliases: OperatorAliases;
|
|
39
41
|
typeChecker: (...input: TypeCheckInput[]) => void;
|
|
40
42
|
resolvedAliasNodes: {
|
|
41
43
|
[key: string]: EvaluatorOutput;
|