fig-tree-evaluator 1.9.4 → 2.0.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.
package/README.md CHANGED
@@ -47,6 +47,8 @@ A range of built-in operators are available, from simple logic, arithmetic and s
47
47
  - [Development environment](#development-environment)
48
48
  - [Tests](#tests)
49
49
  - [Help, Feedback, Suggestions](#help-feedback-suggestions)
50
+ - [Changelog](#changelog)
51
+ - [Credit](#credit)
50
52
 
51
53
  <!-- /TOC -->
52
54
  ## The basics
@@ -138,6 +140,7 @@ The `options` parameter is an object with the following available properties (al
138
140
  - `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)
139
141
  - `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.
140
142
  - `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 encoutered (e.g. trying to pass a primitive value when an array is expected => `.map is not a function`)
143
+ - `nullEqualsUndefined` -- this only affects the [`equal`/`notEqual` operators](#equal) (see there for more detail).
141
144
 
142
145
  As mentioned above, `options` can be provided as part of the constructor as part of each seperate evaluation. You can also change the options permanently for a given evaluator instance with:
143
146
 
@@ -295,7 +298,8 @@ Aliases: `=`, `eq`, `equal`, `equals`
295
298
 
296
299
  #### Properties
297
300
 
298
- - `values`<sup>*</sup>: (array) -- any number of elements; will be compared using Javascript `==` operator
301
+ - `values`<sup>*</sup>: (array) -- any number of elements; will be compared for strict equality. This includes simple types as well as deep equality of objects and arrays.
302
+ - `nullEqualsUndefined`: (boolean, default `false`) -- there are times when it is convenient for `null` to be considered equal to `undefined`. If this is desiered, set this property to `true`, otherwise all equality checks will be "strict" equality. If you find that you want this setting enabled globally, then you can set it in the overall [evaluator options](#available-options) instead of having to add this additional property to every equality expression.
299
303
 
300
304
  e.g.
301
305
  ```js
@@ -317,7 +321,8 @@ Aliases: `!=`, `!`, `ne`, `notEqual`
317
321
 
318
322
  #### Properties
319
323
 
320
- - `values`<sup>*</sup>: (array) -- any number of elements; will be compared using Javascript `!=` operator
324
+ - `values`<sup>*</sup>: (array) -- any number of elements; will be compared for inequality. This includes simple types as well as deep comparison of objects and arrays.
325
+ - `nullEqualsUndefined`: (boolean, default `false`) -- as [above](#equal)
321
326
 
322
327
  e.g.
323
328
  ```js
@@ -1227,6 +1232,8 @@ After cloning:
1227
1232
 
1228
1233
  `yarn demo` -- launch a local version of the demo playground in your browser for building and testing expressions
1229
1234
 
1235
+ `yarn dev` -- execute anything in `/dev/playground.ts`. Use for testing/debugging.
1236
+
1230
1237
  ## Tests
1231
1238
 
1232
1239
  There is a comprehensive [Jest](https://jestjs.io/) test suite for all aspects of fig-tree. To run all tests:
@@ -1239,4 +1246,23 @@ Individual tests can be run by string matching the argument to the test filename
1239
1246
 
1240
1247
  ## Help, Feedback, Suggestions
1241
1248
 
1242
- Please open an issue: https://github.com/CarlosNZ/fig-tree-evaluator/issues
1249
+ Please open an issue: https://github.com/CarlosNZ/fig-tree-evaluator/issues
1250
+
1251
+ ## Changelog
1252
+
1253
+
1254
+ - **v2.0.1**: Add deep equality comparison for objects/arrayr in =/!= operators
1255
+ - **v2.0.0**: Re-write as stand-alone package. Major improvements include:
1256
+ - more [operators](#operator-reference)
1257
+ - operator (and property) [aliases](#operator--property-aliases)
1258
+ - more appropriately-named properties associated with each operator (as opposed to a single `children` array)
1259
+ - class-based Evaluator instances
1260
+ - runtime type-checking
1261
+ - better error handling and error reporting
1262
+ - more flexible output conversion
1263
+ - more well-organised codebase
1264
+ - **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 improvments, but should be 99% backwards compatible.
1265
+
1266
+
1267
+ ## Credit
1268
+ Icon: Tree by ka reemov from <a href="https://thenounproject.com/icon/tree-2665898/" target="_blank" title="Tree Icon">Noun Project</a>
@@ -12,13 +12,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.EQUAL = void 0;
13
13
  const logicalAnd_1 = require("./logicalAnd");
14
14
  const _operatorUtils_1 = require("./_operatorUtils");
15
+ const lite_1 = require("dequal/lite");
15
16
  const requiredProperties = ['values'];
16
17
  const operatorAliases = ['=', 'eq', 'equal', 'equals'];
17
18
  const propertyAliases = {};
18
19
  const evaluate = (expression, config) => __awaiter(void 0, void 0, void 0, function* () {
19
- const values = (yield (0, _operatorUtils_1.evaluateArray)(expression.values, config));
20
+ var _a;
21
+ const [values, nullMatch] = (yield (0, _operatorUtils_1.evaluateArray)([expression.values, expression.nullEqualsUndefined], config));
20
22
  config.typeChecker({ name: 'values', value: values, expectedType: 'array' });
21
- return values.every((value) => value == values[0]);
23
+ const nullEqualsUndefined = nullMatch !== undefined
24
+ ? nullMatch
25
+ : ((_a = config.options) === null || _a === void 0 ? void 0 : _a.nullEqualsUndefined) !== undefined
26
+ ? config.options.nullEqualsUndefined
27
+ : false;
28
+ if (nullEqualsUndefined && (values[0] === null || values[0] === undefined))
29
+ return values.every((value) => value === null || value === undefined);
30
+ return values.every((value) => (0, lite_1.dequal)(value, values[0]));
22
31
  });
23
32
  exports.EQUAL = {
24
33
  requiredProperties,
@@ -12,13 +12,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.NOT_EQUAL = void 0;
13
13
  const logicalAnd_1 = require("./logicalAnd");
14
14
  const _operatorUtils_1 = require("./_operatorUtils");
15
+ const lite_1 = require("dequal/lite");
15
16
  const requiredProperties = ['values'];
16
17
  const operatorAliases = ['!=', '!', 'ne', 'notEqual'];
17
18
  const propertyAliases = {};
18
19
  const evaluate = (expression, config) => __awaiter(void 0, void 0, void 0, function* () {
19
- const values = (yield (0, _operatorUtils_1.evaluateArray)(expression.values, config));
20
+ var _a;
21
+ const [values, nullMatch] = (yield (0, _operatorUtils_1.evaluateArray)([expression.values, expression.nullEqualsUndefined], config));
20
22
  config.typeChecker({ name: 'values', value: values, expectedType: 'array' });
21
- return values.some((val) => val !== values[0]);
23
+ const nullEqualsUndefined = nullMatch !== undefined
24
+ ? nullMatch
25
+ : ((_a = config.options) === null || _a === void 0 ? void 0 : _a.nullEqualsUndefined) !== undefined
26
+ ? config.options.nullEqualsUndefined
27
+ : false;
28
+ if (nullEqualsUndefined && (values[0] === null || values[0] === undefined))
29
+ return values.some((value) => value === null && value === undefined);
30
+ return values.some((val) => !(0, lite_1.dequal)(val, values[0]));
22
31
  });
23
32
  exports.NOT_EQUAL = {
24
33
  requiredProperties,
package/build/types.d.ts CHANGED
@@ -17,6 +17,7 @@ export interface FigTreeOptions {
17
17
  [key: string]: string;
18
18
  };
19
19
  returnErrorAsString?: boolean;
20
+ nullEqualsUndefined?: boolean;
20
21
  allowJSONStringInput?: boolean;
21
22
  skipRuntimeTypeCheck?: boolean;
22
23
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fig-tree-evaluator",
3
- "version": "1.9.4",
3
+ "version": "2.0.1",
4
4
  "description": "Module to evaluate JSON-structured expression trees",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -35,6 +35,7 @@
35
35
  "dependencies": {
36
36
  "axios": "^0.27.2",
37
37
  "change-case": "^4.1.2",
38
+ "dequal": "^2.0.3",
38
39
  "object-property-extractor": "^1.0.3"
39
40
  },
40
41
  "bugs": {