fig-tree-evaluator 2.9.0 → 2.11.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 +104 -8
- package/build/index.cjs.js +1 -0
- package/build/index.d.ts +121 -4
- package/build/index.esm.js +1 -0
- package/package.json +12 -3
- package/build/FigTreeEvaluator.d.ts +0 -26
- package/build/FigTreeEvaluator.js +0 -121
- package/build/cache.d.ts +0 -27
- package/build/cache.js +0 -63
- package/build/evaluate.d.ts +0 -2
- package/build/evaluate.js +0 -87
- package/build/helpers.d.ts +0 -23
- package/build/helpers.js +0 -137
- package/build/index.js +0 -29
- package/build/operators/AND/data.d.ts +0 -4
- package/build/operators/AND/data.js +0 -22
- package/build/operators/AND/index.d.ts +0 -1
- package/build/operators/AND/index.js +0 -5
- package/build/operators/AND/operator.d.ts +0 -3
- package/build/operators/AND/operator.js +0 -53
- package/build/operators/BUILD_OBJECT/data.d.ts +0 -4
- package/build/operators/BUILD_OBJECT/data.js +0 -22
- package/build/operators/BUILD_OBJECT/index.d.ts +0 -1
- package/build/operators/BUILD_OBJECT/index.js +0 -17
- package/build/operators/BUILD_OBJECT/operator.d.ts +0 -2
- package/build/operators/BUILD_OBJECT/operator.js +0 -64
- package/build/operators/CONDITIONAL/data.d.ts +0 -4
- package/build/operators/CONDITIONAL/data.js +0 -36
- package/build/operators/CONDITIONAL/index.d.ts +0 -1
- package/build/operators/CONDITIONAL/index.js +0 -17
- package/build/operators/CONDITIONAL/operator.d.ts +0 -2
- package/build/operators/CONDITIONAL/operator.js +0 -59
- package/build/operators/COUNT/data.d.ts +0 -4
- package/build/operators/COUNT/data.js +0 -22
- package/build/operators/COUNT/index.d.ts +0 -1
- package/build/operators/COUNT/index.js +0 -17
- package/build/operators/COUNT/operator.d.ts +0 -2
- package/build/operators/COUNT/operator.js +0 -52
- package/build/operators/CUSTOM_FUNCTIONS/data.d.ts +0 -4
- package/build/operators/CUSTOM_FUNCTIONS/data.js +0 -43
- package/build/operators/CUSTOM_FUNCTIONS/index.d.ts +0 -1
- package/build/operators/CUSTOM_FUNCTIONS/index.js +0 -17
- package/build/operators/CUSTOM_FUNCTIONS/operator.d.ts +0 -2
- package/build/operators/CUSTOM_FUNCTIONS/operator.js +0 -65
- package/build/operators/DIVIDE/data.d.ts +0 -4
- package/build/operators/DIVIDE/data.js +0 -43
- package/build/operators/DIVIDE/index.d.ts +0 -1
- package/build/operators/DIVIDE/index.js +0 -17
- package/build/operators/DIVIDE/operator.d.ts +0 -2
- package/build/operators/DIVIDE/operator.js +0 -63
- package/build/operators/EQUAL/data.d.ts +0 -4
- package/build/operators/EQUAL/data.js +0 -29
- package/build/operators/EQUAL/index.d.ts +0 -1
- package/build/operators/EQUAL/index.js +0 -17
- package/build/operators/EQUAL/operator.d.ts +0 -2
- package/build/operators/EQUAL/operator.js +0 -58
- package/build/operators/GET/data.d.ts +0 -4
- package/build/operators/GET/data.js +0 -50
- package/build/operators/GET/index.d.ts +0 -1
- package/build/operators/GET/index.js +0 -5
- package/build/operators/GET/operator.d.ts +0 -3
- package/build/operators/GET/operator.js +0 -91
- package/build/operators/GRAPHQL/data.d.ts +0 -4
- package/build/operators/GRAPHQL/data.js +0 -57
- package/build/operators/GRAPHQL/index.d.ts +0 -1
- package/build/operators/GRAPHQL/index.js +0 -17
- package/build/operators/GRAPHQL/operator.d.ts +0 -8
- package/build/operators/GRAPHQL/operator.js +0 -86
- package/build/operators/GREATER_THAN/data.d.ts +0 -4
- package/build/operators/GREATER_THAN/data.js +0 -29
- package/build/operators/GREATER_THAN/index.d.ts +0 -1
- package/build/operators/GREATER_THAN/index.js +0 -17
- package/build/operators/GREATER_THAN/operator.d.ts +0 -2
- package/build/operators/GREATER_THAN/operator.js +0 -54
- package/build/operators/LESS_THAN/data.d.ts +0 -4
- package/build/operators/LESS_THAN/data.js +0 -29
- package/build/operators/LESS_THAN/index.d.ts +0 -1
- package/build/operators/LESS_THAN/index.js +0 -17
- package/build/operators/LESS_THAN/operator.d.ts +0 -2
- package/build/operators/LESS_THAN/operator.js +0 -54
- package/build/operators/MATCH/data.d.ts +0 -4
- package/build/operators/MATCH/data.js +0 -29
- package/build/operators/MATCH/index.d.ts +0 -1
- package/build/operators/MATCH/index.js +0 -17
- package/build/operators/MATCH/operator.d.ts +0 -2
- package/build/operators/MATCH/operator.js +0 -72
- package/build/operators/MULTIPLY/data.d.ts +0 -4
- package/build/operators/MULTIPLY/data.js +0 -22
- package/build/operators/MULTIPLY/index.d.ts +0 -1
- package/build/operators/MULTIPLY/index.js +0 -17
- package/build/operators/MULTIPLY/operator.d.ts +0 -2
- package/build/operators/MULTIPLY/operator.js +0 -53
- package/build/operators/NOT_EQUAL/data.d.ts +0 -4
- package/build/operators/NOT_EQUAL/data.js +0 -29
- package/build/operators/NOT_EQUAL/index.d.ts +0 -1
- package/build/operators/NOT_EQUAL/index.js +0 -17
- package/build/operators/NOT_EQUAL/operator.d.ts +0 -2
- package/build/operators/NOT_EQUAL/operator.js +0 -58
- package/build/operators/OBJECT_PROPERTIES/data.d.ts +0 -4
- package/build/operators/OBJECT_PROPERTIES/data.js +0 -37
- package/build/operators/OBJECT_PROPERTIES/index.d.ts +0 -1
- package/build/operators/OBJECT_PROPERTIES/index.js +0 -17
- package/build/operators/OBJECT_PROPERTIES/operator.d.ts +0 -2
- package/build/operators/OBJECT_PROPERTIES/operator.js +0 -62
- package/build/operators/OR/data.d.ts +0 -4
- package/build/operators/OR/data.js +0 -22
- package/build/operators/OR/index.d.ts +0 -1
- package/build/operators/OR/index.js +0 -17
- package/build/operators/OR/operator.d.ts +0 -2
- package/build/operators/OR/operator.js +0 -49
- package/build/operators/PASSTHRU/data.d.ts +0 -4
- package/build/operators/PASSTHRU/data.js +0 -22
- package/build/operators/PASSTHRU/index.d.ts +0 -1
- package/build/operators/PASSTHRU/index.js +0 -17
- package/build/operators/PASSTHRU/operator.d.ts +0 -2
- package/build/operators/PASSTHRU/operator.js +0 -53
- package/build/operators/PG_SQL/data.d.ts +0 -4
- package/build/operators/PG_SQL/data.js +0 -43
- package/build/operators/PG_SQL/index.d.ts +0 -1
- package/build/operators/PG_SQL/index.js +0 -17
- package/build/operators/PG_SQL/operator.d.ts +0 -2
- package/build/operators/PG_SQL/operator.js +0 -83
- package/build/operators/PLUS/data.d.ts +0 -4
- package/build/operators/PLUS/data.js +0 -29
- package/build/operators/PLUS/index.d.ts +0 -1
- package/build/operators/PLUS/index.js +0 -17
- package/build/operators/PLUS/operator.d.ts +0 -2
- package/build/operators/PLUS/operator.js +0 -63
- package/build/operators/POST/data.d.ts +0 -4
- package/build/operators/POST/data.js +0 -50
- package/build/operators/POST/index.d.ts +0 -1
- package/build/operators/POST/index.js +0 -17
- package/build/operators/POST/operator.d.ts +0 -2
- package/build/operators/POST/operator.js +0 -72
- package/build/operators/REGEX/data.d.ts +0 -4
- package/build/operators/REGEX/data.js +0 -29
- package/build/operators/REGEX/index.d.ts +0 -1
- package/build/operators/REGEX/index.js +0 -17
- package/build/operators/REGEX/operator.d.ts +0 -2
- package/build/operators/REGEX/operator.js +0 -59
- package/build/operators/SPLIT/data.d.ts +0 -4
- package/build/operators/SPLIT/data.js +0 -43
- package/build/operators/SPLIT/index.d.ts +0 -1
- package/build/operators/SPLIT/index.js +0 -17
- package/build/operators/SPLIT/operator.d.ts +0 -2
- package/build/operators/SPLIT/operator.js +0 -69
- package/build/operators/STRING_SUBSTITUTION/data.d.ts +0 -4
- package/build/operators/STRING_SUBSTITUTION/data.js +0 -29
- package/build/operators/STRING_SUBSTITUTION/index.d.ts +0 -1
- package/build/operators/STRING_SUBSTITUTION/index.js +0 -17
- package/build/operators/STRING_SUBSTITUTION/operator.d.ts +0 -2
- package/build/operators/STRING_SUBSTITUTION/operator.js +0 -59
- package/build/operators/SUBTRACT/data.d.ts +0 -4
- package/build/operators/SUBTRACT/data.js +0 -36
- package/build/operators/SUBTRACT/index.d.ts +0 -1
- package/build/operators/SUBTRACT/index.js +0 -17
- package/build/operators/SUBTRACT/operator.d.ts +0 -2
- package/build/operators/SUBTRACT/operator.js +0 -54
- package/build/operators/_operatorAliases.json +0 -92
- package/build/operators/_operatorUtils.d.ts +0 -24
- package/build/operators/_operatorUtils.js +0 -122
- package/build/operators/index.d.ts +0 -24
- package/build/operators/index.js +0 -40
- package/build/shorthandSyntax.d.ts +0 -2
- package/build/shorthandSyntax.js +0 -55
- package/build/typeCheck.d.ts +0 -12
- package/build/typeCheck.js +0 -54
- package/build/types.d.ts +0 -96
- package/build/types.js +0 -29
- package/build/version.d.ts +0 -1
- package/build/version.js +0 -4
package/README.md
CHANGED
|
@@ -122,7 +122,7 @@ or\
|
|
|
122
122
|
## Usage
|
|
123
123
|
|
|
124
124
|
```js
|
|
125
|
-
import FigTreeEvaluator from 'fig-tree-evaluator'
|
|
125
|
+
import { FigTreeEvaluator } from 'fig-tree-evaluator'
|
|
126
126
|
|
|
127
127
|
// New evaluator instance
|
|
128
128
|
const fig = new FigTreeEvaluator([ options ]) // See available options below
|
|
@@ -776,14 +776,21 @@ Example using "data" passed in dynamically as part of expression:
|
|
|
776
776
|
----
|
|
777
777
|
### STRING_SUBSTITUTION
|
|
778
778
|
|
|
779
|
-
*Replace values in a string using simple parameter substitution*
|
|
779
|
+
*Replace values in a string using simple parameter (positional or named properties) substitution*
|
|
780
780
|
|
|
781
781
|
Aliases: `stringSubstitution`, `substitute`, `stringSub`, `replace`
|
|
782
782
|
|
|
783
783
|
#### Properties
|
|
784
784
|
|
|
785
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)"`
|
|
786
|
-
- `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
|
|
787
794
|
|
|
788
795
|
The values in the `substitutions` array are replaced in the original `string` by matching their order to the numerical order of the parameters.
|
|
789
796
|
|
|
@@ -804,7 +811,9 @@ e.g.
|
|
|
804
811
|
|
|
805
812
|
{
|
|
806
813
|
operator: 'replace',
|
|
807
|
-
|
|
814
|
+
// Using $1, $2 instead of %1, %2 this time:
|
|
815
|
+
string: '$1 is actually $2 $3',
|
|
816
|
+
substitutionCharacter: "$",
|
|
808
817
|
substitutions: [
|
|
809
818
|
// Using the 'user' object from above (OBJECT_PROPERTIES operator)
|
|
810
819
|
{
|
|
@@ -830,9 +839,19 @@ e.g.
|
|
|
830
839
|
substitutions: ['bird', 'Tweet!'],
|
|
831
840
|
}
|
|
832
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
|
|
833
851
|
```
|
|
834
852
|
|
|
835
|
-
`children` array: `[string, ...substitutions]`
|
|
853
|
+
`children` array: `[string, ...substitutions]`
|
|
854
|
+
(`trimWhiteSpace` and `substitutionCharacter` not available, since `substitutions` can be an arbitrary number of items)
|
|
836
855
|
|
|
837
856
|
e.g.
|
|
838
857
|
```js
|
|
@@ -843,6 +862,77 @@ e.g.
|
|
|
843
862
|
// => "I am Iron Man"
|
|
844
863
|
```
|
|
845
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
|
+
|
|
846
936
|
----
|
|
847
937
|
|
|
848
938
|
### SPLIT
|
|
@@ -1703,14 +1793,19 @@ Please open an issue: https://github.com/CarlosNZ/fig-tree-evaluator/issues
|
|
|
1703
1793
|
|
|
1704
1794
|
*Trivial upgrades (e.g. documentation, small re-factors, types, etc.) not included*
|
|
1705
1795
|
|
|
1796
|
+
- **v2.11.0**: Improved package bundling (bundle size ~50%), with CommonJS and ESM outputs. Note: small **breaking change**: "FigTreeEvaluator" is no longer a default export, so need to import with: `import { FigTreeEvaluator } from 'fig-tree-evaluator'`
|
|
1797
|
+
- **v2.10.0**: Extended stringSubstitution functionality to included named
|
|
1798
|
+
property substitution, trim whitespace option, and pluralisation (#97)
|
|
1706
1799
|
- **v2.9.0**: Added ability to invalidate cache by time (#94)
|
|
1707
1800
|
- **v2.8.6**: Small bug fix where `options` object would be mutated instead of replaced
|
|
1708
1801
|
- **v2.8.5**: Small bug fix in [COUNT](#count) operator
|
|
1709
1802
|
- **v2.8.4**: Refactor types, better compliance with [ESLint](https://eslint.org/) rules, add more tests
|
|
1710
1803
|
- **v2.8.0**:
|
|
1711
1804
|
- **[Shorthand syntax](#shorthand-syntax)** (#80)
|
|
1712
|
-
- **Methods to retrieve [metadata](#metadata)** about operators, fragments and
|
|
1713
|
-
|
|
1805
|
+
- **Methods to retrieve [metadata](#metadata)** about operators, fragments and
|
|
1806
|
+
functions (#82)
|
|
1807
|
+
- **v2.7.0**: **Add `excludeOperators` option** to allow certain operators to be
|
|
1808
|
+
prohibited (e.g. database lookups) (#54)
|
|
1714
1809
|
- **v2.6.0**: Resolve alias nodes that are not part of an Operator node when `evaluateFullObject` is enabled (#78)
|
|
1715
1810
|
- **v2.5.0**:
|
|
1716
1811
|
- Bug fixes for edge cases (mainly related to backwards compatibility)
|
|
@@ -1732,7 +1827,8 @@ Please open an issue: https://github.com/CarlosNZ/fig-tree-evaluator/issues
|
|
|
1732
1827
|
- **v2.0.0**: Re-write as stand-alone package. Major improvements include:
|
|
1733
1828
|
- more [operators](#operator-reference)
|
|
1734
1829
|
- operator (and property) [aliases](#operator--property-aliases)
|
|
1735
|
-
- more appropriately-named properties associated with each operator (as
|
|
1830
|
+
- more appropriately-named properties associated with each operator (as
|
|
1831
|
+
opposed to a single `children` array)
|
|
1736
1832
|
- class-based Evaluator instances
|
|
1737
1833
|
- runtime type-checking
|
|
1738
1834
|
- better error handling and error reporting
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e=require("change-case"),r=require("axios"),t=require("object-property-extractor"),a=require("dequal/lite");const s=e=>e instanceof Object&&"operator"in e,i=e=>e instanceof Object&&"fragment"in e,n=r=>{const t=e.camelCase(r);return t||r},o=(e,r)=>r[n(e)],u=(e,r,t)=>{const a={...e};return r.forEach((e=>{t[n(e)]||console.warn(`Invalid operator exclusion: ${e}`),delete a[t[n(e)]]})),a},l=(e,r=200)=>e.length<r?e:`${e.slice(0,r-2).trim()}...`,p=(e,r,t=!1)=>{if(void 0!==e)return e;if(t)return l(r);throw new Error(l(r))},c=(e,r)=>{const t=Object.entries(e).map((([e,t])=>[r(e),t]));return Object.fromEntries(t)},d=e=>/^\$.+/.test(e),h=(e,{resolvedAliasNodes:r})=>"string"==typeof e&&d(e)?r?.[e]??e:e,m=(e,r)=>{const t={...e,...r};return(e.data||r.data)&&(t.data={...e.data,...r.data}),(e.functions||r.functions)&&(t.functions={...e.functions,...r.functions}),(e.fragments||r.fragments)&&(t.fragments={...e.fragments,...r.fragments}),(e.headers||r.headers)&&(t.headers={...e.headers,...r.headers}),t},y={number:e=>g(e),string:e=>String(e),array:e=>Array.isArray(e)?e:[e],boolean:e=>Boolean(e),bool:e=>Boolean(e)},f=e=>e.message,g=e=>{if("string"!=typeof e)return Number.isNaN(Number(e))?e:Number(e);const r=new RegExp(/-?\d*\.?\d+/gm),t=e.match(r);return t?Number(t[0]):0},v=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),b={and:"AND","&":"AND","&&":"AND",or:"OR","|":"OR","||":"OR","=":"EQUAL",eq:"EQUAL",equal:"EQUAL",equals:"EQUAL","!=":"NOT_EQUAL","!":"NOT_EQUAL",ne:"NOT_EQUAL",notEqual:"NOT_EQUAL","+":"PLUS",plus:"PLUS",add:"PLUS",concat:"PLUS",join:"PLUS",merge:"PLUS","-":"SUBTRACT",subtract:"SUBTRACT",minus:"SUBTRACT",takeaway:"SUBTRACT","*":"MULTIPLY",x:"MULTIPLY",multiply:"MULTIPLY",times:"MULTIPLY","/":"DIVIDE",divide:"DIVIDE","÷":"DIVIDE",">":"GREATER_THAN",greaterThan:"GREATER_THAN",higher:"GREATER_THAN",larger:"GREATER_THAN","<":"LESS_THAN",lessThan:"LESS_THAN",lower:"LESS_THAN",smaller:"LESS_THAN","?":"CONDITIONAL",conditional:"CONDITIONAL",ifThen:"CONDITIONAL",regex:"REGEX",patternMatch:"REGEX",regexp:"REGEX",matchPattern:"REGEX",dataProperties:"OBJECT_PROPERTIES",data:"OBJECT_PROPERTIES",getData:"OBJECT_PROPERTIES",objectProperties:"OBJECT_PROPERTIES",objProps:"OBJECT_PROPERTIES",getProperty:"OBJECT_PROPERTIES",getObjProp:"OBJECT_PROPERTIES",stringSubstitution:"STRING_SUBSTITUTION",substitute:"STRING_SUBSTITUTION",stringSub:"STRING_SUBSTITUTION",replace:"STRING_SUBSTITUTION",split:"SPLIT",arraySplit:"SPLIT",count:"COUNT",length:"COUNT",get:"GET",api:"GET",post:"POST",pgSql:"PG_SQL",sql:"PG_SQL",postgres:"PG_SQL",pg:"PG_SQL",pgDb:"PG_SQL",graphQl:"GRAPHQL",graphql:"GRAPHQL",gql:"GRAPHQL",buildObject:"BUILD_OBJECT",build:"BUILD_OBJECT",object:"BUILD_OBJECT",match:"MATCH",switch:"MATCH",customFunctions:"CUSTOM_FUNCTIONS",customFunction:"CUSTOM_FUNCTIONS",objectFunctions:"CUSTOM_FUNCTIONS",function:"CUSTOM_FUNCTIONS",functions:"CUSTOM_FUNCTIONS",runFunction:"CUSTOM_FUNCTIONS",_:"PASSTHRU",passThru:"PASSTHRU",passthru:"PASSTHRU",pass:"PASSTHRU",ignore:"PASSTHRU",coerce:"PASSTHRU",convert:"PASSTHRU"},T=b,C=/(\$[^()]+)\((.*)\)/,w=(e,r={},t=!0)=>t?"string"==typeof e?q(e,r):v(e)?A(e,r):e:e,q=(e,r)=>{const t=C.exec(e);if(!t)return e;const a=t[1].trim(),s=t[2].split(",").map((e=>w(e.trim(),r)));return E(a,s,r)},A=(e,r)=>{if(s(e)||i(e))return e;const t=Object.entries(e),a=t.filter((([e])=>d(e))),n=t.filter((([e])=>!d(e)));return{...a.reduce(((e,[t,a])=>e={...e,...E(t,a,r)}),{}),...Object.fromEntries(n)}},E=(e,r,t)=>{const a=e.slice(1),s=o(a,T);return s?Array.isArray(r)?{operator:s,children:r}:v(r)&&!Object.keys(r).some((e=>d(e)))?{operator:s,...r}:{operator:s,children:[r]}:a in t?{fragment:a,parameters:{...r}}:{[e]:r}},S=e=>v(e)&&"literal"in e,O=({value:e,name:r,expectedType:t})=>{if(S(t)){const{literal:a}=t;return!!a.includes(e)||x(r,e,`Literal(${a.map((e=>void 0===e?"undefined":`"${e}"`)).join(", ")})`)}if(Array.isArray(t))return!!t.some((t=>!0===O({value:e,name:r,expectedType:t})))||x(r,e,t.join("|"));return!!(0,P[t])(e)||x(r,e,t)},N=(...e)=>{const r=[];return e.forEach((e=>{const t=O(e);!0!==t&&r.push(t)})),!(r.length>0)||r.join("\n")},P={any:e=>void 0!==e,string:e=>"string"==typeof e,number:e=>"number"==typeof e,boolean:e=>"boolean"==typeof e,array:e=>Array.isArray(e),null:e=>null===e,object:e=>v(e),undefined:e=>void 0===e},x=(e,r,t)=>void 0===r&&e?`- Missing required property "${e}" (type: ${t})`:void 0!==e?`- Property "${e}" (value: ${U(r)}) is not of type: ${t}`:`- ${U(r)} is not of type: ${t}`,U=e=>{const r=void 0===e||Number.isNaN(e)?String(e):JSON.stringify(e);return l(r,50)},j=e=>{const r={};return e.forEach((e=>{e.aliases.forEach((t=>r[t]=e.name))})),r},R=(e,r)=>e.map((({name:e,required:t,type:a})=>{if(S(a)){const s=[...a.literal];return t||s.push(void 0),{name:e,value:r[e],expectedType:{literal:s}}}const s=Array.isArray(a)?a:[a];t||s.push("undefined");const i=1===s.length?s[0]:s;return{name:e,value:r[e],expectedType:i}})),I=(e,r)=>{const t=e.map(((e,t)=>[e,r[t]]));return Object.fromEntries(t)},L=e=>{if(e.length%2!=0)throw new Error("Even number of children required to make key/value pairs");const r=e.filter(((e,r)=>r%2==0)),t=N(...r.map((e=>({value:e,expectedType:["string","number","boolean"]}))));if(!0!==t)throw new Error(t);const a=e.filter(((e,r)=>r%2==1)),s={};return r.forEach(((e,r)=>{s[e]=a[r]})),s},k=e=>v(e)&&1===Object.keys(e).length?Object.values(e)[0]:e,D=(e,r,a=void 0)=>{const s=r?t(e,r,a):e;return Array.isArray(s)?s.map((e=>k(e))):r?null===s?null:k(s):s},_=e=>/^https?:\/\/.+/.test(e),M=(...e)=>e.reduce(((e,r,t)=>{const a="/"===r[0]?1:0,s="/"===r.slice(-1)?-1:void 0,i=r.slice(a,s);return""===i?e:e+(0===t?"":"/")+i}),""),H=async({url:e,params:t={},data:a={},headers:s={},method:i="get"})=>{try{return(await r({method:i,url:e,headers:{"Content-Type":"application/json",Accept:"application/json",...s},params:t,data:a})).data}catch(e){if(r.isAxiosError(e)){if(!e?.response)throw new Error("Network Error");console.log(e.response?.data)}throw e}},F=async(e,r)=>{const{options:t,operators:a,operatorAliases:n}=r;let u=t?.allowJSONStringInput?(e=>{if("string"!=typeof e)return e;try{const r=JSON.parse(e);return s(r)?r:e}catch(r){return e}})(e):e;u=w(u,r.options?.fragments,!t.noShorthand),Array.isArray(u)&&(u=await G(u,r));const l=s(u),d=i(u);if(t.evaluateFullObject&&!l&&!d)return h(await $(u,r),r);if(!l&&!d)return t.supportDeprecatedValueNodes&&v(u)&&"value"in u?u.value:h(u,r);const{fallback:m}=u,g=t?.returnErrorAsString??!1;if(d){const[e,a]=await G([u.fragment,u.parameters],r),i=w(t?.fragments?.[e],t.fragments,!t.noShorthand);if(void 0===i)return p(await F(m,r),`Fragment not defined: ${e}`,g);if(!s(i))return h(i,r);u={...u,...i,...a},delete u.fragment}try{const e=o(u.operator,n);if(!e)return p(await F(m,r),`Invalid operator: ${u.operator}`,g);if(!r.operators[e])return p(await F(m,r),`Excluded operator: ${u.operator}`,g);const{propertyAliases:t,evaluate:s,parseChildren:i}=a[e];u=((e,r)=>c(r,(r=>r in e?e[r]:r)))(t,u);const l=await Q(u,r);d||Object.entries(l).forEach((([e,t])=>r.resolvedAliasNodes[e]=t));const h=d?{...r,resolvedAliasNodes:{...r.resolvedAliasNodes,...l}}:r;if("children"in u){if(Array.isArray(u.children)||(u.children=await F(u.children,h)),!Array.isArray(u.children))return p(await F(m,r),`Operator: ${e}\n- Property "children" is not of type: array`,g);u=await i(u,h),delete u.children}let v;try{v=await s(u,h)}catch(t){return p(await F(u.fallback,r),`Operator: ${e}\n${f(t)}`,g)}const b=u?.outputType??u?.type;if(!b)return v;const T=await F(b,r);return T in y?y[T](v):p(await F(m,r),`Operator: ${e}\n- Invalid output type: ${T}`,g)}catch(e){return p(await F(m,r),f(e),g)}},G=async(e,r)=>Array.isArray(e)?await Promise.all(e.map((e=>F(e,r)))):await F(e,r),Q=async(e,r)=>{const t=Object.keys(e).filter(d);if(0===t.length)return{};const a=[];return t.forEach((t=>a.push(F(e[t],r)))),I(t,await Promise.all(a))},$=async(e,r)=>{if(!v(e))return e;const t=[],a=[];Object.entries(e).forEach((([t,s])=>{d(t)&&(a.push(t,F(s,r)),delete e[t])}));const s=await Promise.all(a);r.resolvedAliasNodes={...r.resolvedAliasNodes,...L(s)},Object.entries(e).forEach((([e,a])=>{t.push(e,F(a,r))}));const i=await Promise.all(t);return h(L(i),r)},B=[{name:"values",description:"Returns true if all values are true",aliases:[],required:!0,type:"array"}],W=j(B),z={description:"Logical AND",aliases:["and","&","&&"],parameters:B},J=e=>{const r=e.children;return{...e,values:r}},V={propertyAliases:W,operatorData:z,evaluate:async(e,r)=>{const t=await G(e.values,r);return r.typeChecker(R(z.parameters,{values:t})),t.reduce(((e,r)=>e&&!!r),!0)},parseChildren:J},X=[{name:"values",description:"Returns true if any values are true",aliases:[],required:!0,type:"array"}],Y=j(X),K={description:"Logical OR",aliases:["or","|","||"],parameters:X},Z={propertyAliases:Y,operatorData:K,evaluate:async(e,r)=>{const t=await G(e.values,r);return r.typeChecker(R(K.parameters,{values:t})),t.reduce(((e,r)=>e||!!r),!1)},parseChildren:J},ee=[{name:"values",description:"Array of values to check for equality",aliases:[],required:!0,type:"array"},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value",aliases:[],required:!1,type:"boolean"}],re=j(ee),te={description:"Test multiple values are equal",aliases:["=","eq","equal","equals"],parameters:ee},ae={propertyAliases:re,operatorData:te,evaluate:async(e,r)=>{const[t,s]=await G([e.values,e.nullEqualsUndefined],r);r.typeChecker(R(te.parameters,{values:t,nullEqualsUndefined:s}));return!(void 0!==s?s:void 0!==r.options?.nullEqualsUndefined&&r.options.nullEqualsUndefined)||null!==t[0]&&void 0!==t[0]?t.every((e=>a.dequal(e,t[0]))):t.every((e=>null==e))},parseChildren:J},se=[{name:"values",description:"Array of values to check for inequality",aliases:[],required:!0,type:"array"},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value",aliases:[],required:!1,type:"boolean"}],ie=j(se),ne={description:"Test if any values are different",aliases:["!=","!","ne","notEqual"],parameters:se},oe={propertyAliases:ie,operatorData:ne,evaluate:async(e,r)=>{const[t,s]=await G([e.values,e.nullEqualsUndefined],r);r.typeChecker(R(ne.parameters,{values:t,nullEqualsUndefined:s}));return!(void 0!==s?s:void 0!==r.options?.nullEqualsUndefined&&r.options.nullEqualsUndefined)||null!==t[0]&&void 0!==t[0]?t.some((e=>!a.dequal(e,t[0]))):t.some((e=>null===e&&void 0===e))},parseChildren:J},ue=[{name:"values",description:"Array of values to check to add together",aliases:[],required:!0,type:"array"},{name:"type",description:"Data type to coerce input values to before addition",aliases:[],required:!1,type:{literal:["string","array","number","boolean","bool"]}}],le=j(ue),pe={description:"Add, concatenate or merge multiple values",aliases:["+","plus","add","concat","join","merge"],parameters:ue},ce={propertyAliases:le,operatorData:pe,evaluate:async(e,r)=>{const t=await G(e.values,r);return r.typeChecker(R(pe.parameters,{values:t,type:e.type})),0===t.length?t:"string"===e?.type?t.reduce(((e,r)=>e.concat(r)),""):"array"===e?.type?t.reduce(((e,r)=>e.concat(r)),[]):t.every((e=>"string"==typeof e||Array.isArray(e)))?t.reduce(((e,r)=>e.concat(r))):t.every((e=>v(e)))?t.reduce(((e,r)=>({...e,...r})),{}):t.reduce(((e,r)=>e+r))},parseChildren:J},de=[{name:"values",description:"Array of values - 2nd element will be subtracted from the first",aliases:[],required:!1,type:"array"},{name:"from",description:"Numerical value that will be subtracted from",aliases:["subtractFrom"],required:!1,type:"number"},{name:"subtract",description:"Numerical value to subtract",aliases:[],required:!1,type:"number"}],he=j(de),me={description:"Subtract one numerical value from another",aliases:["-","subtract","minus","takeaway"],parameters:de},ye={propertyAliases:he,operatorData:me,evaluate:async(e,r)=>{const[t,a,s]=await G([e.values,e.from,e.subtract],r);r.typeChecker(R(me.parameters,{values:t,from:a,subtract:s}));const i=t??[a,s].filter((e=>void 0!==e));if(i.length<2)throw new Error("- Not enough values provided");if(i.some((e=>"number"!=typeof e)))throw new Error("- Not all values are numbers");return i[0]-i[1]},parseChildren:J},fe=[{name:"values",description:"Array of values whose product will be calculated",aliases:[],required:!0,type:"array"}],ge=j(fe),ve={description:"Multiply several numerical values together",aliases:["*","x","multiply","times"],parameters:fe},be={propertyAliases:ge,operatorData:ve,evaluate:async(e,r)=>{const t=await G(e.values,r);if(r.typeChecker(R(ve.parameters,{values:t})),0===t.length)return 0;if(t.some((e=>"number"!=typeof e)))throw new Error("- Not all values are numbers");return t.reduce(((e,r)=>e*r))},parseChildren:J},Te=[{name:"values",description:"Array of values - 1st element will be divided by the first",aliases:[],required:!1,type:"array"},{name:"dividend",description:"The number that will be divided",aliases:["divide"],required:!1,type:"number"},{name:"divisor",description:"The number that dividend will be divided by",aliases:["by","divideBy"],required:!1,type:"number"},{name:"output",description:"Whether to output a quotient, remainder or decimal",aliases:[],required:!1,type:{literal:["quotient","remainder"]}}],Ce=j(Te),we={description:"Divide one numerical value by another",aliases:["/","divide","÷"],parameters:Te},qe={propertyAliases:Ce,operatorData:we,evaluate:async(e,r)=>{const[t,a,s,i]=await G([e.values,e.dividend,e.divisor,e.output],r);r.typeChecker(R(we.parameters,{values:t,dividend:a,divisor:s,output:i}));const n=t??[a,s].filter((e=>void 0!==e));if(n.length<2)throw new Error("- Not enough values provided");if(n.some((e=>"number"!=typeof e)))throw new Error("- Not all values are numbers");if(0===n[1])throw new Error("Division by zero!");switch(i){case"quotient":return Math.floor(n[0]/n[1]);case"remainder":return n[0]%n[1];default:return n[0]/n[1]}},parseChildren:J},Ae=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array"},{name:"strict",description:"Whether value must be strictly greater than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean"}],Ee=j(Ae),Se={description:"Test if a value is greater than (or equal to) another value",aliases:[">","greaterThan","higher","larger"],parameters:Ae},Oe={propertyAliases:Ee,operatorData:Se,evaluate:async(e,r)=>{const[t,a=!0]=await G([e.values,e.strict],r);if(r.typeChecker(R(Se.parameters,{values:t,strict:a})),t.length<2)throw new Error("- Not enough values provided");const[s,i]=t;return s===i&&!a||s>i},parseChildren:J},Ne=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array"},{name:"strict",description:"Whether value must be strictly smaller than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean"}],Pe=j(Ne),xe={description:"Test if a value is smaller than (or equal to) another value",aliases:["<","lessThan","lower","smaller"],parameters:Ne},Ue={propertyAliases:Pe,operatorData:xe,evaluate:async(e,r)=>{const[t,a=!0]=await G([e.values,e.strict],r);if(r.typeChecker(R(xe.parameters,{values:t,strict:a})),t.length<2)throw new Error("- Not enough values provided");const[s,i]=t;return s===i&&!a||s<i},parseChildren:J},je=[{name:"condition",description:"The expression to check for truthiness",aliases:[],required:!0,type:"any"},{name:"valueIfTrue",description:"Value to return if condition is true",aliases:["ifTrue"],required:!0,type:"any"},{name:"valueIfFalse",description:"Value to return if condition is false",aliases:["ifFalse","ifNot"],required:!0,type:"any"}],Re=j(je),Ie={description:"Return a value based on a condition",aliases:["?","conditional","ifThen"],parameters:je},Le={propertyAliases:Re,operatorData:Ie,evaluate:async(e,r)=>{r.typeChecker(R(Ie.parameters,{condition:e.condition,valueIfTrue:e.valueIfTrue,valueIfFalse:e.valueIfFalse}));return await F(e.condition,r)?await F(e.valueIfTrue,r):await F(e.valueIfFalse,r)},parseChildren:e=>{const[r,t,a]=e.children;return{...e,condition:r,valueIfTrue:t,valueIfFalse:a}}},ke=[{name:"testString",description:"The string to test",aliases:["string","value"],required:!0,type:"string"},{name:"pattern",description:"The regular expression pattern",aliases:["regex","regexp","regExp","re"],required:!0,type:"string"}],De=j(ke),_e={description:"Compare a string against a regex pattern",aliases:["regex","patternMatch","regexp","matchPattern"],parameters:ke},Me={propertyAliases:De,operatorData:_e,evaluate:async(e,r)=>{const[t,a]=await G([e.testString,e.pattern],r);r.typeChecker(R(_e.parameters,{testString:t,pattern:a}));try{return new RegExp(a).test(t)}catch(e){throw new Error("Regex error:"+f(e))}},parseChildren:e=>{const[r,t]=e.children;return{...e,testString:r,pattern:t}}},He=[{name:"property",description:'The path to the required property (e.g. "user.firstName")',aliases:["path","propertyName"],required:!0,type:"string"},{name:"additionalData",description:"Additional data objects to be considered",aliases:["additional","objects","data","additionalObjects"],required:!1,type:"object"}],Fe=j(He),Ge={description:"Extract values from data objects",aliases:["dataProperties","data","getData","objectProperties","objProps","getProperty","getObjProp"],parameters:He},Qe={propertyAliases:Fe,operatorData:Ge,evaluate:async(e,r)=>{const[a,s]=await G([e.property,e.additionalData],r);r.typeChecker(R(Ge.parameters,{property:a,additionalData:s}));const i=s?{...r.options?.data??{},...s}:r.options?.data??{};return t(i,a)},parseChildren:e=>{const[r,t]=e.children,a={...e,property:r};return void 0!==t&&(a.fallback=t),a}},$e=[{name:"string",description:"A parameterised (%1, %2) string where the parameters are to be replaced",aliases:[],required:!0,type:"string"},{name:"substitutions",description:"An array of substitution values for the parameterised string",aliases:["replacements","values"],required:!0,type:["array","object"]},{name:"trimWhiteSpace",description:"Whether or not to trim white space from either end of the substituted strings (default: true)",aliases:["trim","trimWhitespace"],required:!1,type:"boolean"},{name:"substitutionCharacter",description:'Which character to search for in original string for replacement -- can be "%" or "$" (default: "%")',aliases:["subCharacter","subChar"],required:!1,type:"string"},{name:"numberMapping",description:"Rules for mapping number values to text strings, such as pluralisation.",aliases:["numMap","numberMap","pluralisation","pluralization","plurals"],required:!1,type:"object"}],Be=j($e),We={description:"Replace values in a string using simple parameter substitution",aliases:["stringSubstitution","substitute","stringSub","replace"],parameters:$e},ze={propertyAliases:Be,operatorData:We,evaluate:async(e,r)=>{const[t,a,s=!0,i="%",n={}]=await G([e.string,e.substitutions,e.trimWhiteSpace,e.substitutionCharacter,e.numberMapping],r);if(r.typeChecker(R(We.parameters,{string:t,substitutions:a,trimWhiteSpace:s,substitutionCharacter:i,numberMapping:n})),Array.isArray(a)){const e="$"===i?"$":"%",r=new RegExp(`(?<!\\\\)(${"%"===e?"%":"\\$"}[\\d]+)`,"g"),n=(t.match(r)||[]).sort(((e,r)=>Number(e.slice(1))-Number(r.slice(1)))),o=new Set(n),u=I(Array.from(o),a.map((e=>s?String(e).trim():e)));return t.split(r).map((e=>e in u?u[e]:e)).join("").replace(`\\${e}`,e)}return t.split(/(?<!\\)({{[A-z0-9_]+}})/g).map((e=>{if(!/(?<!\\){{(.+)}}/.exec(e))return e.replace("\\{{","{{");const r=Je(e,a,n);return s?String(r).trim():r})).join("")},parseChildren:e=>{const[r,...t]=e.children;return{...e,string:r,substitutions:t}}},Je=(e,r,t)=>{const a=e.replace(/{{(.+)}}/,"$1"),s=r?.[a]??"";if("number"!=typeof s)return r?.[a]??"";if(!(a in t))return s;const i=t[a];if(s in i)return i[s].replace("{}",String(s));const n=Object.keys(t[a]),o=n.find((e=>e.startsWith(">")));if(o){if(s>Number(o.slice(1)))return i?.[o]}const u=n.find((e=>e.startsWith("<")));if(u){if(s<Number(u.slice(1)))return i?.[u]}return i.other?i.other.replace("{}",String(s)):s},Ve=[{name:"values",description:"An array to count",aliases:[],required:!0,type:"array"}],Xe=j(Ve),Ye={description:"Count elements in an array",aliases:["count","length"],parameters:Ve},Ke={propertyAliases:Xe,operatorData:Ye,evaluate:async(e,r)=>{const t=await G(e.values,r);return r.typeChecker(R(Ye.parameters,{values:t})),t.length},parseChildren:e=>{const[r]=e.children;return{...e,values:r}}},Ze=[{name:"value",description:"The string to be split",aliases:["string"],required:!0,type:"string"},{name:"delimiter",description:"The value to split the string on (default is white space)",aliases:["separator"],required:!1,type:"string"},{name:"trimWhiteSpace",description:"Whether to trim white space from around the resulting elements (default: true)",aliases:["trim","trimWhitespace"],required:!1,type:"boolean"},{name:"excludeTrailing",description:"If the input string ends in a delimiter, there will be an additional blank element if this value is false (default: true)",aliases:["removeTrailing","excludeTrailingDelimiter"],required:!1,type:"boolean"}],er=j(Ze),rr={description:"Split a string into an array",aliases:["split","arraySplit"],parameters:Ze},tr=" ",ar={propertyAliases:er,operatorData:rr,evaluate:async(e,r)=>{const[t,a,s,i]=await G([e.value,e.delimiter??tr,e.trimWhiteSpace??!0,e.excludeTrailing??!0],r);r.typeChecker(R(rr.parameters,{value:t,delimiter:a,trimWhiteSpace:s,excludeTrailing:i}));let n=t.split(a);return s&&(n=n.map((e=>e.trim()))),i&&""===n[n.length-1]&&n.pop(),n},parseChildren:e=>{const[r,t=tr]=e.children;return{...e,value:r,delimiter:t}}},sr=[{name:"query",description:"A SQL query string, with parameterised replacements (i.e. $1, $2, etc)",aliases:[],required:!0,type:"string"},{name:"values",description:"An array of values to replace in the SQL string parameters",aliases:["replacements"],required:!1,type:"array"},{name:"type",description:"Determines the shape of the resulting data (see documentation)",aliases:["queryType"],required:!1,type:{literal:["array","string","number"]}},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],ir=j(sr),nr={description:"Query a Postgres database using node-postgres",aliases:["pgSql","sql","postgres","pg","pgDb"],parameters:sr},or=async(e,r,t,a)=>{const s={text:e,values:r,rowMode:a?"array":""},i=await t.query(s);if(i?.error)throw new Error(i.error);switch(a){case"array":return i.rows.flat();case"string":return i.rows.flat().join(" ");case"number":{const e=i.rows.flat();return Number.isNaN(Number(e))?e:Number(e)}default:return i.rows}},ur={propertyAliases:ir,operatorData:nr,evaluate:async(e,r)=>{const[t,a,s,i]=await G([e.query,e.type,e.values||[],e.useCache],r);if(r.typeChecker(R(nr.parameters,{query:t,type:a,values:s,useCache:i})),!r.options?.pgConnection)throw new Error("No Postgres database connection provided");const n=e.useCache??r.options.useCache??!0;return r.cache.useCache(n,(async(e,t,a)=>await or(e,a,r.options.pgConnection,t)),t,a,s)},parseChildren:e=>{const[r,...t]=e.children;return{...e,query:r,values:t}}},lr=[{name:"query",description:"GraphQL query string",aliases:[],required:!0,type:"string"},{name:"url",description:"Endpoint for the GraphQL request (if not already provided in options)",aliases:["endpoint"],required:!1,type:["string","null"]},{name:"headers",description:"HTTP Headers (if not already provided in options)",aliases:[],required:!1,type:"object"},{name:"variables",description:"Values for the variables used in query (key-value pairs)",aliases:[],required:!1,type:"object"},{name:"returnNode",description:"Property path to extract from the query response",aliases:["outputNode","returnProperty"],required:!1,type:"string"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],pr=j(lr),cr={description:"GraphQL request",aliases:["graphQl","graphql","gql"],parameters:lr},dr={propertyAliases:pr,operatorData:cr,evaluate:async(e,r)=>{const[t,a,s,i,n,o]=await G([e.query,e.url,e.variables,e.returnNode,e.headers,e.useCache],r),{url:u,headers:l}=a instanceof Object?a:{url:a,headers:null};r.typeChecker([...R(cr.parameters,{url:u,query:t,variables:s,returnNode:i,headers:n,useCache:o}),{name:"headers",value:l,expectedType:["object","null"]}]);const p=u&&"graphqlendpoint"!==u.toLowerCase()?u:"",c=r.options.graphQLConnection?.endpoint??r.options.baseEndpoint??"",d=_(p)?p:M(c,p),h={query:t,variables:s},m=o??r.options.useCache??!0,y=await r.cache.useCache(m,(async(e,r,t,a)=>{const s=await H({url:e,method:"post",data:r,headers:t});return D(s.data,a)}),d,h,{...r.options.graphQLConnection?.headers,...r.options?.headers,...l,...n},i);return y},parseChildren:async(e,r)=>{const[t,a="",s,...i]=await G(e.children,r),n=Array.isArray(s)?s:[s],o=i.slice(0,n.length),u=I(n,o),l={...e,query:t,url:a,variables:u};return i.length>n.length&&(l.returnNode=i.pop()),l}},hr=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string"},{name:"returnProperty",description:"Property from request result",aliases:["outputProperty"],required:!1,type:"string"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object"},{name:"parameters",description:"Query parameters (key-value)",aliases:["queryParams","queryParameters","urlQueries"],required:!1,type:"object"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],mr=j(hr),yr={description:"HTTP GET Request",aliases:["get","api"],parameters:hr},fr=async(e,r)=>{const[t="",a,...s]=await G(e.children,r),i=Array.isArray(a)?a:[a],n=s.slice(0,i.length),o=I(i,n),u={...e,url:t,parameters:o};return s.length>i.length&&(u.returnProperty=s.pop()),u},gr=fr,vr={propertyAliases:mr,operatorData:yr,evaluate:async(e,r)=>{const[t,a,s,i,n]=await G([e.url,e.parameters,e.returnProperty,e.headers,e.useCache],r),{url:o,headers:u}=t instanceof Object?t:{url:t,headers:null};r.typeChecker([...R(yr.parameters,{url:o,returnProperty:s,headers:i,parameters:a,useCache:n}),{name:"headers",value:u,expectedType:["object","null"]}]);const l=r.options.baseEndpoint??"",p={...r.options?.headers,...u,...i},c=n??r.options.useCache??!0,d=await r.cache.useCache(c,(async(e,r,t,a)=>{const s=await H({url:e,params:r,headers:t});return D(s,a)}),_(o)?o:M(l,o),a,p,s);return d},parseChildren:fr},br=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string"},{name:"returnProperty",description:"Property path from request result",aliases:["outputProperty"],required:!1,type:"string"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object"},{name:"parameters",description:"JSON Body parameters (key-value)",aliases:["bodyJson","data"],required:!1,type:"object"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],Tr=j(br),Cr={description:"HTTP POST Request",aliases:["post"],parameters:br},wr={propertyAliases:Tr,operatorData:Cr,evaluate:async(e,r)=>{const[t,a,s,i,n]=await G([e.url,e.parameters,e.returnProperty,e.headers,e.useCache],r),{url:o,headers:u}=t instanceof Object?t:{url:t,headers:null};r.typeChecker([...R(Cr.parameters,{url:o,headers:i,data:a,returnProperty:s,useCache:n}),{name:"headers",value:u,expectedType:["object","null"]}]);const l=r.options.baseEndpoint??"",p={...r.options?.headers,...u,...i},c=n??r.options.useCache??!0;return await r.cache.useCache(c,(async()=>{const e=await H({url:o,data:a,headers:i,method:"post"});return D(e,s)}),_(o)?o:M(l,o),a,p,s)},parseChildren:gr},qr=[{name:"properties",description:'An array of objects, each with a "key" property and a "value" property',aliases:["values","keyValPairs","keyValuePairs"],required:!0,type:"array"}],Ar=j(qr),Er={description:"Construct an object using objects defining keys and values",aliases:["buildObject","build","object"],parameters:qr},Sr={propertyAliases:Ar,operatorData:Er,evaluate:async(e,r)=>{r.typeChecker(R(Er.parameters,{properties:e.properties}));const t=e.properties.filter((e=>e instanceof Object&&"key"in e&&"value"in e)).map((({key:e,value:t})=>(async e=>{const[t,a]=await G(e,r);return r.typeChecker({name:"key",value:t,expectedType:["string","number","boolean"]}),[t,a]})([e,t])));return Object.fromEntries(await Promise.all(t))},parseChildren:e=>{const r=e.children;if(r.length%2!=0)throw new Error("Even number of children required to make key/value pairs");const t=r.filter(((e,r)=>r%2==0)),a=r.filter(((e,r)=>r%2==1)),s=t.map(((e,r)=>({key:e,value:a[r]})));return{...e,properties:s}}},Or=[{name:"matchExpression",description:"Expression to match against",aliases:["match"],required:!0,type:["string","number","boolean"]},{name:"branches",description:"Object whose keys are compared against the match expression. The value of the matching key is returned",aliases:["arms","cases"],required:!1,type:["object","array"]}],Nr={propertyAliases:j(Or),operatorData:{description:"Return different values depending on a matching expression",aliases:["match","switch"],parameters:Or},evaluate:async(e,r)=>{const t=await F(e.matchExpression,r);r.typeChecker({name:"matchExpression",value:t,expectedType:["string","number","boolean"]});const a=Array.isArray(e.branches)?L(e.branches):e.branches??{},i=s(a)?await F(a,r):a;if(!v(i))throw new Error("Branches don't evaluate to an object");if(t in i)return await F(i[t],r);if("fallback"in i)return await F(i.fallback,r);if(t in e)return await F(e[t],r);throw new Error(`No match found for ${t}`)},parseChildren:async(e,r)=>{const[t,...a]=e.children,s=L(await G(a,r));return{...e,matchExpression:t,branches:s}}},Pr=[{name:"functionPath",description:"Path (in options.functions) to the required function",aliases:["functionsPath","functionName","funcName","path","name"],required:!0,type:"string"},{name:"args",description:"Arguments for the function",aliases:["arguments","variables"],required:!1,type:"array"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],xr=j(Pr),Ur={description:"Call a custom function (defined in options)",aliases:["customFunctions","customFunction","objectFunctions","function","functions","runFunction"],parameters:Pr},jr={propertyAliases:xr,operatorData:Ur,evaluate:async(e,r)=>{const[a,s=[],i]=await G([e.functionPath,e.args,e.useCache],r);r.typeChecker(R(Ur.parameters,{functionPath:a,args:s}));const{data:n,functions:o}=r.options,u=t(o,a,null)??t(n,a,null)??t(r.options,a,null);if(!u||"function"!=typeof u)throw new Error(`- No function found: "${a}"`);const l=i??r.options.useCache??!1;return await r.cache.useCache(l,(async(e,...r)=>await u(...r)),a,...s)},parseChildren:e=>{const[r,...t]=e.children;return{...e,functionPath:r,args:t}}},Rr=[{name:"value",description:"Value to pass through",aliases:["_","data"],required:!0,type:"any"}],Ir=j(Rr),Lr={description:"Pass through a value unchanged (or change its type)",aliases:["_","passThru","passthru","pass","ignore","coerce","convert"],parameters:Rr},kr={propertyAliases:Ir,operatorData:Lr,evaluate:async(e,r)=>(r.typeChecker(R(Lr.parameters,{value:e.value})),await F(e.value,r)),parseChildren:e=>{const[...r]=e.children,t=1===r?.length?r[0]:r;return{...e,value:t}}};var Dr=Object.freeze({__proto__:null,AND:V,BUILD_OBJECT:Sr,CONDITIONAL:Le,COUNT:Ke,CUSTOM_FUNCTIONS:jr,DIVIDE:qe,EQUAL:ae,GET:vr,GRAPHQL:dr,GREATER_THAN:Oe,LESS_THAN:Ue,MATCH:Nr,MULTIPLY:be,NOT_EQUAL:oe,OBJECT_PROPERTIES:Qe,OR:Z,PASSTHRU:kr,PG_SQL:ur,PLUS:ce,POST:wr,REGEX:Me,SPLIT:ar,STRING_SUBSTITUTION:ze,SUBTRACT:ye});class _r{store;queue;maxSize;maxTime;constructor(e){this.store={},this.queue=[],this.maxSize=e?.maxSize??50,this.maxTime=e?.maxTime??1800}useCache=async(e,r,...t)=>{if(!e)return await r(...t);const a=Mr(t),s=a in this.store,i=Date.now(),n=s&&i-this.store[a].timestamp>1e3*this.maxTime;if(s)return this.queue=this.queue.filter((e=>e!==a)),this.queue.unshift(a),this.store[a].timestamp=i,n&&(this.store[a].result=await r(...t)),this.store[a].result;const o=await r(...t);return this.store[a]={result:o,timestamp:i},this.queue.unshift(a),this.resizeCache(),o};getMax=()=>this.maxSize;setMax=e=>{this.maxSize=e,this.resizeCache()};getMaxTime=()=>this.maxTime;setMaxTime=e=>{this.maxTime=e};getCache=()=>this.store;setCache=e=>this.store=e;resizeCache=()=>{if(this.queue.length>this.maxSize){this.queue.slice(this.maxSize).forEach((e=>delete this.store[e])),this.queue=this.queue.slice(0,this.maxSize)}}}const Mr=e=>e.map((e=>"object"==typeof e?JSON.stringify(e):e)).join("_");class Hr{options;operators;operatorAliases;cache;constructor(e={}){this.options=Fr(e),this.operators=u(Dr,this.options?.excludeOperators??[],b),this.operatorAliases=b,this.cache=new _r({maxSize:e.maxCacheSize,maxTime:e.maxCacheTime})}typeChecker=(...e)=>{const r=1===e.length&&Array.isArray(e[0])?e[0]:e,t=N(...r);if(!0!==t)throw new Error(t)};async evaluate(e,r={}){const t=m(this.options,Fr(r));return t.maxCacheSize&&t.maxCacheSize!==this.cache.getMax()&&this.cache.setMax(t.maxCacheSize),t.maxCacheTime&&t.maxCacheTime!==this.cache.getMaxTime()&&this.cache.setMaxTime(t.maxCacheTime),await F(e,{options:t,operators:r.excludeOperators?u(Dr,r.excludeOperators,b):this.operators,operatorAliases:this.operatorAliases,typeChecker:t.skipRuntimeTypeCheck?()=>{}:this.typeChecker,resolvedAliasNodes:{},cache:this.cache})}getOptions(){return this.options}updateOptions(e){this.options=m(this.options,Fr(e)),this.options.excludeOperators&&(this.operators=u(Dr,this.options.excludeOperators,b))}getCache=()=>this.cache.getCache();setCache=e=>this.cache.setCache(e);getOperators(){const e=this.options.excludeOperators?u(Dr,this.options.excludeOperators,b):this.operators;return Object.entries(e).map((([e,r])=>({operator:e,...r.operatorData})))}getFragments(){return Object.entries(this.options.fragments??{}).map((([e,r])=>({name:e,...r?.metadata})))}getCustomFunctions(){return Object.entries(this.options.functions??{}).map((([e,r])=>({name:e,numRequiredArgs:r.length})))}getVersion=()=>"2.11.0"}const Fr=e=>"objects"in e?{...e,data:e.objects}:e;exports.FigTreeEvaluator=Hr,exports.evaluateExpression=(e,r)=>new Hr(r).evaluate(e);
|
package/build/index.d.ts
CHANGED
|
@@ -1,4 +1,121 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { Client } from 'pg';
|
|
2
|
+
|
|
3
|
+
interface Store {
|
|
4
|
+
[key: string]: {
|
|
5
|
+
result: EvaluatorOutput;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface GraphQLConnection {
|
|
11
|
+
endpoint: string;
|
|
12
|
+
headers?: {
|
|
13
|
+
[key: string]: string;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
declare const operatorAliases: OperatorAliases;
|
|
18
|
+
|
|
19
|
+
type BasicType = 'any' | 'string' | 'boolean' | 'number' | 'array' | 'object' | 'null' | 'undefined';
|
|
20
|
+
type LiteralType = {
|
|
21
|
+
literal: (string | undefined)[];
|
|
22
|
+
};
|
|
23
|
+
type ExpectedType = BasicType | LiteralType | BasicType[];
|
|
24
|
+
|
|
25
|
+
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"];
|
|
26
|
+
type Operator = (typeof Operators)[number];
|
|
27
|
+
type OperatorAlias = keyof typeof operatorAliases;
|
|
28
|
+
type OperatorAliases = Record<string, Operator>;
|
|
29
|
+
type Fragments = Record<string, Fragment>;
|
|
30
|
+
type UnknownFunction = (...args: any[]) => EvaluatorOutput;
|
|
31
|
+
interface FigTreeOptions {
|
|
32
|
+
data?: object;
|
|
33
|
+
objects?: object;
|
|
34
|
+
functions?: Record<string, UnknownFunction>;
|
|
35
|
+
fragments?: Fragments;
|
|
36
|
+
pgConnection?: Client;
|
|
37
|
+
graphQLConnection?: GraphQLConnection;
|
|
38
|
+
baseEndpoint?: string;
|
|
39
|
+
headers?: {
|
|
40
|
+
[key: string]: string;
|
|
41
|
+
};
|
|
42
|
+
returnErrorAsString?: boolean;
|
|
43
|
+
nullEqualsUndefined?: boolean;
|
|
44
|
+
allowJSONStringInput?: boolean;
|
|
45
|
+
noShorthand?: boolean;
|
|
46
|
+
skipRuntimeTypeCheck?: boolean;
|
|
47
|
+
evaluateFullObject?: boolean;
|
|
48
|
+
excludeOperators?: OperatorAlias[];
|
|
49
|
+
useCache?: boolean;
|
|
50
|
+
maxCacheSize?: number;
|
|
51
|
+
maxCacheTime?: number;
|
|
52
|
+
supportDeprecatedValueNodes?: boolean;
|
|
53
|
+
}
|
|
54
|
+
type OutputType = 'string' | 'number' | 'boolean' | 'bool' | 'array';
|
|
55
|
+
interface OperatorNode {
|
|
56
|
+
operator: OperatorAlias;
|
|
57
|
+
outputType?: OutputType;
|
|
58
|
+
children?: EvaluatorNode[];
|
|
59
|
+
fallback?: EvaluatorNode;
|
|
60
|
+
useCache?: boolean;
|
|
61
|
+
[key: string]: EvaluatorNode;
|
|
62
|
+
}
|
|
63
|
+
interface FragmentNode {
|
|
64
|
+
fragment: string;
|
|
65
|
+
parameters?: Record<string, EvaluatorNode>;
|
|
66
|
+
[key: string]: EvaluatorNode;
|
|
67
|
+
}
|
|
68
|
+
interface FragmentMetadata {
|
|
69
|
+
description?: string;
|
|
70
|
+
parameters?: Record<string, {
|
|
71
|
+
type: string | string[];
|
|
72
|
+
required: boolean;
|
|
73
|
+
}>;
|
|
74
|
+
}
|
|
75
|
+
type Fragment = (EvaluatorNode & {
|
|
76
|
+
metadata?: FragmentMetadata;
|
|
77
|
+
}) | null;
|
|
78
|
+
type EvaluatorOutput = string | boolean | number | object | null | undefined | Array<EvaluatorOutput>;
|
|
79
|
+
type EvaluatorNode = OperatorNode | FragmentNode | EvaluatorOutput;
|
|
80
|
+
type Parameter = {
|
|
81
|
+
name: string;
|
|
82
|
+
description: string;
|
|
83
|
+
aliases: string[];
|
|
84
|
+
required: boolean;
|
|
85
|
+
type: ExpectedType;
|
|
86
|
+
};
|
|
87
|
+
interface OperatorData {
|
|
88
|
+
description: string;
|
|
89
|
+
aliases: string[];
|
|
90
|
+
parameters: Parameter[];
|
|
91
|
+
}
|
|
92
|
+
interface OperatorMetadata extends OperatorData {
|
|
93
|
+
operator: Operator;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
declare class FigTreeEvaluator {
|
|
97
|
+
private options;
|
|
98
|
+
private operators;
|
|
99
|
+
private operatorAliases;
|
|
100
|
+
private cache;
|
|
101
|
+
constructor(options?: FigTreeOptions);
|
|
102
|
+
private typeChecker;
|
|
103
|
+
evaluate(expression: EvaluatorNode, options?: FigTreeOptions): Promise<EvaluatorOutput>;
|
|
104
|
+
getOptions(): FigTreeOptions;
|
|
105
|
+
updateOptions(options: FigTreeOptions): void;
|
|
106
|
+
getCache: () => Store;
|
|
107
|
+
setCache: (cache: Store) => Store;
|
|
108
|
+
getOperators(): readonly OperatorMetadata[];
|
|
109
|
+
getFragments(): readonly (FragmentMetadata & {
|
|
110
|
+
name: string;
|
|
111
|
+
})[];
|
|
112
|
+
getCustomFunctions(): readonly {
|
|
113
|
+
name: string;
|
|
114
|
+
numRequiredArgs: number;
|
|
115
|
+
}[];
|
|
116
|
+
getVersion: () => string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
declare const evaluateExpression: (expression: EvaluatorNode, options?: FigTreeOptions) => Promise<EvaluatorOutput>;
|
|
120
|
+
|
|
121
|
+
export { EvaluatorNode, EvaluatorOutput, FigTreeEvaluator, FigTreeOptions, Operator, evaluateExpression };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{camelCase as e}from"change-case";import r from"axios";import t from"object-property-extractor";import{dequal as a}from"dequal/lite";const s=e=>e instanceof Object&&"operator"in e,i=e=>e instanceof Object&&"fragment"in e,n=r=>{const t=e(r);return t||r},o=(e,r)=>r[n(e)],u=(e,r,t)=>{const a={...e};return r.forEach((e=>{t[n(e)]||console.warn(`Invalid operator exclusion: ${e}`),delete a[t[n(e)]]})),a},l=(e,r=200)=>e.length<r?e:`${e.slice(0,r-2).trim()}...`,p=(e,r,t=!1)=>{if(void 0!==e)return e;if(t)return l(r);throw new Error(l(r))},c=(e,r)=>{const t=Object.entries(e).map((([e,t])=>[r(e),t]));return Object.fromEntries(t)},d=e=>/^\$.+/.test(e),h=(e,{resolvedAliasNodes:r})=>"string"==typeof e&&d(e)?r?.[e]??e:e,m=(e,r)=>{const t={...e,...r};return(e.data||r.data)&&(t.data={...e.data,...r.data}),(e.functions||r.functions)&&(t.functions={...e.functions,...r.functions}),(e.fragments||r.fragments)&&(t.fragments={...e.fragments,...r.fragments}),(e.headers||r.headers)&&(t.headers={...e.headers,...r.headers}),t},y={number:e=>g(e),string:e=>String(e),array:e=>Array.isArray(e)?e:[e],boolean:e=>Boolean(e),bool:e=>Boolean(e)},f=e=>e.message,g=e=>{if("string"!=typeof e)return Number.isNaN(Number(e))?e:Number(e);const r=new RegExp(/-?\d*\.?\d+/gm),t=e.match(r);return t?Number(t[0]):0},v=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),b={and:"AND","&":"AND","&&":"AND",or:"OR","|":"OR","||":"OR","=":"EQUAL",eq:"EQUAL",equal:"EQUAL",equals:"EQUAL","!=":"NOT_EQUAL","!":"NOT_EQUAL",ne:"NOT_EQUAL",notEqual:"NOT_EQUAL","+":"PLUS",plus:"PLUS",add:"PLUS",concat:"PLUS",join:"PLUS",merge:"PLUS","-":"SUBTRACT",subtract:"SUBTRACT",minus:"SUBTRACT",takeaway:"SUBTRACT","*":"MULTIPLY",x:"MULTIPLY",multiply:"MULTIPLY",times:"MULTIPLY","/":"DIVIDE",divide:"DIVIDE","÷":"DIVIDE",">":"GREATER_THAN",greaterThan:"GREATER_THAN",higher:"GREATER_THAN",larger:"GREATER_THAN","<":"LESS_THAN",lessThan:"LESS_THAN",lower:"LESS_THAN",smaller:"LESS_THAN","?":"CONDITIONAL",conditional:"CONDITIONAL",ifThen:"CONDITIONAL",regex:"REGEX",patternMatch:"REGEX",regexp:"REGEX",matchPattern:"REGEX",dataProperties:"OBJECT_PROPERTIES",data:"OBJECT_PROPERTIES",getData:"OBJECT_PROPERTIES",objectProperties:"OBJECT_PROPERTIES",objProps:"OBJECT_PROPERTIES",getProperty:"OBJECT_PROPERTIES",getObjProp:"OBJECT_PROPERTIES",stringSubstitution:"STRING_SUBSTITUTION",substitute:"STRING_SUBSTITUTION",stringSub:"STRING_SUBSTITUTION",replace:"STRING_SUBSTITUTION",split:"SPLIT",arraySplit:"SPLIT",count:"COUNT",length:"COUNT",get:"GET",api:"GET",post:"POST",pgSql:"PG_SQL",sql:"PG_SQL",postgres:"PG_SQL",pg:"PG_SQL",pgDb:"PG_SQL",graphQl:"GRAPHQL",graphql:"GRAPHQL",gql:"GRAPHQL",buildObject:"BUILD_OBJECT",build:"BUILD_OBJECT",object:"BUILD_OBJECT",match:"MATCH",switch:"MATCH",customFunctions:"CUSTOM_FUNCTIONS",customFunction:"CUSTOM_FUNCTIONS",objectFunctions:"CUSTOM_FUNCTIONS",function:"CUSTOM_FUNCTIONS",functions:"CUSTOM_FUNCTIONS",runFunction:"CUSTOM_FUNCTIONS",_:"PASSTHRU",passThru:"PASSTHRU",passthru:"PASSTHRU",pass:"PASSTHRU",ignore:"PASSTHRU",coerce:"PASSTHRU",convert:"PASSTHRU"},T=b,C=/(\$[^()]+)\((.*)\)/,w=(e,r={},t=!0)=>t?"string"==typeof e?A(e,r):v(e)?q(e,r):e:e,A=(e,r)=>{const t=C.exec(e);if(!t)return e;const a=t[1].trim(),s=t[2].split(",").map((e=>w(e.trim(),r)));return E(a,s,r)},q=(e,r)=>{if(s(e)||i(e))return e;const t=Object.entries(e),a=t.filter((([e])=>d(e))),n=t.filter((([e])=>!d(e)));return{...a.reduce(((e,[t,a])=>e={...e,...E(t,a,r)}),{}),...Object.fromEntries(n)}},E=(e,r,t)=>{const a=e.slice(1),s=o(a,T);return s?Array.isArray(r)?{operator:s,children:r}:v(r)&&!Object.keys(r).some((e=>d(e)))?{operator:s,...r}:{operator:s,children:[r]}:a in t?{fragment:a,parameters:{...r}}:{[e]:r}},S=e=>v(e)&&"literal"in e,O=({value:e,name:r,expectedType:t})=>{if(S(t)){const{literal:a}=t;return!!a.includes(e)||x(r,e,`Literal(${a.map((e=>void 0===e?"undefined":`"${e}"`)).join(", ")})`)}if(Array.isArray(t))return!!t.some((t=>!0===O({value:e,name:r,expectedType:t})))||x(r,e,t.join("|"));return!!(0,P[t])(e)||x(r,e,t)},N=(...e)=>{const r=[];return e.forEach((e=>{const t=O(e);!0!==t&&r.push(t)})),!(r.length>0)||r.join("\n")},P={any:e=>void 0!==e,string:e=>"string"==typeof e,number:e=>"number"==typeof e,boolean:e=>"boolean"==typeof e,array:e=>Array.isArray(e),null:e=>null===e,object:e=>v(e),undefined:e=>void 0===e},x=(e,r,t)=>void 0===r&&e?`- Missing required property "${e}" (type: ${t})`:void 0!==e?`- Property "${e}" (value: ${U(r)}) is not of type: ${t}`:`- ${U(r)} is not of type: ${t}`,U=e=>{const r=void 0===e||Number.isNaN(e)?String(e):JSON.stringify(e);return l(r,50)},j=e=>{const r={};return e.forEach((e=>{e.aliases.forEach((t=>r[t]=e.name))})),r},R=(e,r)=>e.map((({name:e,required:t,type:a})=>{if(S(a)){const s=[...a.literal];return t||s.push(void 0),{name:e,value:r[e],expectedType:{literal:s}}}const s=Array.isArray(a)?a:[a];t||s.push("undefined");const i=1===s.length?s[0]:s;return{name:e,value:r[e],expectedType:i}})),I=(e,r)=>{const t=e.map(((e,t)=>[e,r[t]]));return Object.fromEntries(t)},L=e=>{if(e.length%2!=0)throw new Error("Even number of children required to make key/value pairs");const r=e.filter(((e,r)=>r%2==0)),t=N(...r.map((e=>({value:e,expectedType:["string","number","boolean"]}))));if(!0!==t)throw new Error(t);const a=e.filter(((e,r)=>r%2==1)),s={};return r.forEach(((e,r)=>{s[e]=a[r]})),s},k=e=>v(e)&&1===Object.keys(e).length?Object.values(e)[0]:e,D=(e,r,a=void 0)=>{const s=r?t(e,r,a):e;return Array.isArray(s)?s.map((e=>k(e))):r?null===s?null:k(s):s},_=e=>/^https?:\/\/.+/.test(e),M=(...e)=>e.reduce(((e,r,t)=>{const a="/"===r[0]?1:0,s="/"===r.slice(-1)?-1:void 0,i=r.slice(a,s);return""===i?e:e+(0===t?"":"/")+i}),""),H=async({url:e,params:t={},data:a={},headers:s={},method:i="get"})=>{try{return(await r({method:i,url:e,headers:{"Content-Type":"application/json",Accept:"application/json",...s},params:t,data:a})).data}catch(e){if(r.isAxiosError(e)){if(!e?.response)throw new Error("Network Error");console.log(e.response?.data)}throw e}},G=async(e,r)=>{const{options:t,operators:a,operatorAliases:n}=r;let u=t?.allowJSONStringInput?(e=>{if("string"!=typeof e)return e;try{const r=JSON.parse(e);return s(r)?r:e}catch(r){return e}})(e):e;u=w(u,r.options?.fragments,!t.noShorthand),Array.isArray(u)&&(u=await Q(u,r));const l=s(u),d=i(u);if(t.evaluateFullObject&&!l&&!d)return h(await B(u,r),r);if(!l&&!d)return t.supportDeprecatedValueNodes&&v(u)&&"value"in u?u.value:h(u,r);const{fallback:m}=u,g=t?.returnErrorAsString??!1;if(d){const[e,a]=await Q([u.fragment,u.parameters],r),i=w(t?.fragments?.[e],t.fragments,!t.noShorthand);if(void 0===i)return p(await G(m,r),`Fragment not defined: ${e}`,g);if(!s(i))return h(i,r);u={...u,...i,...a},delete u.fragment}try{const e=o(u.operator,n);if(!e)return p(await G(m,r),`Invalid operator: ${u.operator}`,g);if(!r.operators[e])return p(await G(m,r),`Excluded operator: ${u.operator}`,g);const{propertyAliases:t,evaluate:s,parseChildren:i}=a[e];u=((e,r)=>c(r,(r=>r in e?e[r]:r)))(t,u);const l=await $(u,r);d||Object.entries(l).forEach((([e,t])=>r.resolvedAliasNodes[e]=t));const h=d?{...r,resolvedAliasNodes:{...r.resolvedAliasNodes,...l}}:r;if("children"in u){if(Array.isArray(u.children)||(u.children=await G(u.children,h)),!Array.isArray(u.children))return p(await G(m,r),`Operator: ${e}\n- Property "children" is not of type: array`,g);u=await i(u,h),delete u.children}let v;try{v=await s(u,h)}catch(t){return p(await G(u.fallback,r),`Operator: ${e}\n${f(t)}`,g)}const b=u?.outputType??u?.type;if(!b)return v;const T=await G(b,r);return T in y?y[T](v):p(await G(m,r),`Operator: ${e}\n- Invalid output type: ${T}`,g)}catch(e){return p(await G(m,r),f(e),g)}},Q=async(e,r)=>Array.isArray(e)?await Promise.all(e.map((e=>G(e,r)))):await G(e,r),$=async(e,r)=>{const t=Object.keys(e).filter(d);if(0===t.length)return{};const a=[];return t.forEach((t=>a.push(G(e[t],r)))),I(t,await Promise.all(a))},B=async(e,r)=>{if(!v(e))return e;const t=[],a=[];Object.entries(e).forEach((([t,s])=>{d(t)&&(a.push(t,G(s,r)),delete e[t])}));const s=await Promise.all(a);r.resolvedAliasNodes={...r.resolvedAliasNodes,...L(s)},Object.entries(e).forEach((([e,a])=>{t.push(e,G(a,r))}));const i=await Promise.all(t);return h(L(i),r)},F=[{name:"values",description:"Returns true if all values are true",aliases:[],required:!0,type:"array"}],W=j(F),z={description:"Logical AND",aliases:["and","&","&&"],parameters:F},J=e=>{const r=e.children;return{...e,values:r}},V={propertyAliases:W,operatorData:z,evaluate:async(e,r)=>{const t=await Q(e.values,r);return r.typeChecker(R(z.parameters,{values:t})),t.reduce(((e,r)=>e&&!!r),!0)},parseChildren:J},X=[{name:"values",description:"Returns true if any values are true",aliases:[],required:!0,type:"array"}],Y=j(X),K={description:"Logical OR",aliases:["or","|","||"],parameters:X},Z={propertyAliases:Y,operatorData:K,evaluate:async(e,r)=>{const t=await Q(e.values,r);return r.typeChecker(R(K.parameters,{values:t})),t.reduce(((e,r)=>e||!!r),!1)},parseChildren:J},ee=[{name:"values",description:"Array of values to check for equality",aliases:[],required:!0,type:"array"},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value",aliases:[],required:!1,type:"boolean"}],re=j(ee),te={description:"Test multiple values are equal",aliases:["=","eq","equal","equals"],parameters:ee},ae={propertyAliases:re,operatorData:te,evaluate:async(e,r)=>{const[t,s]=await Q([e.values,e.nullEqualsUndefined],r);r.typeChecker(R(te.parameters,{values:t,nullEqualsUndefined:s}));return!(void 0!==s?s:void 0!==r.options?.nullEqualsUndefined&&r.options.nullEqualsUndefined)||null!==t[0]&&void 0!==t[0]?t.every((e=>a(e,t[0]))):t.every((e=>null==e))},parseChildren:J},se=[{name:"values",description:"Array of values to check for inequality",aliases:[],required:!0,type:"array"},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value",aliases:[],required:!1,type:"boolean"}],ie=j(se),ne={description:"Test if any values are different",aliases:["!=","!","ne","notEqual"],parameters:se},oe={propertyAliases:ie,operatorData:ne,evaluate:async(e,r)=>{const[t,s]=await Q([e.values,e.nullEqualsUndefined],r);r.typeChecker(R(ne.parameters,{values:t,nullEqualsUndefined:s}));return!(void 0!==s?s:void 0!==r.options?.nullEqualsUndefined&&r.options.nullEqualsUndefined)||null!==t[0]&&void 0!==t[0]?t.some((e=>!a(e,t[0]))):t.some((e=>null===e&&void 0===e))},parseChildren:J},ue=[{name:"values",description:"Array of values to check to add together",aliases:[],required:!0,type:"array"},{name:"type",description:"Data type to coerce input values to before addition",aliases:[],required:!1,type:{literal:["string","array","number","boolean","bool"]}}],le=j(ue),pe={description:"Add, concatenate or merge multiple values",aliases:["+","plus","add","concat","join","merge"],parameters:ue},ce={propertyAliases:le,operatorData:pe,evaluate:async(e,r)=>{const t=await Q(e.values,r);return r.typeChecker(R(pe.parameters,{values:t,type:e.type})),0===t.length?t:"string"===e?.type?t.reduce(((e,r)=>e.concat(r)),""):"array"===e?.type?t.reduce(((e,r)=>e.concat(r)),[]):t.every((e=>"string"==typeof e||Array.isArray(e)))?t.reduce(((e,r)=>e.concat(r))):t.every((e=>v(e)))?t.reduce(((e,r)=>({...e,...r})),{}):t.reduce(((e,r)=>e+r))},parseChildren:J},de=[{name:"values",description:"Array of values - 2nd element will be subtracted from the first",aliases:[],required:!1,type:"array"},{name:"from",description:"Numerical value that will be subtracted from",aliases:["subtractFrom"],required:!1,type:"number"},{name:"subtract",description:"Numerical value to subtract",aliases:[],required:!1,type:"number"}],he=j(de),me={description:"Subtract one numerical value from another",aliases:["-","subtract","minus","takeaway"],parameters:de},ye={propertyAliases:he,operatorData:me,evaluate:async(e,r)=>{const[t,a,s]=await Q([e.values,e.from,e.subtract],r);r.typeChecker(R(me.parameters,{values:t,from:a,subtract:s}));const i=t??[a,s].filter((e=>void 0!==e));if(i.length<2)throw new Error("- Not enough values provided");if(i.some((e=>"number"!=typeof e)))throw new Error("- Not all values are numbers");return i[0]-i[1]},parseChildren:J},fe=[{name:"values",description:"Array of values whose product will be calculated",aliases:[],required:!0,type:"array"}],ge=j(fe),ve={description:"Multiply several numerical values together",aliases:["*","x","multiply","times"],parameters:fe},be={propertyAliases:ge,operatorData:ve,evaluate:async(e,r)=>{const t=await Q(e.values,r);if(r.typeChecker(R(ve.parameters,{values:t})),0===t.length)return 0;if(t.some((e=>"number"!=typeof e)))throw new Error("- Not all values are numbers");return t.reduce(((e,r)=>e*r))},parseChildren:J},Te=[{name:"values",description:"Array of values - 1st element will be divided by the first",aliases:[],required:!1,type:"array"},{name:"dividend",description:"The number that will be divided",aliases:["divide"],required:!1,type:"number"},{name:"divisor",description:"The number that dividend will be divided by",aliases:["by","divideBy"],required:!1,type:"number"},{name:"output",description:"Whether to output a quotient, remainder or decimal",aliases:[],required:!1,type:{literal:["quotient","remainder"]}}],Ce=j(Te),we={description:"Divide one numerical value by another",aliases:["/","divide","÷"],parameters:Te},Ae={propertyAliases:Ce,operatorData:we,evaluate:async(e,r)=>{const[t,a,s,i]=await Q([e.values,e.dividend,e.divisor,e.output],r);r.typeChecker(R(we.parameters,{values:t,dividend:a,divisor:s,output:i}));const n=t??[a,s].filter((e=>void 0!==e));if(n.length<2)throw new Error("- Not enough values provided");if(n.some((e=>"number"!=typeof e)))throw new Error("- Not all values are numbers");if(0===n[1])throw new Error("Division by zero!");switch(i){case"quotient":return Math.floor(n[0]/n[1]);case"remainder":return n[0]%n[1];default:return n[0]/n[1]}},parseChildren:J},qe=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array"},{name:"strict",description:"Whether value must be strictly greater than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean"}],Ee=j(qe),Se={description:"Test if a value is greater than (or equal to) another value",aliases:[">","greaterThan","higher","larger"],parameters:qe},Oe={propertyAliases:Ee,operatorData:Se,evaluate:async(e,r)=>{const[t,a=!0]=await Q([e.values,e.strict],r);if(r.typeChecker(R(Se.parameters,{values:t,strict:a})),t.length<2)throw new Error("- Not enough values provided");const[s,i]=t;return s===i&&!a||s>i},parseChildren:J},Ne=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array"},{name:"strict",description:"Whether value must be strictly smaller than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean"}],Pe=j(Ne),xe={description:"Test if a value is smaller than (or equal to) another value",aliases:["<","lessThan","lower","smaller"],parameters:Ne},Ue={propertyAliases:Pe,operatorData:xe,evaluate:async(e,r)=>{const[t,a=!0]=await Q([e.values,e.strict],r);if(r.typeChecker(R(xe.parameters,{values:t,strict:a})),t.length<2)throw new Error("- Not enough values provided");const[s,i]=t;return s===i&&!a||s<i},parseChildren:J},je=[{name:"condition",description:"The expression to check for truthiness",aliases:[],required:!0,type:"any"},{name:"valueIfTrue",description:"Value to return if condition is true",aliases:["ifTrue"],required:!0,type:"any"},{name:"valueIfFalse",description:"Value to return if condition is false",aliases:["ifFalse","ifNot"],required:!0,type:"any"}],Re=j(je),Ie={description:"Return a value based on a condition",aliases:["?","conditional","ifThen"],parameters:je},Le={propertyAliases:Re,operatorData:Ie,evaluate:async(e,r)=>{r.typeChecker(R(Ie.parameters,{condition:e.condition,valueIfTrue:e.valueIfTrue,valueIfFalse:e.valueIfFalse}));return await G(e.condition,r)?await G(e.valueIfTrue,r):await G(e.valueIfFalse,r)},parseChildren:e=>{const[r,t,a]=e.children;return{...e,condition:r,valueIfTrue:t,valueIfFalse:a}}},ke=[{name:"testString",description:"The string to test",aliases:["string","value"],required:!0,type:"string"},{name:"pattern",description:"The regular expression pattern",aliases:["regex","regexp","regExp","re"],required:!0,type:"string"}],De=j(ke),_e={description:"Compare a string against a regex pattern",aliases:["regex","patternMatch","regexp","matchPattern"],parameters:ke},Me={propertyAliases:De,operatorData:_e,evaluate:async(e,r)=>{const[t,a]=await Q([e.testString,e.pattern],r);r.typeChecker(R(_e.parameters,{testString:t,pattern:a}));try{return new RegExp(a).test(t)}catch(e){throw new Error("Regex error:"+f(e))}},parseChildren:e=>{const[r,t]=e.children;return{...e,testString:r,pattern:t}}},He=[{name:"property",description:'The path to the required property (e.g. "user.firstName")',aliases:["path","propertyName"],required:!0,type:"string"},{name:"additionalData",description:"Additional data objects to be considered",aliases:["additional","objects","data","additionalObjects"],required:!1,type:"object"}],Ge=j(He),Qe={description:"Extract values from data objects",aliases:["dataProperties","data","getData","objectProperties","objProps","getProperty","getObjProp"],parameters:He},$e={propertyAliases:Ge,operatorData:Qe,evaluate:async(e,r)=>{const[a,s]=await Q([e.property,e.additionalData],r);r.typeChecker(R(Qe.parameters,{property:a,additionalData:s}));const i=s?{...r.options?.data??{},...s}:r.options?.data??{};return t(i,a)},parseChildren:e=>{const[r,t]=e.children,a={...e,property:r};return void 0!==t&&(a.fallback=t),a}},Be=[{name:"string",description:"A parameterised (%1, %2) string where the parameters are to be replaced",aliases:[],required:!0,type:"string"},{name:"substitutions",description:"An array of substitution values for the parameterised string",aliases:["replacements","values"],required:!0,type:["array","object"]},{name:"trimWhiteSpace",description:"Whether or not to trim white space from either end of the substituted strings (default: true)",aliases:["trim","trimWhitespace"],required:!1,type:"boolean"},{name:"substitutionCharacter",description:'Which character to search for in original string for replacement -- can be "%" or "$" (default: "%")',aliases:["subCharacter","subChar"],required:!1,type:"string"},{name:"numberMapping",description:"Rules for mapping number values to text strings, such as pluralisation.",aliases:["numMap","numberMap","pluralisation","pluralization","plurals"],required:!1,type:"object"}],Fe=j(Be),We={description:"Replace values in a string using simple parameter substitution",aliases:["stringSubstitution","substitute","stringSub","replace"],parameters:Be},ze={propertyAliases:Fe,operatorData:We,evaluate:async(e,r)=>{const[t,a,s=!0,i="%",n={}]=await Q([e.string,e.substitutions,e.trimWhiteSpace,e.substitutionCharacter,e.numberMapping],r);if(r.typeChecker(R(We.parameters,{string:t,substitutions:a,trimWhiteSpace:s,substitutionCharacter:i,numberMapping:n})),Array.isArray(a)){const e="$"===i?"$":"%",r=new RegExp(`(?<!\\\\)(${"%"===e?"%":"\\$"}[\\d]+)`,"g"),n=(t.match(r)||[]).sort(((e,r)=>Number(e.slice(1))-Number(r.slice(1)))),o=new Set(n),u=I(Array.from(o),a.map((e=>s?String(e).trim():e)));return t.split(r).map((e=>e in u?u[e]:e)).join("").replace(`\\${e}`,e)}return t.split(/(?<!\\)({{[A-z0-9_]+}})/g).map((e=>{if(!/(?<!\\){{(.+)}}/.exec(e))return e.replace("\\{{","{{");const r=Je(e,a,n);return s?String(r).trim():r})).join("")},parseChildren:e=>{const[r,...t]=e.children;return{...e,string:r,substitutions:t}}},Je=(e,r,t)=>{const a=e.replace(/{{(.+)}}/,"$1"),s=r?.[a]??"";if("number"!=typeof s)return r?.[a]??"";if(!(a in t))return s;const i=t[a];if(s in i)return i[s].replace("{}",String(s));const n=Object.keys(t[a]),o=n.find((e=>e.startsWith(">")));if(o){if(s>Number(o.slice(1)))return i?.[o]}const u=n.find((e=>e.startsWith("<")));if(u){if(s<Number(u.slice(1)))return i?.[u]}return i.other?i.other.replace("{}",String(s)):s},Ve=[{name:"values",description:"An array to count",aliases:[],required:!0,type:"array"}],Xe=j(Ve),Ye={description:"Count elements in an array",aliases:["count","length"],parameters:Ve},Ke={propertyAliases:Xe,operatorData:Ye,evaluate:async(e,r)=>{const t=await Q(e.values,r);return r.typeChecker(R(Ye.parameters,{values:t})),t.length},parseChildren:e=>{const[r]=e.children;return{...e,values:r}}},Ze=[{name:"value",description:"The string to be split",aliases:["string"],required:!0,type:"string"},{name:"delimiter",description:"The value to split the string on (default is white space)",aliases:["separator"],required:!1,type:"string"},{name:"trimWhiteSpace",description:"Whether to trim white space from around the resulting elements (default: true)",aliases:["trim","trimWhitespace"],required:!1,type:"boolean"},{name:"excludeTrailing",description:"If the input string ends in a delimiter, there will be an additional blank element if this value is false (default: true)",aliases:["removeTrailing","excludeTrailingDelimiter"],required:!1,type:"boolean"}],er=j(Ze),rr={description:"Split a string into an array",aliases:["split","arraySplit"],parameters:Ze},tr=" ",ar={propertyAliases:er,operatorData:rr,evaluate:async(e,r)=>{const[t,a,s,i]=await Q([e.value,e.delimiter??tr,e.trimWhiteSpace??!0,e.excludeTrailing??!0],r);r.typeChecker(R(rr.parameters,{value:t,delimiter:a,trimWhiteSpace:s,excludeTrailing:i}));let n=t.split(a);return s&&(n=n.map((e=>e.trim()))),i&&""===n[n.length-1]&&n.pop(),n},parseChildren:e=>{const[r,t=tr]=e.children;return{...e,value:r,delimiter:t}}},sr=[{name:"query",description:"A SQL query string, with parameterised replacements (i.e. $1, $2, etc)",aliases:[],required:!0,type:"string"},{name:"values",description:"An array of values to replace in the SQL string parameters",aliases:["replacements"],required:!1,type:"array"},{name:"type",description:"Determines the shape of the resulting data (see documentation)",aliases:["queryType"],required:!1,type:{literal:["array","string","number"]}},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],ir=j(sr),nr={description:"Query a Postgres database using node-postgres",aliases:["pgSql","sql","postgres","pg","pgDb"],parameters:sr},or=async(e,r,t,a)=>{const s={text:e,values:r,rowMode:a?"array":""},i=await t.query(s);if(i?.error)throw new Error(i.error);switch(a){case"array":return i.rows.flat();case"string":return i.rows.flat().join(" ");case"number":{const e=i.rows.flat();return Number.isNaN(Number(e))?e:Number(e)}default:return i.rows}},ur={propertyAliases:ir,operatorData:nr,evaluate:async(e,r)=>{const[t,a,s,i]=await Q([e.query,e.type,e.values||[],e.useCache],r);if(r.typeChecker(R(nr.parameters,{query:t,type:a,values:s,useCache:i})),!r.options?.pgConnection)throw new Error("No Postgres database connection provided");const n=e.useCache??r.options.useCache??!0;return r.cache.useCache(n,(async(e,t,a)=>await or(e,a,r.options.pgConnection,t)),t,a,s)},parseChildren:e=>{const[r,...t]=e.children;return{...e,query:r,values:t}}},lr=[{name:"query",description:"GraphQL query string",aliases:[],required:!0,type:"string"},{name:"url",description:"Endpoint for the GraphQL request (if not already provided in options)",aliases:["endpoint"],required:!1,type:["string","null"]},{name:"headers",description:"HTTP Headers (if not already provided in options)",aliases:[],required:!1,type:"object"},{name:"variables",description:"Values for the variables used in query (key-value pairs)",aliases:[],required:!1,type:"object"},{name:"returnNode",description:"Property path to extract from the query response",aliases:["outputNode","returnProperty"],required:!1,type:"string"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],pr=j(lr),cr={description:"GraphQL request",aliases:["graphQl","graphql","gql"],parameters:lr},dr={propertyAliases:pr,operatorData:cr,evaluate:async(e,r)=>{const[t,a,s,i,n,o]=await Q([e.query,e.url,e.variables,e.returnNode,e.headers,e.useCache],r),{url:u,headers:l}=a instanceof Object?a:{url:a,headers:null};r.typeChecker([...R(cr.parameters,{url:u,query:t,variables:s,returnNode:i,headers:n,useCache:o}),{name:"headers",value:l,expectedType:["object","null"]}]);const p=u&&"graphqlendpoint"!==u.toLowerCase()?u:"",c=r.options.graphQLConnection?.endpoint??r.options.baseEndpoint??"",d=_(p)?p:M(c,p),h={query:t,variables:s},m=o??r.options.useCache??!0,y=await r.cache.useCache(m,(async(e,r,t,a)=>{const s=await H({url:e,method:"post",data:r,headers:t});return D(s.data,a)}),d,h,{...r.options.graphQLConnection?.headers,...r.options?.headers,...l,...n},i);return y},parseChildren:async(e,r)=>{const[t,a="",s,...i]=await Q(e.children,r),n=Array.isArray(s)?s:[s],o=i.slice(0,n.length),u=I(n,o),l={...e,query:t,url:a,variables:u};return i.length>n.length&&(l.returnNode=i.pop()),l}},hr=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string"},{name:"returnProperty",description:"Property from request result",aliases:["outputProperty"],required:!1,type:"string"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object"},{name:"parameters",description:"Query parameters (key-value)",aliases:["queryParams","queryParameters","urlQueries"],required:!1,type:"object"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],mr=j(hr),yr={description:"HTTP GET Request",aliases:["get","api"],parameters:hr},fr=async(e,r)=>{const[t="",a,...s]=await Q(e.children,r),i=Array.isArray(a)?a:[a],n=s.slice(0,i.length),o=I(i,n),u={...e,url:t,parameters:o};return s.length>i.length&&(u.returnProperty=s.pop()),u},gr=fr,vr={propertyAliases:mr,operatorData:yr,evaluate:async(e,r)=>{const[t,a,s,i,n]=await Q([e.url,e.parameters,e.returnProperty,e.headers,e.useCache],r),{url:o,headers:u}=t instanceof Object?t:{url:t,headers:null};r.typeChecker([...R(yr.parameters,{url:o,returnProperty:s,headers:i,parameters:a,useCache:n}),{name:"headers",value:u,expectedType:["object","null"]}]);const l=r.options.baseEndpoint??"",p={...r.options?.headers,...u,...i},c=n??r.options.useCache??!0,d=await r.cache.useCache(c,(async(e,r,t,a)=>{const s=await H({url:e,params:r,headers:t});return D(s,a)}),_(o)?o:M(l,o),a,p,s);return d},parseChildren:fr},br=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string"},{name:"returnProperty",description:"Property path from request result",aliases:["outputProperty"],required:!1,type:"string"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object"},{name:"parameters",description:"JSON Body parameters (key-value)",aliases:["bodyJson","data"],required:!1,type:"object"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],Tr=j(br),Cr={description:"HTTP POST Request",aliases:["post"],parameters:br},wr={propertyAliases:Tr,operatorData:Cr,evaluate:async(e,r)=>{const[t,a,s,i,n]=await Q([e.url,e.parameters,e.returnProperty,e.headers,e.useCache],r),{url:o,headers:u}=t instanceof Object?t:{url:t,headers:null};r.typeChecker([...R(Cr.parameters,{url:o,headers:i,data:a,returnProperty:s,useCache:n}),{name:"headers",value:u,expectedType:["object","null"]}]);const l=r.options.baseEndpoint??"",p={...r.options?.headers,...u,...i},c=n??r.options.useCache??!0;return await r.cache.useCache(c,(async()=>{const e=await H({url:o,data:a,headers:i,method:"post"});return D(e,s)}),_(o)?o:M(l,o),a,p,s)},parseChildren:gr},Ar=[{name:"properties",description:'An array of objects, each with a "key" property and a "value" property',aliases:["values","keyValPairs","keyValuePairs"],required:!0,type:"array"}],qr=j(Ar),Er={description:"Construct an object using objects defining keys and values",aliases:["buildObject","build","object"],parameters:Ar},Sr={propertyAliases:qr,operatorData:Er,evaluate:async(e,r)=>{r.typeChecker(R(Er.parameters,{properties:e.properties}));const t=e.properties.filter((e=>e instanceof Object&&"key"in e&&"value"in e)).map((({key:e,value:t})=>(async e=>{const[t,a]=await Q(e,r);return r.typeChecker({name:"key",value:t,expectedType:["string","number","boolean"]}),[t,a]})([e,t])));return Object.fromEntries(await Promise.all(t))},parseChildren:e=>{const r=e.children;if(r.length%2!=0)throw new Error("Even number of children required to make key/value pairs");const t=r.filter(((e,r)=>r%2==0)),a=r.filter(((e,r)=>r%2==1)),s=t.map(((e,r)=>({key:e,value:a[r]})));return{...e,properties:s}}},Or=[{name:"matchExpression",description:"Expression to match against",aliases:["match"],required:!0,type:["string","number","boolean"]},{name:"branches",description:"Object whose keys are compared against the match expression. The value of the matching key is returned",aliases:["arms","cases"],required:!1,type:["object","array"]}],Nr={propertyAliases:j(Or),operatorData:{description:"Return different values depending on a matching expression",aliases:["match","switch"],parameters:Or},evaluate:async(e,r)=>{const t=await G(e.matchExpression,r);r.typeChecker({name:"matchExpression",value:t,expectedType:["string","number","boolean"]});const a=Array.isArray(e.branches)?L(e.branches):e.branches??{},i=s(a)?await G(a,r):a;if(!v(i))throw new Error("Branches don't evaluate to an object");if(t in i)return await G(i[t],r);if("fallback"in i)return await G(i.fallback,r);if(t in e)return await G(e[t],r);throw new Error(`No match found for ${t}`)},parseChildren:async(e,r)=>{const[t,...a]=e.children,s=L(await Q(a,r));return{...e,matchExpression:t,branches:s}}},Pr=[{name:"functionPath",description:"Path (in options.functions) to the required function",aliases:["functionsPath","functionName","funcName","path","name"],required:!0,type:"string"},{name:"args",description:"Arguments for the function",aliases:["arguments","variables"],required:!1,type:"array"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],xr=j(Pr),Ur={description:"Call a custom function (defined in options)",aliases:["customFunctions","customFunction","objectFunctions","function","functions","runFunction"],parameters:Pr},jr={propertyAliases:xr,operatorData:Ur,evaluate:async(e,r)=>{const[a,s=[],i]=await Q([e.functionPath,e.args,e.useCache],r);r.typeChecker(R(Ur.parameters,{functionPath:a,args:s}));const{data:n,functions:o}=r.options,u=t(o,a,null)??t(n,a,null)??t(r.options,a,null);if(!u||"function"!=typeof u)throw new Error(`- No function found: "${a}"`);const l=i??r.options.useCache??!1;return await r.cache.useCache(l,(async(e,...r)=>await u(...r)),a,...s)},parseChildren:e=>{const[r,...t]=e.children;return{...e,functionPath:r,args:t}}},Rr=[{name:"value",description:"Value to pass through",aliases:["_","data"],required:!0,type:"any"}],Ir=j(Rr),Lr={description:"Pass through a value unchanged (or change its type)",aliases:["_","passThru","passthru","pass","ignore","coerce","convert"],parameters:Rr},kr={propertyAliases:Ir,operatorData:Lr,evaluate:async(e,r)=>(r.typeChecker(R(Lr.parameters,{value:e.value})),await G(e.value,r)),parseChildren:e=>{const[...r]=e.children,t=1===r?.length?r[0]:r;return{...e,value:t}}};var Dr=Object.freeze({__proto__:null,AND:V,BUILD_OBJECT:Sr,CONDITIONAL:Le,COUNT:Ke,CUSTOM_FUNCTIONS:jr,DIVIDE:Ae,EQUAL:ae,GET:vr,GRAPHQL:dr,GREATER_THAN:Oe,LESS_THAN:Ue,MATCH:Nr,MULTIPLY:be,NOT_EQUAL:oe,OBJECT_PROPERTIES:$e,OR:Z,PASSTHRU:kr,PG_SQL:ur,PLUS:ce,POST:wr,REGEX:Me,SPLIT:ar,STRING_SUBSTITUTION:ze,SUBTRACT:ye});class _r{store;queue;maxSize;maxTime;constructor(e){this.store={},this.queue=[],this.maxSize=e?.maxSize??50,this.maxTime=e?.maxTime??1800}useCache=async(e,r,...t)=>{if(!e)return await r(...t);const a=Mr(t),s=a in this.store,i=Date.now(),n=s&&i-this.store[a].timestamp>1e3*this.maxTime;if(s)return this.queue=this.queue.filter((e=>e!==a)),this.queue.unshift(a),this.store[a].timestamp=i,n&&(this.store[a].result=await r(...t)),this.store[a].result;const o=await r(...t);return this.store[a]={result:o,timestamp:i},this.queue.unshift(a),this.resizeCache(),o};getMax=()=>this.maxSize;setMax=e=>{this.maxSize=e,this.resizeCache()};getMaxTime=()=>this.maxTime;setMaxTime=e=>{this.maxTime=e};getCache=()=>this.store;setCache=e=>this.store=e;resizeCache=()=>{if(this.queue.length>this.maxSize){this.queue.slice(this.maxSize).forEach((e=>delete this.store[e])),this.queue=this.queue.slice(0,this.maxSize)}}}const Mr=e=>e.map((e=>"object"==typeof e?JSON.stringify(e):e)).join("_");class Hr{options;operators;operatorAliases;cache;constructor(e={}){this.options=Qr(e),this.operators=u(Dr,this.options?.excludeOperators??[],b),this.operatorAliases=b,this.cache=new _r({maxSize:e.maxCacheSize,maxTime:e.maxCacheTime})}typeChecker=(...e)=>{const r=1===e.length&&Array.isArray(e[0])?e[0]:e,t=N(...r);if(!0!==t)throw new Error(t)};async evaluate(e,r={}){const t=m(this.options,Qr(r));return t.maxCacheSize&&t.maxCacheSize!==this.cache.getMax()&&this.cache.setMax(t.maxCacheSize),t.maxCacheTime&&t.maxCacheTime!==this.cache.getMaxTime()&&this.cache.setMaxTime(t.maxCacheTime),await G(e,{options:t,operators:r.excludeOperators?u(Dr,r.excludeOperators,b):this.operators,operatorAliases:this.operatorAliases,typeChecker:t.skipRuntimeTypeCheck?()=>{}:this.typeChecker,resolvedAliasNodes:{},cache:this.cache})}getOptions(){return this.options}updateOptions(e){this.options=m(this.options,Qr(e)),this.options.excludeOperators&&(this.operators=u(Dr,this.options.excludeOperators,b))}getCache=()=>this.cache.getCache();setCache=e=>this.cache.setCache(e);getOperators(){const e=this.options.excludeOperators?u(Dr,this.options.excludeOperators,b):this.operators;return Object.entries(e).map((([e,r])=>({operator:e,...r.operatorData})))}getFragments(){return Object.entries(this.options.fragments??{}).map((([e,r])=>({name:e,...r?.metadata})))}getCustomFunctions(){return Object.entries(this.options.functions??{}).map((([e,r])=>({name:e,numRequiredArgs:r.length})))}getVersion=()=>"2.11.0"}const Gr=(e,r)=>new Hr(r).evaluate(e),Qr=e=>"objects"in e?{...e,data:e.objects}:e;export{Hr as FigTreeEvaluator,Gr as evaluateExpression};
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fig-tree-evaluator",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.11.0",
|
|
4
4
|
"description": "Module to evaluate JSON-structured expression trees",
|
|
5
|
-
"main": "build/index.js",
|
|
5
|
+
"main": "build/index.cjs.js",
|
|
6
|
+
"module": "build/index.esm.js",
|
|
6
7
|
"types": "build/index.d.ts",
|
|
7
8
|
"files": [
|
|
8
9
|
"build/**/*"
|
|
@@ -11,20 +12,27 @@
|
|
|
11
12
|
"author": "Carl Smith <5456533+CarlosNZ@users.noreply.github.com>",
|
|
12
13
|
"license": "GPL-3.0",
|
|
13
14
|
"devDependencies": {
|
|
15
|
+
"@rollup/plugin-typescript": "^11.1.1",
|
|
14
16
|
"@testing-library/jest-dom": "^5.14.1",
|
|
15
17
|
"@testing-library/react": "^13.0.0",
|
|
16
18
|
"@types/jest": "^27.5.1",
|
|
17
19
|
"@types/node": "^17.0.38",
|
|
18
20
|
"@types/pg": "^8.6.5",
|
|
21
|
+
"@types/prettier": "^3.0.0",
|
|
19
22
|
"@typescript-eslint/eslint-plugin": "^5.57.0",
|
|
20
23
|
"@typescript-eslint/parser": "^5.57.0",
|
|
21
24
|
"dotenv": "^16.0.1",
|
|
22
25
|
"eslint": "^8.37.0",
|
|
23
26
|
"jest": "^29.6.2",
|
|
24
27
|
"pg": "^8.7.3",
|
|
28
|
+
"prettier": "^3.0.0",
|
|
25
29
|
"rimraf": "^3.0.2",
|
|
30
|
+
"rollup-plugin-dts": "^5.3.0",
|
|
31
|
+
"rollup-plugin-sizes": "^1.0.5",
|
|
32
|
+
"rollup-plugin-terser": "^7.0.2",
|
|
26
33
|
"ts-jest": "^29.1.1",
|
|
27
34
|
"ts-node": "^10.8.0",
|
|
35
|
+
"tslib": "^2.5.0",
|
|
28
36
|
"typescript": "^4.7.2"
|
|
29
37
|
},
|
|
30
38
|
"scripts": {
|
|
@@ -34,7 +42,8 @@
|
|
|
34
42
|
"generateMassiveQuery": "ts-node ./codegen/generateMassiveQuery.ts",
|
|
35
43
|
"getVersion": "ts-node ./codegen/getVersion.ts",
|
|
36
44
|
"lint": "eslint . --ext .ts",
|
|
37
|
-
"build": "rimraf ./build &&
|
|
45
|
+
"build": "rimraf ./build && rollup -c && rimraf ./build/dts",
|
|
46
|
+
"compile": "rimraf ./build && tsc",
|
|
38
47
|
"prebuild": "yarn generate && yarn getVersion",
|
|
39
48
|
"dev": "cp -n src/dev/playground_example.ts src/dev/playground.ts || ts-node src/dev/playground.ts",
|
|
40
49
|
"demo": "yarn getVersion && cd demo && yarn start",
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { EvaluatorNode, FigTreeOptions, OperatorMetadata, FragmentMetadata } from './types';
|
|
2
|
-
import { Store } from './cache';
|
|
3
|
-
declare class FigTreeEvaluator {
|
|
4
|
-
private options;
|
|
5
|
-
private operators;
|
|
6
|
-
private operatorAliases;
|
|
7
|
-
private cache;
|
|
8
|
-
constructor(options?: FigTreeOptions);
|
|
9
|
-
private typeChecker;
|
|
10
|
-
evaluate(expression: EvaluatorNode, options?: FigTreeOptions): Promise<import("./types").EvaluatorOutput>;
|
|
11
|
-
getOptions(): FigTreeOptions;
|
|
12
|
-
updateOptions(options: FigTreeOptions): void;
|
|
13
|
-
getCache: () => Store;
|
|
14
|
-
setCache: (cache: Store) => Store;
|
|
15
|
-
getOperators(): readonly OperatorMetadata[];
|
|
16
|
-
getFragments(): readonly (FragmentMetadata & {
|
|
17
|
-
name: string;
|
|
18
|
-
})[];
|
|
19
|
-
getCustomFunctions(): readonly {
|
|
20
|
-
name: string;
|
|
21
|
-
numRequiredArgs: number;
|
|
22
|
-
}[];
|
|
23
|
-
getVersion: () => string;
|
|
24
|
-
}
|
|
25
|
-
export default FigTreeEvaluator;
|
|
26
|
-
export declare const evaluateExpression: (expression: EvaluatorNode, options?: FigTreeOptions) => Promise<import("./types").EvaluatorOutput>;
|