fig-tree-evaluator 2.8.6 → 2.10.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 CHANGED
@@ -115,9 +115,9 @@ A playground for building and testing expressions is available [here](https://ca
115
115
 
116
116
  ## Install
117
117
 
118
- `npm install fig-tree`\
118
+ `npm install fig-tree-evaluator`\
119
119
  or\
120
- `yarn add fig-tree`
120
+ `yarn add fig-tree-evaluator`
121
121
 
122
122
  ## Usage
123
123
 
@@ -162,6 +162,7 @@ The `options` parameter is an object with the following available properties (al
162
162
  - `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).
163
163
  - `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
164
164
  - `maxCacheSize` -- the maximum number of results that will be held in the aforementioned cache (default: `50`)
165
+ - `maxCacheTime` -- the maximum time (in seconds) that a result will be cached since last access (default: `1800` (30 minutes))
165
166
  - `noShorthand` -- there is a [shorthand syntax](#shorthand-syntax) available for writing expressions. Internally, this is pre-processed into the standard expression form before evaluation. If you have no use for this and you'd rather all expressions were written with full verbosity, set `noShorthand: true` to save a small amount in performance by skipping internal pre-processing.
166
167
 
167
168
  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:
@@ -775,14 +776,21 @@ Example using "data" passed in dynamically as part of expression:
775
776
  ----
776
777
  ### STRING_SUBSTITUTION
777
778
 
778
- *Replace values in a string using simple parameter substitution*
779
+ *Replace values in a string using simple parameter (positional or named properties) substitution*
779
780
 
780
781
  Aliases: `stringSubstitution`, `substitute`, `stringSub`, `replace`
781
782
 
782
783
  #### Properties
783
784
 
784
785
  - `string`<sup>*</sup>: (string) -- a parameterized (`%1`, `%2`) string, where the parameters are to be replaced by dynamic values. E.g. `"My name is %1 (age %2)"`
785
- - `substitutions` (or `replacements`)<sup>*</sup>: (array) -- the values to be substituted into `string`
786
+ - `substitutions` (or `replacements`, `values`)<sup>*</sup>: (array | object) -- the values to be substituted into `string`. Will be either an array or object depending on whether you're using positional replacements or named properties (see [below](#positional-replacement)).
787
+ - `trimWhiteSpace` (or `trimWhitespace`, `trim`): (boolean, default `true`) -- strips whitespace from the beginning or end of the substitution values
788
+ - `substitutionCharacter` (or `subCharacter`, `subChar`): (`"%"` or `"$"`) -- by default, when using positional replacement, it looks for the `%` token (i.e `%1, %2, etc`), but this can be changed to `$` (i.e. `$1, $2, $3, etc`) by setting this property to `$`.
789
+ - `numberMapping` (or `numMap`, `numberMap`, `pluralisation`, `pluralization`, `plurals`): (object) -- when replacing with named properties and you have replacement values that are numbers, it's possible to map values or ranges to specific string outputs. This can be used to produce correct pluralisation, for example. [See below](#named-property-replacement) for more details.
790
+
791
+ Substitution can be done using either **positional** replacement, or with **named properties**:
792
+
793
+ #### Positional replacement
786
794
 
787
795
  The values in the `substitutions` array are replaced in the original `string` by matching their order to the numerical order of the parameters.
788
796
 
@@ -803,7 +811,9 @@ e.g.
803
811
 
804
812
  {
805
813
  operator: 'replace',
806
- string: '%1 is actually %2 %3',
814
+ // Using $1, $2 instead of %1, %2 this time:
815
+ string: '$1 is actually $2 $3',
816
+ substitutionCharacter: "$",
807
817
  substitutions: [
808
818
  // Using the 'user' object from above (OBJECT_PROPERTIES operator)
809
819
  {
@@ -829,9 +839,19 @@ e.g.
829
839
  substitutions: ['bird', 'Tweet!'],
830
840
  }
831
841
  // => 'A bird says: "Tweet! Tweet! Tweet!"'
842
+
843
+ // Replacement tokens can be escaped using the standard "\" escape character:
844
+ {
845
+ operator: 'stringSubstitution',
846
+ string: 'The price of $1 is \$5',
847
+ subChar: '$',
848
+ substitutions: [ 'a coffee', 'not used' ],
849
+ }
850
+ // => The price of a coffee is $5
832
851
  ```
833
852
 
834
- `children` array: `[string, ...substitutions]`
853
+ `children` array: `[string, ...substitutions]`
854
+ (`trimWhiteSpace` and `substitutionCharacter` not available, since `substitutions` can be an arbitrary number of items)
835
855
 
836
856
  e.g.
837
857
  ```js
@@ -842,6 +862,77 @@ e.g.
842
862
  // => "I am Iron Man"
843
863
  ```
844
864
 
865
+ #### Named property replacement
866
+
867
+ Replacement tokens can be indicated in the main string with a named value, using `{{<name>}}` syntax, e.g. `"Your name is {{firstName}} {{lastName}}"`. Then the `substitutions` property must be an object with those property names:
868
+
869
+ ```js
870
+ {
871
+ operator: 'stringSubstitution',
872
+ string: 'Your name is {{firstName}} {{lastName}}',
873
+ substitutions: {
874
+ firstName: 'Steve',
875
+ lastName: "Rogers"
876
+ }
877
+ }
878
+ // => "Your name is Steve Rogers"
879
+ ```
880
+
881
+ If the replacement values are numbers, we can extend this functionality with a special `numberMapping` object, which allows for different replacements depending on the value, which is handy for pluralisation, for example.
882
+
883
+ The syntax for the `numberMapping` property is:
884
+ ```js
885
+ {
886
+ propertyName1: {
887
+ 1: "Output if value is {}",
888
+ 2: "Output if value is 2",
889
+ ">5": "Output if value is greater than 5",
890
+ "<0": "Output if value is less than 0"
891
+ "other": "Fallback output if none of the others match: {} count"
892
+ // {} is a replacement for the numerical value itself
893
+ },
894
+ propertyName2: { ...etc }
895
+ }
896
+ ```
897
+ The number map can have as few or as many match options as desired -- if no match is found (or if no `numberMapping` property at all), the number will be returned as-is.
898
+
899
+ e.g.
900
+ ```js
901
+ {
902
+ operator: 'stringSubstitution',
903
+ string: 'Hi {{name}}, we have {{count}} attending this event.',
904
+ values: {
905
+ name: "Tatiana",
906
+ count: {operator: "getData", property: "numOfPeople" }
907
+ },
908
+ numberMap: {
909
+ count: {
910
+ 0: "no one",
911
+ 1: "just one person",
912
+ ">10": "too many people",
913
+ "other": "{} people"
914
+ }
915
+ }
916
+ }
917
+ // Output with varying values for "numOfPeople" passed into evaluation
918
+ // "data" object:
919
+
920
+ // { numOfPeople: 5 }
921
+ // => "Hi Tatiana, we have 5 people attending this event."
922
+
923
+ // { numOfPeople: 0 }
924
+ // => "Hi Tatiana, we have no one attending this event."
925
+
926
+ // { numOfPeople: 100 }
927
+ // => "Hi Tatiana, we have too many people attending this event."
928
+
929
+ // { numOfPeople: 1 }
930
+ // => "Hi Tatiana, we have just one person attending this event.
931
+ ```
932
+
933
+ **Note**: `children` array not available for named properties
934
+
935
+
845
936
  ----
846
937
 
847
938
  ### SPLIT
@@ -1527,7 +1618,7 @@ For more examples, see `23_shorthand.test.ts`, or have a play with the [demo app
1527
1618
 
1528
1619
  ## Caching (Memoization)
1529
1620
 
1530
- FigTree Evaluator has basic [memoization](https://en.wikipedia.org/wiki/Memoization) functionality for certain nodes to speed up re-evaluation when the input parameters haven't changed. There is a single cache store per FigTree instance which persists for the lifetime of the instance. By default, it remembers the last 50 results, but this can be modified using the `maxCacheSize` option.
1621
+ FigTree Evaluator has basic [memoization](https://en.wikipedia.org/wiki/Memoization) functionality for certain nodes to speed up re-evaluation when the input parameters haven't changed. There is a single cache store per FigTree instance which persists for the lifetime of the instance. By default, it remembers the last 50 results with each result being valid for half and hour, but these values can be modified using the `maxCacheSize` and `maxCacheTime` [options](#available-options).
1531
1622
 
1532
1623
  Currently, caching is only implemented for the following operators, since they perform requests to external resources, which are inherently slow:
1533
1624
 
@@ -1543,6 +1634,17 @@ This is different to the memoization provided by [Alias Nodes](#alias-nodes):
1543
1634
 
1544
1635
  Caching is enabled by default for most of the above operators, but this can be overridden by setting `useCache: false` in [options](#available-options), either globally or per expression. If you're querying a database or API that is likely to have a different result for the same request (i.e. data has changed), then you probably want to turn the cache off.
1545
1636
 
1637
+ It's possible to manually set/get the cache store, which can be used (for example) to save the cache in local storage to persist it between page reloads or new FigTree instances.
1638
+
1639
+ Use the methods:
1640
+
1641
+ ```js
1642
+ fig.getCache() // returns key-value store
1643
+
1644
+ fig.setCache(cache) // where "cache" is the object retrieved by .getCache()
1645
+ ```
1646
+
1647
+
1546
1648
  ## Metadata
1547
1649
 
1548
1650
  Evaluator expression can be configured by hand, with [aliases](#alias-nodes), [fragments](#fragments) and [shorthand](#shorthand-syntax) available to make the job easier.
@@ -1691,13 +1793,18 @@ Please open an issue: https://github.com/CarlosNZ/fig-tree-evaluator/issues
1691
1793
 
1692
1794
  *Trivial upgrades (e.g. documentation, small re-factors, types, etc.) not included*
1693
1795
 
1796
+ - **v2.10.0**: Extended stringSubstitution functionality to included named
1797
+ property substitution, trim whitespace option, and pluralisation (#97)
1798
+ - **v2.9.0**: Added ability to invalidate cache by time (#94)
1694
1799
  - **v2.8.6**: Small bug fix where `options` object would be mutated instead of replaced
1695
1800
  - **v2.8.5**: Small bug fix in [COUNT](#count) operator
1696
1801
  - **v2.8.4**: Refactor types, better compliance with [ESLint](https://eslint.org/) rules, add more tests
1697
1802
  - **v2.8.0**:
1698
1803
  - **[Shorthand syntax](#shorthand-syntax)** (#80)
1699
- - **Methods to retrieve [metadata](#metadata)** about operators, fragments and functions (#82)
1700
- - **v2.7.0**: **Add `excludeOperators` option** to allow certain operators to be prohibited (e.g. database lookups) (#54)
1804
+ - **Methods to retrieve [metadata](#metadata)** about operators, fragments and
1805
+ functions (#82)
1806
+ - **v2.7.0**: **Add `excludeOperators` option** to allow certain operators to be
1807
+ prohibited (e.g. database lookups) (#54)
1701
1808
  - **v2.6.0**: Resolve alias nodes that are not part of an Operator node when `evaluateFullObject` is enabled (#78)
1702
1809
  - **v2.5.0**:
1703
1810
  - Bug fixes for edge cases (mainly related to backwards compatibility)
@@ -1719,7 +1826,8 @@ Please open an issue: https://github.com/CarlosNZ/fig-tree-evaluator/issues
1719
1826
  - **v2.0.0**: Re-write as stand-alone package. Major improvements include:
1720
1827
  - more [operators](#operator-reference)
1721
1828
  - operator (and property) [aliases](#operator--property-aliases)
1722
- - more appropriately-named properties associated with each operator (as opposed to a single `children` array)
1829
+ - more appropriately-named properties associated with each operator (as
1830
+ opposed to a single `children` array)
1723
1831
  - class-based Evaluator instances
1724
1832
  - runtime type-checking
1725
1833
  - better error handling and error reporting
@@ -1,4 +1,5 @@
1
1
  import { EvaluatorNode, FigTreeOptions, OperatorMetadata, FragmentMetadata } from './types';
2
+ import { Store } from './cache';
2
3
  declare class FigTreeEvaluator {
3
4
  private options;
4
5
  private operators;
@@ -9,6 +10,8 @@ declare class FigTreeEvaluator {
9
10
  evaluate(expression: EvaluatorNode, options?: FigTreeOptions): Promise<import("./types").EvaluatorOutput>;
10
11
  getOptions(): FigTreeOptions;
11
12
  updateOptions(options: FigTreeOptions): void;
13
+ getCache: () => Store;
14
+ setCache: (cache: Store) => Store;
12
15
  getOperators(): readonly OperatorMetadata[];
13
16
  getFragments(): readonly (FragmentMetadata & {
14
17
  name: string;
@@ -54,17 +54,21 @@ class FigTreeEvaluator {
54
54
  return;
55
55
  throw new Error(result);
56
56
  };
57
+ this.getCache = () => this.cache.getCache();
58
+ this.setCache = (cache) => this.cache.setCache(cache);
57
59
  this.getVersion = () => version_1.version;
58
60
  this.options = standardiseOptionNames(options);
59
61
  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);
60
62
  this.operatorAliases = operatorAliases;
61
- this.cache = new cache_1.default(options.maxCacheSize);
63
+ this.cache = new cache_1.default({ maxSize: options.maxCacheSize, maxTime: options.maxCacheTime });
62
64
  }
63
65
  evaluate(expression, options = {}) {
64
66
  return __awaiter(this, void 0, void 0, function* () {
65
67
  const currentOptions = (0, helpers_1.mergeOptions)(this.options, standardiseOptionNames(options));
66
68
  if (currentOptions.maxCacheSize && currentOptions.maxCacheSize !== this.cache.getMax())
67
69
  this.cache.setMax(currentOptions.maxCacheSize);
70
+ if (currentOptions.maxCacheTime && currentOptions.maxCacheTime !== this.cache.getMaxTime())
71
+ this.cache.setMaxTime(currentOptions.maxCacheTime);
68
72
  return yield (0, evaluate_1.evaluatorFunction)(expression, {
69
73
  options: currentOptions,
70
74
  operators: options.excludeOperators
package/build/cache.d.ts CHANGED
@@ -1,12 +1,27 @@
1
1
  import { EvaluatorOutput, UnknownFunction } from './types';
2
+ interface CacheOptions {
3
+ maxSize?: number;
4
+ maxTime?: number;
5
+ }
6
+ export interface Store {
7
+ [key: string]: {
8
+ result: EvaluatorOutput;
9
+ timestamp: number;
10
+ };
11
+ }
2
12
  declare class FigTreeCache {
3
13
  private store;
4
14
  private queue;
5
15
  private maxSize;
6
- constructor(maxSize?: number);
16
+ private maxTime;
17
+ constructor(options?: CacheOptions);
7
18
  useCache: (shouldUseCache: boolean, action: UnknownFunction, ...args: unknown[]) => Promise<EvaluatorOutput>;
8
19
  getMax: () => number;
9
20
  setMax: (size: number) => void;
21
+ getMaxTime: () => number;
22
+ setMaxTime: (time: number) => void;
23
+ getCache: () => Store;
24
+ setCache: (cache: Store) => Store;
10
25
  private resizeCache;
11
26
  }
12
27
  export default FigTreeCache;
package/build/cache.js CHANGED
@@ -10,19 +10,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const MAX_CACHED_ITEMS = 50;
13
+ const MAX_CACHE_TIME = 1800;
13
14
  class FigTreeCache {
14
- constructor(maxSize) {
15
+ constructor(options) {
16
+ var _a, _b;
15
17
  this.useCache = (shouldUseCache, action, ...args) => __awaiter(this, void 0, void 0, function* () {
16
18
  if (!shouldUseCache)
17
19
  return yield action(...args);
18
20
  const key = stringifyInput(args);
19
- if (key in this.store) {
21
+ const keyExists = key in this.store;
22
+ const newTimestamp = Date.now();
23
+ const isExpired = keyExists && newTimestamp - this.store[key].timestamp > this.maxTime * 1000;
24
+ if (keyExists) {
20
25
  this.queue = this.queue.filter((val) => val !== key);
21
26
  this.queue.unshift(key);
22
- return this.store[key];
27
+ this.store[key].timestamp = newTimestamp;
28
+ if (isExpired)
29
+ this.store[key].result = yield action(...args);
30
+ return this.store[key].result;
23
31
  }
24
32
  const result = yield action(...args);
25
- this.store[key] = result;
33
+ this.store[key] = { result, timestamp: newTimestamp };
26
34
  this.queue.unshift(key);
27
35
  this.resizeCache();
28
36
  return result;
@@ -32,6 +40,12 @@ class FigTreeCache {
32
40
  this.maxSize = size;
33
41
  this.resizeCache();
34
42
  };
43
+ this.getMaxTime = () => this.maxTime;
44
+ this.setMaxTime = (time) => {
45
+ this.maxTime = time;
46
+ };
47
+ this.getCache = () => this.store;
48
+ this.setCache = (cache) => (this.store = cache);
35
49
  this.resizeCache = () => {
36
50
  if (this.queue.length > this.maxSize) {
37
51
  const keysToRemove = this.queue.slice(this.maxSize);
@@ -41,7 +55,8 @@ class FigTreeCache {
41
55
  };
42
56
  this.store = {};
43
57
  this.queue = [];
44
- this.maxSize = maxSize !== null && maxSize !== void 0 ? maxSize : MAX_CACHED_ITEMS;
58
+ this.maxSize = (_a = options === null || options === void 0 ? void 0 : options.maxSize) !== null && _a !== void 0 ? _a : MAX_CACHED_ITEMS;
59
+ this.maxTime = (_b = options === null || options === void 0 ? void 0 : options.maxTime) !== null && _b !== void 0 ? _b : MAX_CACHE_TIME;
45
60
  }
46
61
  }
47
62
  exports.default = FigTreeCache;
@@ -15,9 +15,30 @@ const parameters = [
15
15
  {
16
16
  name: 'substitutions',
17
17
  description: 'An array of substitution values for the parameterised string',
18
- aliases: ['replacements'],
18
+ aliases: ['replacements', 'values'],
19
19
  required: true,
20
- type: 'array',
20
+ type: ['array', 'object'],
21
+ },
22
+ {
23
+ name: 'trimWhiteSpace',
24
+ description: 'Whether or not to trim white space from either end of the substituted strings (default: true)',
25
+ aliases: ['trim', 'trimWhitespace'],
26
+ required: false,
27
+ type: 'boolean',
28
+ },
29
+ {
30
+ name: 'substitutionCharacter',
31
+ description: 'Which character to search for in original string for replacement -- can be "%" or "$" (default: "%")',
32
+ aliases: ['subCharacter', 'subChar'],
33
+ required: false,
34
+ type: 'string',
35
+ },
36
+ {
37
+ name: 'numberMapping',
38
+ description: 'Rules for mapping number values to text strings, such as pluralisation.',
39
+ aliases: ['numMap', 'numberMap', 'pluralisation', 'pluralization', 'plurals'],
40
+ required: false,
41
+ type: 'object',
21
42
  },
22
43
  ];
23
44
  exports.propertyAliases = (0, _operatorUtils_1.getPropertyAliases)(parameters);
@@ -36,15 +36,42 @@ exports.STRING_SUBSTITUTION = void 0;
36
36
  const _operatorUtils_1 = require("../_operatorUtils");
37
37
  const data_1 = __importStar(require("./data"));
38
38
  const evaluate = (expression, config) => __awaiter(void 0, void 0, void 0, function* () {
39
- const [string, substitutions] = (yield (0, _operatorUtils_1.evaluateArray)([expression.string, expression.substitutions], config));
40
- config.typeChecker((0, _operatorUtils_1.getTypeCheckInput)(data_1.default.parameters, { string, substitutions }));
41
- const parameterPattern = /(%[\d]+)/g;
42
- const parameters = (string.match(parameterPattern) || []).sort((a, b) => Number(a.slice(1)) - Number(b.slice(1)));
43
- const uniqueParameters = new Set(parameters);
44
- const replacementsObj = (0, _operatorUtils_1.zipArraysToObject)(Array.from(uniqueParameters), substitutions);
39
+ const [string, substitutions, trimWhiteSpace = true, substitutionCharacter = '%', numberMapping = {},] = (yield (0, _operatorUtils_1.evaluateArray)([
40
+ expression.string,
41
+ expression.substitutions,
42
+ expression.trimWhiteSpace,
43
+ expression.substitutionCharacter,
44
+ expression.numberMapping,
45
+ ], config));
46
+ config.typeChecker((0, _operatorUtils_1.getTypeCheckInput)(data_1.default.parameters, {
47
+ string,
48
+ substitutions,
49
+ trimWhiteSpace,
50
+ substitutionCharacter,
51
+ numberMapping,
52
+ }));
53
+ if (Array.isArray(substitutions)) {
54
+ const subChar = substitutionCharacter === '$' ? '$' : '%';
55
+ const patternString = `(?<!\\\\)(${subChar === '%' ? '%' : '\\$'}[\\d]+)`;
56
+ const parameterPattern = new RegExp(patternString, 'g');
57
+ const parameters = (string.match(parameterPattern) || []).sort((a, b) => Number(a.slice(1)) - Number(b.slice(1)));
58
+ const uniqueParameters = new Set(parameters);
59
+ const replacementsObj = (0, _operatorUtils_1.zipArraysToObject)(Array.from(uniqueParameters), substitutions.map((sub) => (trimWhiteSpace ? String(sub).trim() : sub)));
60
+ return (string
61
+ .split(parameterPattern)
62
+ .map((fragment) => (fragment in replacementsObj ? replacementsObj[fragment] : fragment))
63
+ .join('')
64
+ .replace(`\\${subChar}`, subChar));
65
+ }
66
+ const parameterPattern = /(?<!\\)({{[A-z0-9_]+}})/g;
45
67
  return string
46
68
  .split(parameterPattern)
47
- .map((fragment) => (fragment in replacementsObj ? replacementsObj[fragment] : fragment))
69
+ .map((fragment) => {
70
+ if (!/(?<!\\){{(.+)}}/.exec(fragment))
71
+ return fragment.replace('\\{{', '{{');
72
+ const replacement = getReplacement(fragment, substitutions, numberMapping);
73
+ return trimWhiteSpace ? String(replacement).trim() : replacement;
74
+ })
48
75
  .join('');
49
76
  });
50
77
  const parseChildren = (expression) => {
@@ -57,3 +84,29 @@ exports.STRING_SUBSTITUTION = {
57
84
  evaluate,
58
85
  parseChildren,
59
86
  };
87
+ const getReplacement = (fragment, replacements, numberMaps) => {
88
+ var _a, _b;
89
+ const key = fragment.replace(/{{(.+)}}/, '$1');
90
+ const value = (_a = replacements === null || replacements === void 0 ? void 0 : replacements[key]) !== null && _a !== void 0 ? _a : '';
91
+ if (typeof value !== 'number')
92
+ return (_b = replacements === null || replacements === void 0 ? void 0 : replacements[key]) !== null && _b !== void 0 ? _b : '';
93
+ if (!(key in numberMaps))
94
+ return value;
95
+ const numMap = numberMaps[key];
96
+ if (value in numMap)
97
+ return numMap[value].replace('{}', String(value));
98
+ const numberKeys = Object.keys(numberMaps[key]);
99
+ const greaterThanKey = numberKeys.find((key) => key.startsWith('>'));
100
+ if (greaterThanKey) {
101
+ const num = Number(greaterThanKey.slice(1));
102
+ if (value > num)
103
+ return numMap === null || numMap === void 0 ? void 0 : numMap[greaterThanKey];
104
+ }
105
+ const lessThanKey = numberKeys.find((key) => key.startsWith('<'));
106
+ if (lessThanKey) {
107
+ const num = Number(lessThanKey.slice(1));
108
+ if (value < num)
109
+ return numMap === null || numMap === void 0 ? void 0 : numMap[lessThanKey];
110
+ }
111
+ return numMap.other ? numMap.other.replace('{}', String(value)) : value;
112
+ };
package/build/types.d.ts CHANGED
@@ -4,7 +4,7 @@ import { GraphQLConnection } from './operators';
4
4
  import operatorAliases from './operators/_operatorAliases.json';
5
5
  import { ExpectedType, TypeCheckInput } from './typeCheck';
6
6
  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"];
7
- export type Operator = typeof Operators[number];
7
+ export type Operator = (typeof Operators)[number];
8
8
  export type OperatorAlias = keyof typeof operatorAliases;
9
9
  export type OperatorAliases = Record<OperatorAlias, Operator>;
10
10
  export type Fragments = Record<string, Fragment>;
@@ -29,6 +29,7 @@ export interface FigTreeOptions {
29
29
  excludeOperators?: OperatorAlias[];
30
30
  useCache?: boolean;
31
31
  maxCacheSize?: number;
32
+ maxCacheTime?: number;
32
33
  supportDeprecatedValueNodes?: boolean;
33
34
  }
34
35
  export interface FigTreeConfig {
@@ -1 +1 @@
1
- export declare const version = "2.8.6";
1
+ export declare const version = "2.10.0";
package/build/version.js CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.version = void 0;
4
- exports.version = '2.8.6';
4
+ exports.version = '2.10.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fig-tree-evaluator",
3
- "version": "2.8.6",
3
+ "version": "2.10.0",
4
4
  "description": "Module to evaluate JSON-structured expression trees",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -20,10 +20,10 @@
20
20
  "@typescript-eslint/parser": "^5.57.0",
21
21
  "dotenv": "^16.0.1",
22
22
  "eslint": "^8.37.0",
23
- "jest": "^28.1.0",
23
+ "jest": "^29.6.2",
24
24
  "pg": "^8.7.3",
25
25
  "rimraf": "^3.0.2",
26
- "ts-jest": "^28.0.3",
26
+ "ts-jest": "^29.1.1",
27
27
  "ts-node": "^10.8.0",
28
28
  "typescript": "^4.7.2"
29
29
  },