fig-tree-evaluator 2.22.1 → 2.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +23 -3
- package/build/index.cjs.js +1 -1
- package/build/index.d.ts +2 -1
- package/build/index.esm.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
The format below (from v2.21.4 onwards) is loosely based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## [2.23.1]
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- `stringSubstitution`: escaped substitution characters (`\%N` for positional, `\{{name}}` for named) are now un-escaped for every occurrence, not just the first. ([#142](https://github.com/CarlosNZ/fig-tree-evaluator/issues/142))
|
|
10
|
+
- `DIVIDE` operator: `output: 'decimal'` is now accepted (previously rejected by its own type-check, even though decimal division was the runtime fall-through behaviour). The `output` metadata `default` also now correctly reflects the actual runtime default (`'decimal'`). Minor typo fix in the `values` parameter description ("by the first" → "by the second"). ([#141](https://github.com/CarlosNZ/fig-tree-evaluator/issues/141))
|
|
11
|
+
- `inputDefault` in a custom `FunctionDefinition` now accepts primitive values (previously only object values were valid at the type level). Falsy primitives (`0`, `false`, `""`) are also preserved by `getCustomFunctions()` instead of being silently dropped from the exposed metadata.
|
|
12
|
+
- `notEqual` (`!=`, `ne`) with `nullEqualsUndefined: true` no longer always returns `false` when the first value is `null` or `undefined`. The check now correctly returns `true` when any value falls outside the null/undefined equivalence class ([#140](https://github.com/CarlosNZ/fig-tree-evaluator/issues/140)).
|
|
13
|
+
- `split` operator: the `delimiter` now interprets the whitespace escape sequences `\n`, `\t` and `\r` when written literally, so a delimiter typed as `\n` (backslash + `n`) splits on real line breaks. This is convenient when authoring the delimiter in an input field that can't hold a real control character. Genuine control characters and other delimiters (including a single backslash) are unaffected.
|
|
14
|
+
|
|
15
|
+
## [2.23.0] - 2026-06-30
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- New `FigTreeEvaluator` instance method `isFigTreeExpression(expression)` — a registry-aware check for whether an expression is something *this* instance would actually evaluate. Unlike the structural stand-alone `isFigTreeExpression` export, it validates `$`-prefixed shorthand and keys against the instance's registered operators, fragments and custom functions, and follows its `evaluateFullObject` and `noShorthand` settings. Useful for editor UIs deciding whether to treat a value as an evaluable expression rather than plain data.
|
|
20
|
+
|
|
5
21
|
## [2.22.1] - 2026-06-30
|
|
6
22
|
|
|
7
23
|
### Fixed
|
package/README.md
CHANGED
|
@@ -501,7 +501,7 @@ Aliases: `/`, `divide`, `÷`
|
|
|
501
501
|
- `values`: (array) -- exactly 2 numerical elements; the first will be divided by the second. (If non-numerical elements are provided, the operator will return `NaN`)
|
|
502
502
|
- `dividend` (or `divide`): (number) -- the number that will be divided
|
|
503
503
|
- `divisor` (or `by`): (number) -- the number to divide `dividend` by
|
|
504
|
-
- `output` (`'quotient' | 'remainder'`) -- by default, the operator returns a floating point value.
|
|
504
|
+
- `output` (`'quotient' | 'remainder' | 'decimal'`) -- by default (or if `decimal` is specified), the operator returns a floating point value. If `quotient` is specified, it will return the integer part of the result; if `remainder` is specified, it will return the remainder after division (i.e. `value1 % value2`)
|
|
505
505
|
|
|
506
506
|
Note that the input values can be provided as *either* a `values` array *or* `dividend`/`divisor` properties. If both are provided, `values` takes precedence.
|
|
507
507
|
|
|
@@ -988,7 +988,7 @@ Aliases: `split`, `arraySplit`
|
|
|
988
988
|
#### Properties
|
|
989
989
|
|
|
990
990
|
- `value` (or `string`)<sup>*</sup>: (string) -- string to be split
|
|
991
|
-
- `delimiter` (or `separator`): (string) -- substring to split `value` on (Default: `" "` (space))
|
|
991
|
+
- `delimiter` (or `separator`): (string) -- substring to split `value` on (Default: `" "` (space)). The whitespace escape sequences `\n`, `\t` and `\r` may be written literally (e.g. `"\n"` to split on line breaks), which is convenient when authoring the delimiter in an input field that can't hold a real control character.
|
|
992
992
|
- `trimWhiteSpace` (or `trimWhitespace`, `trim`): (boolean, default `true`) -- strips whitespace from the beginning or end of resulting substrings
|
|
993
993
|
- `excludeTrailing` (or `removeTrailing`, `excludeTrailingDelimiter`): (boolean, default `true`) -- if `false`, if the input string ends with the delimiter, the last member of the output array will be an empty string.
|
|
994
994
|
i.e. `this, that, another,` (delimiter `","`) => `["this", "that", "another", ""]`
|
|
@@ -1959,7 +1959,7 @@ If extending FigTree with additional [HTTP Client](#http-requests), [SQL Connect
|
|
|
1959
1959
|
|
|
1960
1960
|
Evaluator expressions can be configured by hand, with [aliases](#alias-nodes), [fragments](#fragments) and [shorthand](#shorthand-syntax) available to make the job easier.
|
|
1961
1961
|
|
|
1962
|
-
However, you may wish to use an external UI (such as [this one](https://carlosnz.github.io/fig-tree-evaluator/) for React) for building FigTree expression (or create your own). To this end, the FigTree instance provides
|
|
1962
|
+
However, you may wish to use an external UI (such as [this one](https://carlosnz.github.io/fig-tree-evaluator/) for React) for building FigTree expression (or create your own). To this end, the FigTree instance provides several methods that could be useful for populating the configuration UI:
|
|
1963
1963
|
|
|
1964
1964
|
#### A new FigTree instance:
|
|
1965
1965
|
|
|
@@ -2092,6 +2092,26 @@ Returns:
|
|
|
2092
2092
|
]
|
|
2093
2093
|
```
|
|
2094
2094
|
|
|
2095
|
+
#### Check if a value is a FigTree expression
|
|
2096
|
+
|
|
2097
|
+
```js
|
|
2098
|
+
fig.isFigTreeExpression(value)
|
|
2099
|
+
```
|
|
2100
|
+
|
|
2101
|
+
When building a UI, you often need to decide whether a given value should be treated as an evaluable FigTree expression or as plain data. This method returns `true` only for values that *this* instance would actually process as an expression. It is **registry-aware** — `$`-prefixed [shorthand](#shorthand-syntax) and keys are validated against the instance's registered operators, [fragments](#fragments) and [custom functions](#custom_functions) — and it follows the instance's [`evaluateFullObject`](#available-options) and `noShorthand` settings.
|
|
2102
|
+
|
|
2103
|
+
```js
|
|
2104
|
+
fig.isFigTreeExpression({ operator: '+', values: [1, 2] }) // true
|
|
2105
|
+
fig.isFigTreeExpression({ $getData: 'user.name' }) // true (registered shorthand)
|
|
2106
|
+
fig.isFigTreeExpression({ name: 'Steve', age: 30 }) // false (plain data)
|
|
2107
|
+
fig.isFigTreeExpression({ $somethingUnknown: 1 }) // false (not a registered operator/fragment/function)
|
|
2108
|
+
fig.isFigTreeExpression('$myAlias') // false (alias reference with no definition in scope)
|
|
2109
|
+
```
|
|
2110
|
+
|
|
2111
|
+
The last two cases are why this is preferable to a purely structural check: an object whose only `$`-prefixed key doesn't correspond to anything the evaluator recognises (e.g. `{ "$somethingUnknown": 1 }`) is plain data, not an expression, and won't be flagged here.
|
|
2112
|
+
|
|
2113
|
+
The check mirrors what the evaluator would actually do: operator/fragment nodes and arrays are always considered, but it only descends into plain (non-operator) objects when [`evaluateFullObject`](#available-options) is enabled on the instance. Alias references (`"$name"` strings) count only when a matching alias definition is in scope (on the same node or an ancestor).
|
|
2114
|
+
|
|
2095
2115
|
## More examples
|
|
2096
2116
|
|
|
2097
2117
|
More examples, included large, complex expressions can be found within the test suites in the [repository](https://github.com/CarlosNZ/fig-tree-evaluator).
|
package/build/index.cjs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("object-property-extractor"),r=require("dequal/lite");const t=e=>e instanceof Object&&"operator"in e,a=e=>e instanceof Object&&"fragment"in e,s=e=>{const r=m(e);return r||e},i=(e,r)=>r[s(e)],n=(e,r,t)=>{const a={...e};return r.forEach((e=>{t[s(e)]||console.warn(`Invalid operator exclusion: ${e}`),delete a[t[s(e)]]})),a},o=(e,r=200)=>e.length<r?e:`${e.slice(0,r-2).trim()}...`,l=(e,r)=>{const t=Object.entries(e).map((([e,t])=>[r(e),t]));return Object.fromEntries(t)},u=e=>/^\$.+/.test(e),p=(e,{resolvedAliasNodes:r})=>"string"==typeof e&&u(e)?r?.[e]??e:e,c=(e,r,t)=>{const a={...e,...r};return t?((e.data||r.data)&&(a.data={...e.data,...r.data}),(e.functions||r.functions)&&(a.functions={...e.functions,...r.functions}),(e.fragments||r.fragments)&&(a.fragments={...e.fragments,...r.fragments}),(e.headers||r.headers)&&(a.headers={...e.headers,...r.headers}),a):a},d={number:e=>h(e),string:e=>String(e),array:e=>Array.isArray(e)?e:[e],boolean:e=>Boolean(e),bool:e=>Boolean(e)},h=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},m=e=>e.replace(/[^A-Za-z\d _-]/g,"").split(/[-_ ]/).map((e=>e.match(/[a-z]+|[A-Z]+[a-z]*/g)??e)).flat().filter((e=>""!==e)).map(((e,r)=>0===r?e.toLowerCase():e.charAt(0).toUpperCase()+e.slice(1).toLowerCase())).join(""),f=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),y={and:"AND","&":"AND","&&":"AND",or:"OR","|":"OR","||":"OR","=":"EQUAL",eq:"EQUAL",equal:"EQUAL",equals:"EQUAL","!=":"NOT_EQUAL",notEqual:"NOT_EQUAL","!":"NOT_EQUAL",ne:"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",getData:"OBJECT_PROPERTIES",dataProperties:"OBJECT_PROPERTIES",data:"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",get:"GET",api:"GET",POST:"POST",post:"POST",sql:"SQL",pgSql:"SQL",postgres:"SQL",pg:"SQL",sqLite:"SQL",sqlite:"SQL",mySql:"SQL",graphQL:"GRAPHQL",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",pass:"PASSTHRU",_:"PASSTHRU",passThru:"PASSTHRU",passthru:"PASSTHRU",ignore:"PASSTHRU",coerce:"PASSTHRU",convert:"PASSTHRU"},g=y,v=(e,r={},t,a=!0)=>a&&f(e)?b(e,r,t):e,b=(e,r,s)=>{if(t(e)||a(e))return e;const i=Object.entries(e),n=i.filter((([e])=>u(e))),o=i.filter((([e])=>!u(e)));return{...n.reduce(((e,[t,a])=>e={...e,...T(t,a,r,s)}),{}),...Object.fromEntries(o)}},T=(e,r,t,a)=>{const s=e.slice(1),n=i(s,g);return n?Array.isArray(r)?{operator:n,children:r}:f(r)&&!Object.keys(r).some((e=>u(e)))?{operator:n,...r}:{operator:n,children:[r]}:s in t?{fragment:s,parameters:{...r}}:a.includes(s)?Array.isArray(r)?{operator:s,args:r}:f(r)?"input"in r||"args"in r?{operator:s,...r}:{operator:s,input:r}:{operator:s,args:[r]}:{[e]:r}};class w extends Error{constructor(e,r,t,a){super(e.message),Object.assign(this,e),this.operator=r,this.expression=a,this.errorData=e.errorData,t&&(this.name=t),"Error"===this.name&&(this.name="FigTreeError");const s=(r?"Operator: "+r:"")+("FigTreeError"===this.name?"":` - ${this.name}`),i=this.errorData?"\n"+JSON.stringify(this.errorData,null,2):"";this.prettyPrint=`${""!==s?s+"\n":""}${this.message}${"\n{}"===i?"":i}`}}const C=({fallback:e,operator:r,name:t,error:a,expression:s,returnErrorAsString:i=!1})=>{if(void 0!==e)return e;if(a instanceof w){if(!i)throw a;return a.prettyPrint}const n=new w("string"==typeof a?new Error(a):a,r,t,s);if(i)return n.prettyPrint;throw n},E=e=>f(e)&&"literal"in e,A=({value:e,name:r,expectedType:t})=>{if(E(t)){const{literal:a}=t;return!!a.includes(e)||O(r,e,`Literal(${a.map((e=>void 0===e?"undefined":`"${e}"`)).join(", ")})`)}if(Array.isArray(t))return!!t.some((t=>!0===A({value:e,name:r,expectedType:t})))||O(r,e,t.join("|"));return!!(0,q[t])(e)||O(r,e,t)},S=(...e)=>{const r=[];return e.forEach((e=>{const t=A(e);!0!==t&&r.push(t)})),!(r.length>0)||r.join("\n")},q={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=>f(e),undefined:e=>void 0===e},O=(e,r,t)=>void 0===r&&e?`- Missing required property "${e}" (type: ${t})`:void 0!==e?`- Property "${e}" (value: ${x(r)}) is not of type: ${t}`:`- ${x(r)} is not of type: ${t}`,x=e=>{const r=void 0===e||Number.isNaN(e)?String(e):JSON.stringify(e);return o(r,50)},N=e=>{const r={};return e.forEach((e=>{e.aliases.forEach((t=>r[t]=e.name))})),r},P=(e,r)=>e.map((({name:e,required:t,type:a})=>{if(E(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}})),j=(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=S(...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=>f(e)&&1===Object.keys(e).length?Object.values(e)[0]:e,I=(r,t,a=void 0)=>{const s=t?e(r,t,a):r;return Array.isArray(s)?s.map((e=>k(e))):t?null===s?null:k(s):s},U=e=>/^https?:\/\/.+/.test(e),R=(...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}),""),D=async(e,r)=>{const{url:t,params:a={},data:s={},headers:i={},method:n="get"}=r;if(!t||""===t)throw new Error("Invalid url");try{return await e[n]({url:t,headers:{"Content-Type":"application/json",Accept:"application/json",...i},params:a,data:s})}catch(r){e.throwError(r)}},Q=async(e,r)=>{const{options:s,operators:n,operatorAliases:o}=r;let u=s?.allowJSONStringInput?(e=>{if("string"!=typeof e)return e;try{const r=JSON.parse(e);return t(r)?r:e}catch(r){return e}})(e):e;const c=Object.keys(r.options?.functions??{});u=v(u,r.options?.fragments,c,!s.noShorthand),Array.isArray(u)&&(u=await _(u,r));const h=t(u),m=a(u);if(h&&(u=await(async(e,r)=>{if(!(e.operator in(r.options?.functions??{})))return e;const{operator:t,fallback:a,outputType:s,type:i,useCache:n,input:o,args:l,...u}=e,p={operator:"CUSTOM_FUNCTIONS",function:t};return void 0!==a&&(p.fallback=a),void 0!==s&&(p.outputType=s),void 0!==i&&(p.type=i),void 0!==n&&(p.useCache=n),void 0!==l&&(p.args=l),void 0!==o?p.input=o:Object.keys(u).length>0&&(p.input=u),p})(u,r)),s.evaluateFullObject&&!h&&!m)return p(await $(u,r),r);if(!h&&!m)return s.supportDeprecatedValueNodes&&f(u)&&"value"in u?u.value:p(u,r);const{fallback:y}=u,g=s?.returnErrorAsString??!1;if(m){const e={...u},a=s?.fragments?.[e.fragment]?.metadata?.parameters?.filter((e=>void 0!==e.default));void 0===e.parameters&&(e.parameters={}),a?.forEach((r=>{void 0===e.parameters?.[r.name]&&void 0===e?.[r.name]&&(e.parameters[r.name]=r.default)}));const[i,n]=await _([e.fragment,e.parameters],r),o=v(s?.fragments?.[i],s.fragments,c,!s.noShorthand);if(void 0===o)return C({fallback:await Q(y,r),error:`Fragment not defined: ${i}`,expression:u,returnErrorAsString:g});if(!t(o))return p(o,r);u={...e,...o,...n},delete u.fragment}const b=u,T=i(b.operator,o);if(!T)return C({fallback:await Q(y,r),error:`Invalid operator: ${b.operator}`,expression:u,returnErrorAsString:g});if(!r.operators[T])return C({fallback:await Q(y,r),error:`Excluded operator: ${b.operator}`,expression:u,returnErrorAsString:g});const{propertyAliases:w,evaluate:E,parseChildren:A}=n[T];let S=((e,r)=>l(r,(r=>r in e?e[r]:r)))(w,b);const q=await F(S,r);m||Object.entries(q).forEach((([e,t])=>r.resolvedAliasNodes[e]=t));const O=m?{...r,resolvedAliasNodes:{...r.resolvedAliasNodes,...q}}:r;if("children"in S){if(Array.isArray(S.children)||(S.children=await Q(S.children,O)),!Array.isArray(S.children))return C({fallback:await Q(y,r),operator:T,name:"Type Error",error:'- Property "children" is not of type: array',expression:u,returnErrorAsString:g});try{S=A(S,O),delete S.children}catch(e){return C({fallback:await Q(S.fallback,r),operator:T,error:e,expression:S,returnErrorAsString:g})}}let x;try{x=await E(S,O)}catch(e){return C({fallback:await Q(S.fallback,r),operator:T,error:e,expression:S,returnErrorAsString:g})}const N=S?.outputType??S?.type;if(!N)return x;const P=await Q(N,r);return P in d?d[P](x):C({fallback:await Q(y,r),operator:T,error:`- Invalid output type: ${P}`,expression:S,returnErrorAsString:g})},_=async(e,r)=>Array.isArray(e)?await Promise.all(e.map((e=>Q(e,r)))):await Q(e,r),F=async(e,r)=>{const t=Object.keys(e).filter(u);if(0===t.length)return{};const a=[];t.forEach((t=>a.push(Q(e[t],r))));const s=await Promise.all(a),i=j(t,await Promise.all(a));for(const[e,r]of s.entries())"string"==typeof r&&u(r)&&(i[t[e]]=i?.[r]??r);return i},$=async(e,r)=>{const t=Object.keys(r.options?.functions??{}),a=v(e,r.options?.fragments,t);if(!f(a))return e;const s=[],i=[];Object.entries(a).forEach((([e,t])=>{u(e)&&(i.push(e,Q(t,r)),delete a[e])}));const n=await Promise.all(i);r.resolvedAliasNodes={...r.resolvedAliasNodes,...L(n)},Object.entries(a).forEach((([e,t])=>{s.push(e,Q(t,r))}));const o=await Promise.all(s);return p(L(o),r)},H=[{name:"values",description:"Returns true if all values are true",aliases:[],required:!0,type:"array",default:[!0,!0]}],M=N(H),G={description:"Logical AND",aliases:["and","&","&&"],parameters:H},B=e=>{const r=e.children;return{...e,values:r}},z={propertyAliases:M,operatorData:G,evaluate:async(e,r)=>{const t=await _(e.values,r);return r.typeChecker(P(G.parameters,{values:t})),t.reduce(((e,r)=>e&&!!r),!0)},parseChildren:B},W=[{name:"values",description:"Returns true if any values are true",aliases:[],required:!0,type:"array",default:[!0,!1]}],J=N(W),V={description:"Logical OR",aliases:["or","|","||"],parameters:W},Y={propertyAliases:J,operatorData:V,evaluate:async(e,r)=>{const t=await _(e.values,r);return r.typeChecker(P(V.parameters,{values:t})),t.reduce(((e,r)=>e||!!r),!1)},parseChildren:B},X=[{name:"values",description:"Array of values to check for equality",aliases:[],required:!0,type:"array",default:["These are equal","These are equal"]},{name:"caseInsensitive",description:"If the values are strings, ignore the case (default: false)",aliases:[],required:!1,type:"boolean",default:!1},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],Z=N(X),K={description:"Test multiple values are equal",aliases:["=","eq","equal","equals"],parameters:X},ee={propertyAliases:Z,operatorData:K,evaluate:async(e,t)=>{const[a,s,i]=await _([e.values,e.caseInsensitive,e.nullEqualsUndefined],t);t.typeChecker(P(K.parameters,{values:a,caseInsensitive:s,nullEqualsUndefined:i}));const n=(void 0!==s?s:t.options?.caseInsensitive??!1)&&a.every((e=>"string"==typeof e))?a.map((e=>e.toLowerCase())):a;return!(void 0!==i?i:void 0!==t.options?.nullEqualsUndefined&&t.options.nullEqualsUndefined)||null!==n[0]&&void 0!==n[0]?n.every((e=>r.dequal(e,n[0]))):n.every((e=>null==e))},parseChildren:B},re=[{name:"values",description:"Array of values to check for inequality",aliases:[],required:!0,type:"array",default:["These items","don't match"]},{name:"caseInsensitive",description:"If the values are strings, ignore the case (default: false)",aliases:[],required:!1,type:"boolean",default:!1},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],te=N(re),ae={description:"Test if any values are different",aliases:["!=","notEqual","!","ne"],parameters:re},se={propertyAliases:te,operatorData:ae,evaluate:async(e,t)=>{const[a,s,i]=await _([e.values,e.caseInsensitive,e.nullEqualsUndefined],t);t.typeChecker(P(ae.parameters,{values:a,caseInsensitive:s,nullEqualsUndefined:i}));const n=(void 0!==s?s:t.options?.caseInsensitive??!1)&&a.every((e=>"string"==typeof e))?a.map((e=>e.toLowerCase())):a;return!(void 0!==i?i:void 0!==t.options?.nullEqualsUndefined&&t.options.nullEqualsUndefined)||null!==n[0]&&void 0!==n[0]?n.some((e=>!r.dequal(e,n[0]))):n.some((e=>null===e&&void 0===e))},parseChildren:B},ie=[{name:"values",description:"Array of values to check to add together",aliases:[],required:!0,type:"array",default:[1,2,3]},{name:"type",description:"Data type to coerce input values to before addition",aliases:[],required:!1,type:{literal:["string","array","number","boolean","bool"]},default:"string"}],ne=N(ie),oe={description:"Add, concatenate or merge multiple values",aliases:["+","plus","add","concat","join","merge"],parameters:ie},le={propertyAliases:ne,operatorData:oe,evaluate:async(e,r)=>{const t=await _(e.values,r);return r.typeChecker(P(oe.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=>f(e)))?t.reduce(((e,r)=>({...e,...r})),{}):t.reduce(((e,r)=>e+r))},parseChildren:B},ue=[{name:"values",description:"Array of values - 2nd element will be subtracted from the first",aliases:[],required:!1,type:"array",default:[10,5]},{name:"from",description:"Numerical value that will be subtracted from",aliases:["subtractFrom"],required:!1,type:"number",default:100},{name:"subtract",description:"Numerical value to subtract",aliases:[],required:!1,type:"number",default:50}],pe=N(ue),ce={description:"Subtract one numerical value from another",aliases:["-","subtract","minus","takeaway"],parameters:ue},de={propertyAliases:pe,operatorData:ce,evaluate:async(e,r)=>{const[t,a,s]=await _([e.values,e.from,e.subtract],r);r.typeChecker(P(ce.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:B},he=[{name:"values",description:"Array of values whose product will be calculated",aliases:[],required:!0,type:"array",default:[5,5]}],me=N(he),fe={description:"Multiply several numerical values together",aliases:["*","x","multiply","times"],parameters:he},ye={propertyAliases:me,operatorData:fe,evaluate:async(e,r)=>{const t=await _(e.values,r);if(r.typeChecker(P(fe.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:B},ge=[{name:"values",description:"Array of values - 1st element will be divided by the first",aliases:[],required:!1,type:"array",default:[100,10]},{name:"dividend",description:"The number that will be divided",aliases:["divide"],required:!1,type:"number",default:99},{name:"divisor",description:"The number that dividend will be divided by",aliases:["by","divideBy"],required:!1,type:"number",default:3},{name:"output",description:"Whether to output a quotient, remainder or decimal",aliases:[],required:!1,type:{literal:["quotient","remainder"]},default:"quotient"}],ve=N(ge),be={description:"Divide one numerical value by another",aliases:["/","divide","÷"],parameters:ge},Te={propertyAliases:ve,operatorData:be,evaluate:async(e,r)=>{const[t,a,s,i]=await _([e.values,e.dividend,e.divisor,e.output],r);r.typeChecker(P(be.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:B},we=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array",default:[10,9]},{name:"strict",description:"Whether value must be strictly greater than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],Ce=N(we),Ee={description:"Test if a value is greater than (or equal to) another value",aliases:[">","greaterThan","higher","larger"],parameters:we},Ae={propertyAliases:Ce,operatorData:Ee,evaluate:async(e,r)=>{const[t,a=!0]=await _([e.values,e.strict],r);if(r.typeChecker(P(Ee.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:B},Se=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array",default:[9,10]},{name:"strict",description:"Whether value must be strictly smaller than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],qe=N(Se),Oe={description:"Test if a value is smaller than (or equal to) another value",aliases:["<","lessThan","lower","smaller"],parameters:Se},xe={propertyAliases:qe,operatorData:Oe,evaluate:async(e,r)=>{const[t,a=!0]=await _([e.values,e.strict],r);if(r.typeChecker(P(Oe.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:B},Ne=[{name:"condition",description:"The expression to check for truthiness",aliases:[],required:!0,type:"any",default:!0},{name:"valueIfTrue",description:"Value to return if condition is true",aliases:["ifTrue"],required:!0,type:"any",default:"The condition is true"},{name:"valueIfFalse",description:"Value to return if condition is false",aliases:["ifFalse","ifNot"],required:!0,type:"any",default:"The condition is false"}],Pe=N(Ne),je={description:"Return a value based on a condition",aliases:["?","conditional","ifThen"],parameters:Ne},Le={propertyAliases:Pe,operatorData:je,evaluate:async(e,r)=>{r.typeChecker(P(je.parameters,{condition:e.condition,valueIfTrue:e.valueIfTrue,valueIfFalse:e.valueIfFalse}));return await Q(e.condition,r)?await Q(e.valueIfTrue,r):await Q(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",default:"test-this"},{name:"pattern",description:"The regular expression pattern",aliases:["regex","regexp","regExp","re"],required:!0,type:"string",default:"^[a-z]{4}-[a-z]{4}$"}],Ie=N(ke),Ue={description:"Compare a string against a regex pattern",aliases:["regex","patternMatch","regexp","matchPattern"],parameters:ke},Re={propertyAliases:Ie,operatorData:Ue,evaluate:async(e,r)=>{const[t,a]=await _([e.testString,e.pattern],r);r.typeChecker(P(Ue.parameters,{testString:t,pattern:a}));return new RegExp(a).test(t)},parseChildren:e=>{const[r,t]=e.children;return{...e,testString:r,pattern:t}}},De=[{name:"property",description:'The path to the required property (e.g. "user.firstName")',aliases:["path","propertyName"],required:!0,type:"string",default:"path.to[0].my.data"},{name:"additionalData",description:"Additional data objects to be considered",aliases:["additional","objects","data","additionalObjects"],required:!1,type:["object","array"],default:{}}],Qe=N(De),_e={description:"Extract values from data objects",aliases:["getData","dataProperties","data","objectProperties","objProps","getProperty","getObjProp"],parameters:De},Fe={propertyAliases:Qe,operatorData:_e,evaluate:async(r,t)=>{const[a,s={}]=await _([r.property,r.additionalData],t);t.typeChecker(P(_e.parameters,{property:a,additionalData:s}));const i={...t.options?.data??{},...s};return e(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",default:"Hello, %1"},{name:"substitutions",description:"An array of substitution values for the parameterised string",aliases:["replacements","values"],required:!1,type:["array","object"],default:{}},{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",default:!0},{name:"substitutionCharacter",description:'Which character to search for in original string for replacement -- can be "%" or "$" (default: "%")',aliases:["subCharacter","subChar"],required:!1,type:"string",default:"$"},{name:"numberMapping",description:"Rules for mapping number values to text strings, such as pluralisation.",aliases:["numMap","numberMap","pluralisation","pluralization","plurals"],required:!1,type:"object",default:{}}],He=N($e),Me={description:"Replace values in a string using simple parameter substitution",aliases:["stringSubstitution","substitute","stringSub","replace"],parameters:$e},Ge={propertyAliases:He,operatorData:Me,evaluate:async(e,r)=>{const[t,a={},s=!0,i="%",n={}]=await _([e.string,e.substitutions,e.trimWhiteSpace,e.substitutionCharacter,e.numberMapping],r);if(r.typeChecker(P(Me.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),l=j(Array.from(o),a.map((e=>s?String(e).trim():e)));return t.split(r).map((e=>e in l?l[e]:e)).join("").replace(`\\${e}`,e)}const o=/(?<!\\)({{(?:[A-Za-z0-9_.]|\[[0-9]+\])+}})/g,l=[];for(const e of t.split(o)){if(!/(?<!\\){{(.+)}}/.exec(e)){l.push(e.replace("\\{{","{{"));continue}const t=await Be(e,a,n,r);l.push(s?String(t).trim():t)}return l.join("")},parseChildren:e=>{const[r,...t]=e.children;return{...e,string:r,substitutions:t}}},Be=async(r,t,a,s)=>{const i=s.options?.data??{},n=r.replace(/{{(.+)}}/,"$1"),o=await Q(e(t,n,e(i,n,"")),s);if("number"!=typeof o)return o;if(!(n in a))return o;const l=a[n];if(o in l)return l[o].replace("{}",String(o));const u=Object.keys(a[n]),p=u.find((e=>e.startsWith(">")));if(p){if(o>Number(p.slice(1)))return l?.[p]}const c=u.find((e=>e.startsWith("<")));if(c){if(o<Number(c.slice(1)))return l?.[c]}return l.other?l.other.replace("{}",String(o)):o},ze=[{name:"values",description:"An array to count",aliases:[],required:!0,type:"array",default:[1,2,3,4,5]}],We=N(ze),Je={description:"Count elements in an array",aliases:["count","length"],parameters:ze},Ve={propertyAliases:We,operatorData:Je,evaluate:async(e,r)=>{const t=await _(e.values,r);return r.typeChecker(P(Je.parameters,{values:t})),t.length},parseChildren:B},Ye=[{name:"value",description:"The string to be split",aliases:["string"],required:!0,type:"string",default:"Alpha, Bravo, Charlie"},{name:"delimiter",description:"The value to split the string on (default is white space)",aliases:["separator"],required:!1,type:"string",default:","},{name:"trimWhiteSpace",description:"Whether to trim white space from around the resulting elements (default: true)",aliases:["trim","trimWhitespace"],required:!1,type:"boolean",default:!0},{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",default:!0}],Xe=N(Ye),Ze={description:"Split a string into an array",aliases:["split","arraySplit"],parameters:Ye},Ke=" ",er={propertyAliases:Xe,operatorData:Ze,evaluate:async(e,r)=>{const[t,a,s,i]=await _([e.value,e.delimiter??Ke,e.trimWhiteSpace??!0,e.excludeTrailing??!0],r);r.typeChecker(P(Ze.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=Ke]=e.children;return{...e,value:r,delimiter:t}}},rr=[{name:"query",description:"SQL query string, with parameterised replacements (e.g. $1, $2, etc)",aliases:["text"],required:!0,type:"string"},{name:"values",description:"An array/object of values to replace the SQL string parameters, as per SQL connection specifications ",aliases:["replacements"],required:!1,type:["array","object"]},{name:"single",description:"Specify if returning a single record",aliases:["singleRecord"],required:!1,type:"boolean"},{name:"flatten",description:"Specify whether to flatten resulting record objects to arrays of values",aliases:["flat","array"],required:!1,type:"boolean"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],tr=N(rr),ar={description:"Query an SQL database",aliases:["sql","pgSql","postgres","pg","sqLite","sqlite","mySql"],parameters:rr},sr={propertyAliases:tr,operatorData:ar,evaluate:async(e,r)=>{const t=r.options?.sqlConnection;if(!t)throw new Error("No SQL database connection provided");const[a,s,i,n,o,l]=await _([e.query,e.values||[],e.single,e.flatten,e.useCache,e.type],r);r.typeChecker(P(ar.parameters,{query:a,single:i,flatten:n,values:s,useCache:o}));const u=e.useCache??r.options.useCache??!0;{const e=r.cache.useCache(u,(async(e,r,a,s,i)=>{const n=await t.query({query:e,values:r})||[];["array","string","number"].includes(i??"")&&(s=!0);const o=s?n.map((e=>{const r=Object.values(e);return r.length<=1?r[0]:r})):n;return a?o[0]:o}),a,s,i,n,l);return e}},parseChildren:e=>{const[r,...t]=e.children;return{...e,query:r,values:t}}},ir=[{name:"query",description:"GraphQL query string",aliases:[],required:!0,type:"string",default:'query getCountries {\n countries(filter: {continent: {eq: "OC"}}) {\n name\n }\n }'},{name:"url",description:"Endpoint for the GraphQL request (if not already provided in options)",aliases:["endpoint"],required:!1,type:["string","null"],default:"https://countries.trevorblades.com/"},{name:"headers",description:"HTTP Headers (if not already provided in options)",aliases:[],required:!1,type:"object",default:{}},{name:"variables",description:"Values for the variables used in query (key-value pairs)",aliases:[],required:!1,type:"object",default:{}},{name:"returnNode",description:"Property path to extract from the query response",aliases:["outputNode","returnProperty"],required:!1,type:"string",default:"data.countries[1].name"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],nr=N(ir),or={description:"GraphQL request",aliases:["graphQL","graphQl","graphql","gql"],parameters:ir},lr={propertyAliases:nr,operatorData:or,evaluate:async(e,r)=>{const t=r.graphQLClient??r.httpClient;if(!t)throw new Error("No HTTP client provided for GraphQL connection");const[a,s,i,n,o,l]=await _([e.query,e.url,await $(e.variables,r),e.returnNode,e.headers,e.useCache],r),{url:u,headers:p}=s instanceof Object?s:{url:s,headers:null};r.typeChecker([...P(or.parameters,{url:u,query:a,variables:i,returnNode:n,headers:o,useCache:l}),{name:"headers",value:p,expectedType:["object","null"]}]);const c=u&&"graphqlendpoint"!==u.toLowerCase()?u:"",d=r.options.graphQLConnection?.endpoint??r.options.baseEndpoint??"",h=U(c)?c:R(d,c),m={query:a,variables:i},f=l??r.options.useCache??!0,y=await r.cache.useCache(f,(async(e,r,a,s)=>{const i=await D(t,{url:e,method:"post",data:r,headers:a});return I(i?.data,s)}),h,m,{...r.options.graphQLConnection?.headers,...r.options?.headers,...p,...o},n);return y},parseChildren:e=>{const[r,t="",a,...s]=e.children,i=Array.isArray(a)?a:[a],n=s.slice(0,i.length),o=j(i,n),l={...e,query:r,url:t,variables:o};return s.length>i.length&&(l.returnNode=s.pop()),l}},ur=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string",default:"https://restcountries.com/v3.1/name/zealand"},{name:"returnProperty",description:"Property from request result",aliases:["outputProperty"],required:!1,type:"string",default:"result.path"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object",default:{}},{name:"parameters",description:"Query parameters (key-value)",aliases:["queryParams","queryParameters","urlQueries"],required:!1,type:"object",default:{}},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],pr=N(ur),cr={description:"HTTP GET Request",aliases:["GET","get","api"],parameters:ur},dr=e=>{const[r="",t,...a]=e.children,s=Array.isArray(t)?t:[t],i=a.slice(0,s.length),n=j(s,i),o={...e,url:r,parameters:n};return a.length>s.length&&(o.returnProperty=a.pop()),o},hr=dr,mr={propertyAliases:pr,operatorData:cr,evaluate:async(e,r)=>{const t=r.httpClient;if(!t)throw new Error("No HTTP client provided");const[a,s,i,n,o]=await _([e.url,await $(e.parameters,r),e.returnProperty,await $(e.headers,r),e.useCache],r),{url:l,headers:u}=a instanceof Object?a:{url:a,headers:null};r.typeChecker([...P(cr.parameters,{url:l,returnProperty:i,headers:n,parameters:s,useCache:o}),{name:"headers",value:u,expectedType:["object","null"]}]);const p=r.options.baseEndpoint??"",c={...r.options?.headers,...u,...n},d=o??r.options.useCache??!0,h=await r.cache.useCache(d,(async(e,r,a,s)=>{const i=await D(t,{url:e,params:r,headers:a});return I(i,s)}),U(l)?l:R(p,l),s,c,i);return h},parseChildren:dr},fr=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string",default:"https://jsonplaceholder.typicode.com/posts"},{name:"returnProperty",description:"Property path from request result",aliases:["outputProperty"],required:!1,type:"string",default:"result.path"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object",default:{}},{name:"parameters",description:"JSON Body parameters (key-value)",aliases:["bodyJson","data"],required:!1,type:"object",default:{}},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],yr=N(fr),gr={description:"HTTP POST Request",aliases:["POST","post"],parameters:fr},vr={propertyAliases:yr,operatorData:gr,evaluate:async(e,r)=>{const t=r.httpClient;if(!t)throw new Error("No HTTP client provided");const[a,s,i,n,o]=await _([e.url,await $(e.parameters,r),e.returnProperty,await $(e.headers,r),e.useCache],r),{url:l,headers:u}=a instanceof Object?a:{url:a,headers:null};r.typeChecker([...P(gr.parameters,{url:l,headers:n,data:s,returnProperty:i,useCache:o}),{name:"headers",value:u,expectedType:["object","null"]}]);const p=r.options.baseEndpoint??"",c={...r.options?.headers,...u,...n},d=o??r.options.useCache??!1,h=await r.cache.useCache(d,(async(e,r,a,s)=>{const i=await D(t,{url:e,data:r,headers:a,method:"post"});return I(i,s)}),U(l)?l:R(p,l),s,c,i);return h},parseChildren:hr},br=[{name:"properties",description:'An array of objects, each with a "key" property and a "value" property',aliases:["values","keyValPairs","keyValuePairs"],required:!0,type:"array",default:["firstKey","firstValue","secondKey","secondValue"]}],Tr=N(br),wr={description:"Construct an object using objects defining keys and values",aliases:["buildObject","build","object"],parameters:br},Cr=e=>{const r=e.children;if(r.every((e=>f(e))))return{...e,properties:r};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}},Er={propertyAliases:Tr,operatorData:wr,evaluate:async(e,r)=>{const t=await _(e.properties,r);r.typeChecker(P(wr.parameters,{properties:t}));const{properties:a}=t.some((e=>!f(e)))?Cr({...e,children:t}):{properties:t},s=a.filter((e=>e instanceof Object&&"key"in e&&"value"in e)).map((({key:e,value:t})=>(async e=>{const[t,a]=await _(e,r);return r.typeChecker({name:"key",value:t,expectedType:["string","number","boolean"]}),[t,a]})([e,t])));return Object.fromEntries(await Promise.all(s))},parseChildren:Cr},Ar=[{name:"matchExpression",description:"Expression to match against",aliases:["matchValue"],required:!0,type:["string","number","boolean"],default:"matchMe"},{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"],default:{matchMe:"YES",nonMatch:"NO"}},{name:"[...branches]",description:"Branch properties can optionally be placed at the operator root",aliases:[],required:!1,type:["object","array"]}],Sr={propertyAliases:N(Ar),operatorData:{description:"Return different values depending on a matching expression",aliases:["match","switch"],parameters:Ar},evaluate:async(e,r)=>{const a=await Q(e.matchExpression,r);r.typeChecker({name:"matchExpression",value:a,expectedType:["string","number","boolean"]});const s=Array.isArray(e.branches)?L(e.branches):e.branches??{},i=t(s)?await Q(s,r):s;if(!f(i))throw new Error("Branches don't evaluate to an object");if(a in i)return await Q(i[a],r);if("fallback"in i)return await Q(i.fallback,r);if(a in e)return await Q(e[a],r);throw new Error(`No match found for ${a}`)},parseChildren:e=>{const[r,...t]=e.children,a=L(t);return{...e,matchExpression:r,branches:a}}},qr=[{name:"functionName",description:"Path (in options.functions) to the required function",aliases:["functionPath","funcName","function","path","name"],required:!0,type:"string",default:null},{name:"args",description:"Arguments for the function",aliases:["arguments","variables"],required:!1,type:["array","any"],default:[]},{name:"input",description:"Argument for the function if a single input parameter",aliases:["arg"],required:!1,type:"any",default:"input"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!1}],Or=N(qr),xr={description:"Call a custom function (defined in options)",aliases:["customFunctions","customFunction","objectFunctions","function","functions","runFunction"],parameters:qr},Nr={propertyAliases:Or,operatorData:xr,evaluate:async(r,t)=>{const[a,s=[],i,n]=await _([r.functionName,r.args,r.input,r.useCache],t);t.typeChecker(P(xr.parameters,{functionName:a,args:s}));const{data:o,functions:l}=t.options;if(!l)throw new Error("- No functions defined");const u=e(l,`${a}.function`,null)??e(l,a,null)??e(t.options,`${a}.function`,null)??e(t.options,a,null)??e(o,a,null);if(!u||"function"!=typeof u)throw new Error(`- No function found: "${a}"`);const p=n??t.options.useCache??!1,c=[...void 0===i?[]:[await $(i,t)],...Array.isArray(s)?s:[s]];return await t.cache.useCache(p,(async(e,...r)=>await u(...r)),a,...c)},parseChildren:e=>{const[r,...t]=e.children;return{...e,functionName:r,args:t}}},Pr=[{name:"value",description:"Value to pass through",aliases:["_","data"],required:!0,type:"any",default:null}],jr=N(Pr),Lr={description:"Pass through a value unchanged (or change its type)",aliases:["pass","_","passThru","passthru","ignore","coerce","convert"],parameters:Pr},kr={propertyAliases:jr,operatorData:Lr,evaluate:async(e,r)=>(r.typeChecker(P(Lr.parameters,{value:e.value})),await Q(e.value,r)),parseChildren:e=>{const[...r]=e.children,t=1===r?.length?r[0]:r;return{...e,value:t}}};var Ir=Object.freeze({__proto__:null,AND:z,BUILD_OBJECT:Er,CONDITIONAL:Le,COUNT:Ve,CUSTOM_FUNCTIONS:Nr,DIVIDE:Te,EQUAL:ee,GET:mr,GRAPHQL:lr,GREATER_THAN:Ae,LESS_THAN:xe,MATCH:Sr,MULTIPLY:ye,NOT_EQUAL:se,OBJECT_PROPERTIES:Fe,OR:Y,PASSTHRU:kr,PLUS:le,POST:vr,REGEX:Re,SPLIT:er,SQL:sr,STRING_SUBSTITUTION:Ge,SUBTRACT:de});class Ur{constructor(e){this.useCache=async(e,r,...t)=>{if(!e)return await r(...t);const a=Rr(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},this.getMax=()=>this.maxSize,this.setMax=e=>{this.maxSize=e,this.resizeCache()},this.getMaxTime=()=>this.maxTime,this.setMaxTime=e=>{this.maxTime=e},this.getCache=()=>this.store,this.setCache=e=>this.store=e,this.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)}},this.store={},this.queue=[],this.maxSize=e?.maxSize??50,this.maxTime=e?.maxTime??1800}}const Rr=e=>e.map((e=>"object"==typeof e?JSON.stringify(e):e)).join("_"),Dr=e=>e||("undefined"!=typeof window&&"document"in window&&"fetch"in window?Qr(window.fetch):void 0),Qr=e=>({get:async r=>{const{url:t,headers:a,params:s={}}=r,i=Object.keys(s).length>0?`?${new URLSearchParams(s).toString()}`:"",n=await e(t+i,{headers:a,method:"GET"}),o=await n.json();if(!n.ok){const e=new Error("Problem with GET request");throw e.name="FetchError",e.errorData={status:n.status,error:n.statusText,url:n.url,response:o},console.log(e.errorData),e}return o},post:async r=>{const{url:t,headers:a,params:s,data:i}=r,n=new URLSearchParams(s),o=n.size>0?`?${n.toString()}`:"",l=await e(t+o,{headers:a,body:JSON.stringify(i),method:"POST"}),u=await l.json();if(!l.ok){const e=new Error("Problem with POST request");throw e.name="FetchError",e.errorData={status:l.status,error:l.statusText,url:l.url,response:u},console.log(e.errorData),e}return u},throwError:e=>{throw e}});class _r{constructor(e={}){this.typeChecker=(...e)=>{const r=1===e.length&&Array.isArray(e[0])?e[0]:e,t=S(...r);if(!0===t)return;const a=new Error(t);throw a.name="Type Error",a},this.getCache=()=>this.cache.getCache(),this.setCache=e=>this.cache.setCache(e),this.getVersion=()=>"2.22.1",this.options=Fr(e),this.operators=n(Ir,this.options?.excludeOperators??[],y),this.operatorAliases=y,this.cache=new Ur({maxSize:e.maxCacheSize,maxTime:e.maxCacheTime}),this.graphQLClient=Dr(e.graphQLConnection?.httpClient),this.httpClient=Dr(e.httpClient)}async evaluate(e,r={}){const t=c(this.options,Fr(r),!0);return r.httpClient&&(this.httpClient=Dr(r.httpClient)),r.graphQLConnection?.httpClient&&(this.graphQLClient=Dr(r.graphQLConnection.httpClient)),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 Q(e,{options:t,operators:r.excludeOperators?n(Ir,r.excludeOperators,y):this.operators,operatorAliases:this.operatorAliases,typeChecker:t.skipRuntimeTypeCheck?()=>{}:this.typeChecker,resolvedAliasNodes:{},cache:this.cache,graphQLClient:this.graphQLClient,httpClient:this.httpClient})}getOptions(){return this.options}updateOptions(e){this.options=c(this.options,Fr(e),!1),this.options.excludeOperators&&(this.operators=n(Ir,this.options.excludeOperators,y))}getOperators(){const e=this.options.excludeOperators?n(Ir,this.options.excludeOperators,y):this.operators,r=Object.entries(e).map((([e,r])=>({name:e,...r.operatorData,parseChildren:r.parseChildren}))),t=[...new Set(Object.values(y))];return r.sort(((e,r)=>t.indexOf(e.name)-t.indexOf(r.name)))}getFragments(){return Object.entries(this.options.fragments??{}).map((([e,r])=>({name:e,...r?.metadata})))}getCustomFunctions(){return Object.entries(this.options.functions??{}).map((([e,r])=>{const t="function"==typeof r?r:r?.function,a={name:e,numRequiredArgs:t?.length};if("function"!=typeof r){const{description:e,argsDefault:t,inputDefault:s,textColor:i,backgroundColor:n}=r;return e&&(a.description=e),t&&(a.argsDefault=t),s&&(a.inputDefault=s),i&&(a.textColor=i),n&&(a.backgroundColor=n),a}return a}))}getConfig(){return{options:this.options,operators:this.options.excludeOperators?n(Ir,this.options.excludeOperators,y):this.operators,operatorAliases:this.operatorAliases,typeChecker:this.options.skipRuntimeTypeCheck?()=>{}:this.typeChecker,resolvedAliasNodes:{},cache:this.cache,graphQLClient:this.graphQLClient,httpClient:this.httpClient}}}const Fr=e=>"objects"in e?{...e,data:e.objects}:e,$r=e=>f(e)&&"operator"in e&&"children"in e&&Array.isArray(e.children),Hr=(e,r,t)=>{const a=t.find((r=>r.name===e||r.aliases.includes(e)));if(!a)throw new Error("Invalid operator: "+e);const s=[];switch(a.name){case"OBJECT_PROPERTIES":{if(Gr("additionalData",r,a.parameters))return Object.fromEntries(r);const e=Gr("property",r,a.parameters);if(!e)throw new Error("Missing required property for operator $getData: property");const t=r.find((([e])=>"fallback"===e));return t?[e[1],t[1]]:e[1]}case"GET":case"POST":case"GRAPHQL":return Object.fromEntries(r);default:{const t=new Set;for(const{name:i,aliases:n,required:o}of a.parameters){const a=[i,...n],l=r.find((([e])=>a.includes(e)));if(void 0===l&&o)throw new Error(`Missing required property for operator ${e}: ${i}`);if(void 0===l)break;s.push(l[1]),t.add(l[0])}if(r.some((([e])=>!t.has(e))))return Object.fromEntries(r)}}return s},Mr=(e,r,t)=>{if(!e)return!1;const a=s(e),i=t.find((e=>e.name===a||e.aliases.includes(a)))?.parameters[0];if(!i)return!1;return!!("array"===i.type||Array.isArray(i.type)&&i.type.includes("array"))&&[i.name,...i.aliases].some((e=>e in r))},Gr=(e,r,t)=>{const a=t.find((r=>r.name===e));if(!a)return;const s=[a.name,...a.aliases];return r.find((([e])=>s.includes(e)))},Br=(e,r)=>u(e)&&!r.has(e),zr=(e,r)=>{if(!e)return;const t=r.find((r=>e===r.name||r.aliases.includes(s(e))));return t?.aliases.find((e=>/^[A-Za-z_]{2,}$/.test(e)))},Wr=(e,r={})=>{const t=r[e];if(!t)throw new Error("Fragment referenced in expression that is not defined in FigTree: "+e);const a=JSON.stringify(t).match(/"(\$\w+)"/gm);if(!a)return[];const s=new Set;return a.forEach((e=>s.add(e.replace(/"/g,"")))),Array.from(s)},Jr=(e,r)=>{const t=r.parameters.map((e=>[e.name,...e.aliases])).flat();return Object.keys(e).some((e=>t.includes(e)))};Object.defineProperty(exports,"dequal",{enumerable:!0,get:function(){return r.dequal}}),exports.AxiosClient=e=>({get:async r=>(await e({...r,method:"get"})).data,post:async r=>(await e({...r,method:"post"})).data,throwError:r=>{if(e.isAxiosError(r)&&r.response)throw r.errorData={status:r.response?.status,error:r.response?.statusText,url:r.config?.url,response:r.response?.data},r;throw new Error("Network error: "+r?.message)}}),exports.FetchClient=Qr,exports.FigTreeError=w,exports.FigTreeEvaluator=_r,exports.SQLNodePostgres=e=>({query:async({query:r,values:t=[]})=>{const a={text:r,values:t??[]};try{const r=await e.query(a);if(r?.error)throw new Error(r.error);return r.rows}catch(e){throw e.name="Node-Postgres error",e}}}),exports.SQLite=e=>({query:async({query:r,values:t=[]})=>{try{return await e.all(r,t)}catch(e){throw e.name="SQLite error",e}}}),exports.convertFromShorthand=(e,r)=>{const i=r.getOperators(),n=r.getFragments(),o=r.getCustomFunctions(),l=n.map((e=>e.name)),u=o.map((e=>e.name)),p=e=>{if(Array.isArray(e))return e.map((e=>p(e)));if(!f(e))return e;const n=Object.entries(e);if(0===n.length)return e;const o=n[0][0].replace("$",""),d=s(o),h=i.find((e=>e.name===d||e.aliases.includes(d))),m=l.includes(o),y=u.includes(o);if(h){const e=h.aliases[0],s=n[0][1];if(Array.isArray(s)){const t=s.map((e=>p(e))),a=h.parseChildren({operator:e,children:t},r.getConfig());return delete a.children,{...a,...c(n)}}const i=p(s);if(!f(i)||!Jr(i,h)||t(i)||a(i)){return{operator:e,[h.parameters[0].name]:i}}return{operator:e,...i,...c(n)}}if(m){const r=p(e[n[0][0]]);if(!f(r))throw new Error("Invalid shorthand Fragment");return{fragment:o,...r,...c(n)}}if(y){const e=o,r=n[0][1],s=p(r);if(!f(s)||t(s)||a(s)){return{operator:e,["args"]:s}}return{operator:e,...s,...c(n)}}return Object.fromEntries(n.map((([e,r])=>[e,p(r)])))},c=e=>{const r=e.slice(1);return Object.fromEntries(r.map((([e,r])=>[e,p(r)])))};return p(e)},exports.convertToShorthand=(e,r,t=2)=>{const a=r.getOperators(),i=r.getFragments(),n=r.getCustomFunctions(),o=r.getOptions().fragments,l=a.map((e=>[e.name,...e.aliases])).flat(),u=i.map((e=>e.name)),p=n.map((e=>e.name)),c=new Set([...l,...u,...p]),d=e=>{if(Array.isArray(e))return e.map((e=>d(e)));if(!f(e))return e;const{operator:i,fragment:n,...l}=e;if(!i&&!n)return Object.fromEntries(Object.entries(e).map((([e,r])=>[e,d(r)])));if(i&&Array.isArray(l.children)){const e=s(i),t=a.find((r=>r.name===e||r.aliases.includes(e)));if(t){const e=t.parseChildren({...l,operator:i},r.getConfig());return delete e.children,d(e)}}const u=p.includes(i);n&&l?.parameters&&(Object.entries(l.parameters).forEach((([e,r])=>{l[e]=r})),delete l.parameters);const h=u?i:zr(i,a),m=`$${h??n}`,y=n?Wr(n,o):[],g=Object.keys(l).filter((e=>Br(e,c)&&!y.includes(e))),v=Object.entries(l).filter((([e])=>!g.includes(e)&&!y.includes(e))).map((([e,r])=>[e,d(r)])),b=Object.fromEntries(g.map((e=>[e,d(l[e])]))),T=Object.fromEntries(y.map((e=>[e,d(l[e])])));switch(!0){case Object.keys(T).length>0:return{[m]:T,...b};case u:return 1!==v.length||"input"in l?{[m]:Object.fromEntries(v),...b}:{[m]:v[0][1]};case Mr(i,l,a):return 1===v.length?{[m]:v[0][1]}:{[m]:Object.fromEntries(v),...b};case"match"===h:return{[m]:Object.fromEntries(v),...b};case v.length>t||!!n||v.some((([e])=>"useCache"===e||"outputType"===e))||v.some((e=>Array.isArray(e[1]))):return{[m]:Object.fromEntries(v),...b};case 1===v.length:return{[m]:v[0][1],...b};default:return{[m]:Hr(s(i),v,a),...b}}};return d(e)},exports.convertV1ToV2=(e,r)=>{const t=r.getOperators(),a=e=>{if(!f(e))return e;const i=$r(e)?(()=>{const{operator:a}=e,i=s(a),n=t.find((e=>e.name===i||e.aliases.includes(i)));if(n){const t=n.parseChildren(e,r.getConfig());delete t.children;const a=n.aliases[0];return t.operator=a,t}throw new Error("Invalid operator: "+a)})():e,n={};for(const[e,r]of Object.entries(i)){const t="type"===e?"outputType":e;Array.isArray(r)?n[t]=r.map((e=>a(e))):n[t]=a(r)}return n};return a(e)},exports.evaluateExpression=(e,r)=>new _r(r).evaluate(e),exports.isAliasString=u,exports.isFigTreeError=e=>e instanceof w,exports.isFigTreeExpression=e=>t(e)||a(e)||"string"==typeof e&&u(e)||f(e)&&1===Object.keys(e).length&&u(Object.keys(e)[0]),exports.isFragmentNode=a,exports.isObject=f,exports.isOperatorNode=t,exports.isV1Node=$r,exports.preProcessShorthand=v,exports.standardiseOperatorName=s,exports.truncateString=o;
|
|
1
|
+
"use strict";var e=require("object-property-extractor"),r=require("dequal/lite");const t=e=>e instanceof Object&&"operator"in e,a=e=>e instanceof Object&&"fragment"in e,s=e=>{const r=m(e);return r||e},n=(e,r)=>r[s(e)],i=(e,r,t)=>{const a={...e};return r.forEach((e=>{t[s(e)]||console.warn(`Invalid operator exclusion: ${e}`),delete a[t[s(e)]]})),a},o=(e,r=200)=>e.length<r?e:`${e.slice(0,r-2).trim()}...`,l=(e,r)=>{const t=Object.entries(e).map((([e,t])=>[r(e),t]));return Object.fromEntries(t)},u=e=>/^\$.+/.test(e),c=(e,{resolvedAliasNodes:r})=>"string"==typeof e&&u(e)?r?.[e]??e:e,p=(e,r,t)=>{const a={...e,...r};return t?((e.data||r.data)&&(a.data={...e.data,...r.data}),(e.functions||r.functions)&&(a.functions={...e.functions,...r.functions}),(e.fragments||r.fragments)&&(a.fragments={...e.fragments,...r.fragments}),(e.headers||r.headers)&&(a.headers={...e.headers,...r.headers}),a):a},d={number:e=>h(e),string:e=>String(e),array:e=>Array.isArray(e)?e:[e],boolean:e=>Boolean(e),bool:e=>Boolean(e)},h=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},m=e=>e.replace(/[^A-Za-z\d _-]/g,"").split(/[-_ ]/).map((e=>e.match(/[a-z]+|[A-Z]+[a-z]*/g)??e)).flat().filter((e=>""!==e)).map(((e,r)=>0===r?e.toLowerCase():e.charAt(0).toUpperCase()+e.slice(1).toLowerCase())).join(""),f=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),y={and:"AND","&":"AND","&&":"AND",or:"OR","|":"OR","||":"OR","=":"EQUAL",eq:"EQUAL",equal:"EQUAL",equals:"EQUAL","!=":"NOT_EQUAL",notEqual:"NOT_EQUAL","!":"NOT_EQUAL",ne:"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",getData:"OBJECT_PROPERTIES",dataProperties:"OBJECT_PROPERTIES",data:"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",get:"GET",api:"GET",POST:"POST",post:"POST",sql:"SQL",pgSql:"SQL",postgres:"SQL",pg:"SQL",sqLite:"SQL",sqlite:"SQL",mySql:"SQL",graphQL:"GRAPHQL",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",pass:"PASSTHRU",_:"PASSTHRU",passThru:"PASSTHRU",passthru:"PASSTHRU",ignore:"PASSTHRU",coerce:"PASSTHRU",convert:"PASSTHRU"},g=y,v=(e,r={},t,a=!0)=>a&&f(e)?b(e,r,t):e,b=(e,r,s)=>{if(t(e)||a(e))return e;const n=Object.entries(e),i=n.filter((([e])=>u(e))),o=n.filter((([e])=>!u(e)));return{...i.reduce(((e,[t,a])=>e={...e,...T(t,a,r,s)}),{}),...Object.fromEntries(o)}},T=(e,r,t,a)=>{const s=e.slice(1),i=n(s,g);return i?Array.isArray(r)?{operator:i,children:r}:f(r)&&!Object.keys(r).some((e=>u(e)))?{operator:i,...r}:{operator:i,children:[r]}:s in t?{fragment:s,parameters:{...r}}:a.includes(s)?Array.isArray(r)?{operator:s,args:r}:f(r)?"input"in r||"args"in r?{operator:s,...r}:{operator:s,input:r}:{operator:s,args:[r]}:{[e]:r}};class w extends Error{constructor(e,r,t,a){super(e.message),Object.assign(this,e),this.operator=r,this.expression=a,this.errorData=e.errorData,t&&(this.name=t),"Error"===this.name&&(this.name="FigTreeError");const s=(r?"Operator: "+r:"")+("FigTreeError"===this.name?"":` - ${this.name}`),n=this.errorData?"\n"+JSON.stringify(this.errorData,null,2):"";this.prettyPrint=`${""!==s?s+"\n":""}${this.message}${"\n{}"===n?"":n}`}}const C=({fallback:e,operator:r,name:t,error:a,expression:s,returnErrorAsString:n=!1})=>{if(void 0!==e)return e;if(a instanceof w){if(!n)throw a;return a.prettyPrint}const i=new w("string"==typeof a?new Error(a):a,r,t,s);if(n)return i.prettyPrint;throw i},E=e=>f(e)&&"literal"in e,A=({value:e,name:r,expectedType:t})=>{if(E(t)){const{literal:a}=t;return!!a.includes(e)||O(r,e,`Literal(${a.map((e=>void 0===e?"undefined":`"${e}"`)).join(", ")})`)}if(Array.isArray(t))return!!t.some((t=>!0===A({value:e,name:r,expectedType:t})))||O(r,e,t.join("|"));return!!(0,q[t])(e)||O(r,e,t)},S=(...e)=>{const r=[];return e.forEach((e=>{const t=A(e);!0!==t&&r.push(t)})),!(r.length>0)||r.join("\n")},q={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=>f(e),undefined:e=>void 0===e},O=(e,r,t)=>void 0===r&&e?`- Missing required property "${e}" (type: ${t})`:void 0!==e?`- Property "${e}" (value: ${x(r)}) is not of type: ${t}`:`- ${x(r)} is not of type: ${t}`,x=e=>{const r=void 0===e||Number.isNaN(e)?String(e):JSON.stringify(e);return o(r,50)},N=e=>{const r={};return e.forEach((e=>{e.aliases.forEach((t=>r[t]=e.name))})),r},j=(e,r)=>e.map((({name:e,required:t,type:a})=>{if(E(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 n=1===s.length?s[0]:s;return{name:e,value:r[e],expectedType:n}})),P=(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=S(...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=>f(e)&&1===Object.keys(e).length?Object.values(e)[0]:e,I=(r,t,a=void 0)=>{const s=t?e(r,t,a):r;return Array.isArray(s)?s.map((e=>k(e))):t?null===s?null:k(s):s},U=e=>/^https?:\/\/.+/.test(e),R=(...e)=>e.reduce(((e,r,t)=>{const a="/"===r[0]?1:0,s="/"===r.slice(-1)?-1:void 0,n=r.slice(a,s);return""===n?e:e+(0===t?"":"/")+n}),""),D=async(e,r)=>{const{url:t,params:a={},data:s={},headers:n={},method:i="get"}=r;if(!t||""===t)throw new Error("Invalid url");try{return await e[i]({url:t,headers:{"Content-Type":"application/json",Accept:"application/json",...n},params:a,data:s})}catch(r){e.throwError(r)}},Q=async(e,r)=>{const{options:s,operators:i,operatorAliases:o}=r;let u=s?.allowJSONStringInput?(e=>{if("string"!=typeof e)return e;try{const r=JSON.parse(e);return t(r)?r:e}catch(r){return e}})(e):e;const p=Object.keys(r.options?.functions??{});u=v(u,r.options?.fragments,p,!s.noShorthand),Array.isArray(u)&&(u=await F(u,r));const h=t(u),m=a(u);if(h&&(u=await(async(e,r)=>{if(!(e.operator in(r.options?.functions??{})))return e;const{operator:t,fallback:a,outputType:s,type:n,useCache:i,input:o,args:l,...u}=e,c={operator:"CUSTOM_FUNCTIONS",function:t};return void 0!==a&&(c.fallback=a),void 0!==s&&(c.outputType=s),void 0!==n&&(c.type=n),void 0!==i&&(c.useCache=i),void 0!==l&&(c.args=l),void 0!==o?c.input=o:Object.keys(u).length>0&&(c.input=u),c})(u,r)),s.evaluateFullObject&&!h&&!m)return c(await $(u,r),r);if(!h&&!m)return s.supportDeprecatedValueNodes&&f(u)&&"value"in u?u.value:c(u,r);const{fallback:y}=u,g=s?.returnErrorAsString??!1;if(m){const e={...u},a=s?.fragments?.[e.fragment]?.metadata?.parameters?.filter((e=>void 0!==e.default));void 0===e.parameters&&(e.parameters={}),a?.forEach((r=>{void 0===e.parameters?.[r.name]&&void 0===e?.[r.name]&&(e.parameters[r.name]=r.default)}));const[n,i]=await F([e.fragment,e.parameters],r),o=v(s?.fragments?.[n],s.fragments,p,!s.noShorthand);if(void 0===o)return C({fallback:await Q(y,r),error:`Fragment not defined: ${n}`,expression:u,returnErrorAsString:g});if(!t(o))return c(o,r);u={...e,...o,...i},delete u.fragment}const b=u,T=n(b.operator,o);if(!T)return C({fallback:await Q(y,r),error:`Invalid operator: ${b.operator}`,expression:u,returnErrorAsString:g});if(!r.operators[T])return C({fallback:await Q(y,r),error:`Excluded operator: ${b.operator}`,expression:u,returnErrorAsString:g});const{propertyAliases:w,evaluate:E,parseChildren:A}=i[T];let S=((e,r)=>l(r,(r=>r in e?e[r]:r)))(w,b);const q=await _(S,r);m||Object.entries(q).forEach((([e,t])=>r.resolvedAliasNodes[e]=t));const O=m?{...r,resolvedAliasNodes:{...r.resolvedAliasNodes,...q}}:r;if("children"in S){if(Array.isArray(S.children)||(S.children=await Q(S.children,O)),!Array.isArray(S.children))return C({fallback:await Q(y,r),operator:T,name:"Type Error",error:'- Property "children" is not of type: array',expression:u,returnErrorAsString:g});try{S=A(S,O),delete S.children}catch(e){return C({fallback:await Q(S.fallback,r),operator:T,error:e,expression:S,returnErrorAsString:g})}}let x;try{x=await E(S,O)}catch(e){return C({fallback:await Q(S.fallback,r),operator:T,error:e,expression:S,returnErrorAsString:g})}const N=S?.outputType??S?.type;if(!N)return x;const j=await Q(N,r);return j in d?d[j](x):C({fallback:await Q(y,r),operator:T,error:`- Invalid output type: ${j}`,expression:S,returnErrorAsString:g})},F=async(e,r)=>Array.isArray(e)?await Promise.all(e.map((e=>Q(e,r)))):await Q(e,r),_=async(e,r)=>{const t=Object.keys(e).filter(u);if(0===t.length)return{};const a=[];t.forEach((t=>a.push(Q(e[t],r))));const s=await Promise.all(a),n=P(t,await Promise.all(a));for(const[e,r]of s.entries())"string"==typeof r&&u(r)&&(n[t[e]]=n?.[r]??r);return n},$=async(e,r)=>{const t=Object.keys(r.options?.functions??{}),a=v(e,r.options?.fragments,t);if(!f(a))return e;const s=[],n=[];Object.entries(a).forEach((([e,t])=>{u(e)&&(n.push(e,Q(t,r)),delete a[e])}));const i=await Promise.all(n);r.resolvedAliasNodes={...r.resolvedAliasNodes,...L(i)},Object.entries(a).forEach((([e,t])=>{s.push(e,Q(t,r))}));const o=await Promise.all(s);return c(L(o),r)},H=[{name:"values",description:"Returns true if all values are true",aliases:[],required:!0,type:"array",default:[!0,!0]}],M=N(H),G={description:"Logical AND",aliases:["and","&","&&"],parameters:H},B=e=>{const r=e.children;return{...e,values:r}},z={propertyAliases:M,operatorData:G,evaluate:async(e,r)=>{const t=await F(e.values,r);return r.typeChecker(j(G.parameters,{values:t})),t.reduce(((e,r)=>e&&!!r),!0)},parseChildren:B},W=[{name:"values",description:"Returns true if any values are true",aliases:[],required:!0,type:"array",default:[!0,!1]}],J=N(W),V={description:"Logical OR",aliases:["or","|","||"],parameters:W},Y={propertyAliases:J,operatorData:V,evaluate:async(e,r)=>{const t=await F(e.values,r);return r.typeChecker(j(V.parameters,{values:t})),t.reduce(((e,r)=>e||!!r),!1)},parseChildren:B},X=[{name:"values",description:"Array of values to check for equality",aliases:[],required:!0,type:"array",default:["These are equal","These are equal"]},{name:"caseInsensitive",description:"If the values are strings, ignore the case (default: false)",aliases:[],required:!1,type:"boolean",default:!1},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],Z=N(X),K={description:"Test multiple values are equal",aliases:["=","eq","equal","equals"],parameters:X},ee={propertyAliases:Z,operatorData:K,evaluate:async(e,t)=>{const[a,s,n]=await F([e.values,e.caseInsensitive,e.nullEqualsUndefined],t);t.typeChecker(j(K.parameters,{values:a,caseInsensitive:s,nullEqualsUndefined:n}));const i=(void 0!==s?s:t.options?.caseInsensitive??!1)&&a.every((e=>"string"==typeof e))?a.map((e=>e.toLowerCase())):a;return!(void 0!==n?n:void 0!==t.options?.nullEqualsUndefined&&t.options.nullEqualsUndefined)||null!==i[0]&&void 0!==i[0]?i.every((e=>r.dequal(e,i[0]))):i.every((e=>null==e))},parseChildren:B},re=[{name:"values",description:"Array of values to check for inequality",aliases:[],required:!0,type:"array",default:["These items","don't match"]},{name:"caseInsensitive",description:"If the values are strings, ignore the case (default: false)",aliases:[],required:!1,type:"boolean",default:!1},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],te=N(re),ae={description:"Test if any values are different",aliases:["!=","notEqual","!","ne"],parameters:re},se={propertyAliases:te,operatorData:ae,evaluate:async(e,t)=>{const[a,s,n]=await F([e.values,e.caseInsensitive,e.nullEqualsUndefined],t);t.typeChecker(j(ae.parameters,{values:a,caseInsensitive:s,nullEqualsUndefined:n}));const i=(void 0!==s?s:t.options?.caseInsensitive??!1)&&a.every((e=>"string"==typeof e))?a.map((e=>e.toLowerCase())):a;return!(void 0!==n?n:void 0!==t.options?.nullEqualsUndefined&&t.options.nullEqualsUndefined)||null!==i[0]&&void 0!==i[0]?i.some((e=>!r.dequal(e,i[0]))):i.some((e=>!(null==e)))},parseChildren:B},ne=[{name:"values",description:"Array of values to check to add together",aliases:[],required:!0,type:"array",default:[1,2,3]},{name:"type",description:"Data type to coerce input values to before addition",aliases:[],required:!1,type:{literal:["string","array","number","boolean","bool"]},default:"string"}],ie=N(ne),oe={description:"Add, concatenate or merge multiple values",aliases:["+","plus","add","concat","join","merge"],parameters:ne},le={propertyAliases:ie,operatorData:oe,evaluate:async(e,r)=>{const t=await F(e.values,r);return r.typeChecker(j(oe.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=>f(e)))?t.reduce(((e,r)=>({...e,...r})),{}):t.reduce(((e,r)=>e+r))},parseChildren:B},ue=[{name:"values",description:"Array of values - 2nd element will be subtracted from the first",aliases:[],required:!1,type:"array",default:[10,5]},{name:"from",description:"Numerical value that will be subtracted from",aliases:["subtractFrom"],required:!1,type:"number",default:100},{name:"subtract",description:"Numerical value to subtract",aliases:[],required:!1,type:"number",default:50}],ce=N(ue),pe={description:"Subtract one numerical value from another",aliases:["-","subtract","minus","takeaway"],parameters:ue},de={propertyAliases:ce,operatorData:pe,evaluate:async(e,r)=>{const[t,a,s]=await F([e.values,e.from,e.subtract],r);r.typeChecker(j(pe.parameters,{values:t,from:a,subtract:s}));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");return n[0]-n[1]},parseChildren:B},he=[{name:"values",description:"Array of values whose product will be calculated",aliases:[],required:!0,type:"array",default:[5,5]}],me=N(he),fe={description:"Multiply several numerical values together",aliases:["*","x","multiply","times"],parameters:he},ye={propertyAliases:me,operatorData:fe,evaluate:async(e,r)=>{const t=await F(e.values,r);if(r.typeChecker(j(fe.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:B},ge=[{name:"values",description:"Array of values - 1st element will be divided by the second",aliases:[],required:!1,type:"array",default:[100,10]},{name:"dividend",description:"The number that will be divided",aliases:["divide"],required:!1,type:"number",default:99},{name:"divisor",description:"The number that dividend will be divided by",aliases:["by","divideBy"],required:!1,type:"number",default:3},{name:"output",description:"Whether to output a quotient, remainder or decimal",aliases:[],required:!1,type:{literal:["quotient","remainder","decimal"]},default:"decimal"}],ve=N(ge),be={description:"Divide one numerical value by another",aliases:["/","divide","÷"],parameters:ge},Te={propertyAliases:ve,operatorData:be,evaluate:async(e,r)=>{const[t,a,s,n]=await F([e.values,e.dividend,e.divisor,e.output],r);r.typeChecker(j(be.parameters,{values:t,dividend:a,divisor:s,output:n}));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");if(0===i[1])throw new Error("Division by zero!");switch(n){case"quotient":return Math.floor(i[0]/i[1]);case"remainder":return i[0]%i[1];default:return i[0]/i[1]}},parseChildren:B},we=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array",default:[10,9]},{name:"strict",description:"Whether value must be strictly greater than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],Ce=N(we),Ee={description:"Test if a value is greater than (or equal to) another value",aliases:[">","greaterThan","higher","larger"],parameters:we},Ae={propertyAliases:Ce,operatorData:Ee,evaluate:async(e,r)=>{const[t,a=!0]=await F([e.values,e.strict],r);if(r.typeChecker(j(Ee.parameters,{values:t,strict:a})),t.length<2)throw new Error("- Not enough values provided");const[s,n]=t;return s===n&&!a||s>n},parseChildren:B},Se=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array",default:[9,10]},{name:"strict",description:"Whether value must be strictly smaller than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],qe=N(Se),Oe={description:"Test if a value is smaller than (or equal to) another value",aliases:["<","lessThan","lower","smaller"],parameters:Se},xe={propertyAliases:qe,operatorData:Oe,evaluate:async(e,r)=>{const[t,a=!0]=await F([e.values,e.strict],r);if(r.typeChecker(j(Oe.parameters,{values:t,strict:a})),t.length<2)throw new Error("- Not enough values provided");const[s,n]=t;return s===n&&!a||s<n},parseChildren:B},Ne=[{name:"condition",description:"The expression to check for truthiness",aliases:[],required:!0,type:"any",default:!0},{name:"valueIfTrue",description:"Value to return if condition is true",aliases:["ifTrue"],required:!0,type:"any",default:"The condition is true"},{name:"valueIfFalse",description:"Value to return if condition is false",aliases:["ifFalse","ifNot"],required:!0,type:"any",default:"The condition is false"}],je=N(Ne),Pe={description:"Return a value based on a condition",aliases:["?","conditional","ifThen"],parameters:Ne},Le={propertyAliases:je,operatorData:Pe,evaluate:async(e,r)=>{r.typeChecker(j(Pe.parameters,{condition:e.condition,valueIfTrue:e.valueIfTrue,valueIfFalse:e.valueIfFalse}));return await Q(e.condition,r)?await Q(e.valueIfTrue,r):await Q(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",default:"test-this"},{name:"pattern",description:"The regular expression pattern",aliases:["regex","regexp","regExp","re"],required:!0,type:"string",default:"^[a-z]{4}-[a-z]{4}$"}],Ie=N(ke),Ue={description:"Compare a string against a regex pattern",aliases:["regex","patternMatch","regexp","matchPattern"],parameters:ke},Re={propertyAliases:Ie,operatorData:Ue,evaluate:async(e,r)=>{const[t,a]=await F([e.testString,e.pattern],r);r.typeChecker(j(Ue.parameters,{testString:t,pattern:a}));return new RegExp(a).test(t)},parseChildren:e=>{const[r,t]=e.children;return{...e,testString:r,pattern:t}}},De=[{name:"property",description:'The path to the required property (e.g. "user.firstName")',aliases:["path","propertyName"],required:!0,type:"string",default:"path.to[0].my.data"},{name:"additionalData",description:"Additional data objects to be considered",aliases:["additional","objects","data","additionalObjects"],required:!1,type:["object","array"],default:{}}],Qe=N(De),Fe={description:"Extract values from data objects",aliases:["getData","dataProperties","data","objectProperties","objProps","getProperty","getObjProp"],parameters:De},_e={propertyAliases:Qe,operatorData:Fe,evaluate:async(r,t)=>{const[a,s={}]=await F([r.property,r.additionalData],t);t.typeChecker(j(Fe.parameters,{property:a,additionalData:s}));const n={...t.options?.data??{},...s};return e(n,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",default:"Hello, %1"},{name:"substitutions",description:"An array of substitution values for the parameterised string",aliases:["replacements","values"],required:!1,type:["array","object"],default:{}},{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",default:!0},{name:"substitutionCharacter",description:'Which character to search for in original string for replacement -- can be "%" or "$" (default: "%")',aliases:["subCharacter","subChar"],required:!1,type:"string",default:"$"},{name:"numberMapping",description:"Rules for mapping number values to text strings, such as pluralisation.",aliases:["numMap","numberMap","pluralisation","pluralization","plurals"],required:!1,type:"object",default:{}}],He=N($e),Me={description:"Replace values in a string using simple parameter substitution",aliases:["stringSubstitution","substitute","stringSub","replace"],parameters:$e},Ge={propertyAliases:He,operatorData:Me,evaluate:async(e,r)=>{const[t,a={},s=!0,n="%",i={}]=await F([e.string,e.substitutions,e.trimWhiteSpace,e.substitutionCharacter,e.numberMapping],r);if(r.typeChecker(j(Me.parameters,{string:t,substitutions:a,trimWhiteSpace:s,substitutionCharacter:n,numberMapping:i})),Array.isArray(a)){const e="$"===n?"$":"%",r=new RegExp(`(?<!\\\\)(${"%"===e?"%":"\\$"}[\\d]+)`,"g"),i=(t.match(r)||[]).sort(((e,r)=>Number(e.slice(1))-Number(r.slice(1)))),o=new Set(i),l=P(Array.from(o),a.map((e=>s?String(e).trim():e)));return t.split(r).map((e=>e in l?l[e]:e)).join("").replace(new RegExp(`\\\\${"$"===e?"\\$":e}`,"g"),e)}const o=/(?<!\\)({{(?:[A-Za-z0-9_.]|\[[0-9]+\])+}})/g,l=[];for(const e of t.split(o)){if(!/(?<!\\){{(.+)}}/.exec(e)){l.push(e.replace(/\\\{\{/g,"{{"));continue}const t=await Be(e,a,i,r);l.push(s?String(t).trim():t)}return l.join("")},parseChildren:e=>{const[r,...t]=e.children;return{...e,string:r,substitutions:t}}},Be=async(r,t,a,s)=>{const n=s.options?.data??{},i=r.replace(/{{(.+)}}/,"$1"),o=await Q(e(t,i,e(n,i,"")),s);if("number"!=typeof o)return o;if(!(i in a))return o;const l=a[i];if(o in l)return l[o].replace("{}",String(o));const u=Object.keys(a[i]),c=u.find((e=>e.startsWith(">")));if(c){if(o>Number(c.slice(1)))return l?.[c]}const p=u.find((e=>e.startsWith("<")));if(p){if(o<Number(p.slice(1)))return l?.[p]}return l.other?l.other.replace("{}",String(o)):o},ze=[{name:"values",description:"An array to count",aliases:[],required:!0,type:"array",default:[1,2,3,4,5]}],We=N(ze),Je={description:"Count elements in an array",aliases:["count","length"],parameters:ze},Ve={propertyAliases:We,operatorData:Je,evaluate:async(e,r)=>{const t=await F(e.values,r);return r.typeChecker(j(Je.parameters,{values:t})),t.length},parseChildren:B},Ye=[{name:"value",description:"The string to be split",aliases:["string"],required:!0,type:"string",default:"Alpha, Bravo, Charlie"},{name:"delimiter",description:"The value to split the string on (default is white space)",aliases:["separator"],required:!1,type:"string",default:","},{name:"trimWhiteSpace",description:"Whether to trim white space from around the resulting elements (default: true)",aliases:["trim","trimWhitespace"],required:!1,type:"boolean",default:!0},{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",default:!0}],Xe=N(Ye),Ze={description:"Split a string into an array",aliases:["split","arraySplit"],parameters:Ye},Ke=" ",er={propertyAliases:Xe,operatorData:Ze,evaluate:async(e,r)=>{const[t,a,s,n]=await F([e.value,e.delimiter??Ke,e.trimWhiteSpace??!0,e.excludeTrailing??!0],r);r.typeChecker(j(Ze.parameters,{value:t,delimiter:a,trimWhiteSpace:s,excludeTrailing:n}));let i=t.split((e=>e.replace(/\\n/g,"\n").replace(/\\t/g,"\t").replace(/\\r/g,"\r"))(a));return s&&(i=i.map((e=>e.trim()))),n&&""===i[i.length-1]&&i.pop(),i},parseChildren:e=>{const[r,t=Ke]=e.children;return{...e,value:r,delimiter:t}}},rr=[{name:"query",description:"SQL query string, with parameterised replacements (e.g. $1, $2, etc)",aliases:["text"],required:!0,type:"string"},{name:"values",description:"An array/object of values to replace the SQL string parameters, as per SQL connection specifications ",aliases:["replacements"],required:!1,type:["array","object"]},{name:"single",description:"Specify if returning a single record",aliases:["singleRecord"],required:!1,type:"boolean"},{name:"flatten",description:"Specify whether to flatten resulting record objects to arrays of values",aliases:["flat","array"],required:!1,type:"boolean"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],tr=N(rr),ar={description:"Query an SQL database",aliases:["sql","pgSql","postgres","pg","sqLite","sqlite","mySql"],parameters:rr},sr={propertyAliases:tr,operatorData:ar,evaluate:async(e,r)=>{const t=r.options?.sqlConnection;if(!t)throw new Error("No SQL database connection provided");const[a,s,n,i,o,l]=await F([e.query,e.values||[],e.single,e.flatten,e.useCache,e.type],r);r.typeChecker(j(ar.parameters,{query:a,single:n,flatten:i,values:s,useCache:o}));const u=e.useCache??r.options.useCache??!0;{const e=r.cache.useCache(u,(async(e,r,a,s,n)=>{const i=await t.query({query:e,values:r})||[];["array","string","number"].includes(n??"")&&(s=!0);const o=s?i.map((e=>{const r=Object.values(e);return r.length<=1?r[0]:r})):i;return a?o[0]:o}),a,s,n,i,l);return e}},parseChildren:e=>{const[r,...t]=e.children;return{...e,query:r,values:t}}},nr=[{name:"query",description:"GraphQL query string",aliases:[],required:!0,type:"string",default:'query getCountries {\n countries(filter: {continent: {eq: "OC"}}) {\n name\n }\n }'},{name:"url",description:"Endpoint for the GraphQL request (if not already provided in options)",aliases:["endpoint"],required:!1,type:["string","null"],default:"https://countries.trevorblades.com/"},{name:"headers",description:"HTTP Headers (if not already provided in options)",aliases:[],required:!1,type:"object",default:{}},{name:"variables",description:"Values for the variables used in query (key-value pairs)",aliases:[],required:!1,type:"object",default:{}},{name:"returnNode",description:"Property path to extract from the query response",aliases:["outputNode","returnProperty"],required:!1,type:"string",default:"data.countries[1].name"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],ir=N(nr),or={description:"GraphQL request",aliases:["graphQL","graphQl","graphql","gql"],parameters:nr},lr={propertyAliases:ir,operatorData:or,evaluate:async(e,r)=>{const t=r.graphQLClient??r.httpClient;if(!t)throw new Error("No HTTP client provided for GraphQL connection");const[a,s,n,i,o,l]=await F([e.query,e.url,await $(e.variables,r),e.returnNode,e.headers,e.useCache],r),{url:u,headers:c}=s instanceof Object?s:{url:s,headers:null};r.typeChecker([...j(or.parameters,{url:u,query:a,variables:n,returnNode:i,headers:o,useCache:l}),{name:"headers",value:c,expectedType:["object","null"]}]);const p=u&&"graphqlendpoint"!==u.toLowerCase()?u:"",d=r.options.graphQLConnection?.endpoint??r.options.baseEndpoint??"",h=U(p)?p:R(d,p),m={query:a,variables:n},f=l??r.options.useCache??!0,y=await r.cache.useCache(f,(async(e,r,a,s)=>{const n=await D(t,{url:e,method:"post",data:r,headers:a});return I(n?.data,s)}),h,m,{...r.options.graphQLConnection?.headers,...r.options?.headers,...c,...o},i);return y},parseChildren:e=>{const[r,t="",a,...s]=e.children,n=Array.isArray(a)?a:[a],i=s.slice(0,n.length),o=P(n,i),l={...e,query:r,url:t,variables:o};return s.length>n.length&&(l.returnNode=s.pop()),l}},ur=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string",default:"https://restcountries.com/v3.1/name/zealand"},{name:"returnProperty",description:"Property from request result",aliases:["outputProperty"],required:!1,type:"string",default:"result.path"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object",default:{}},{name:"parameters",description:"Query parameters (key-value)",aliases:["queryParams","queryParameters","urlQueries"],required:!1,type:"object",default:{}},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],cr=N(ur),pr={description:"HTTP GET Request",aliases:["GET","get","api"],parameters:ur},dr=e=>{const[r="",t,...a]=e.children,s=Array.isArray(t)?t:[t],n=a.slice(0,s.length),i=P(s,n),o={...e,url:r,parameters:i};return a.length>s.length&&(o.returnProperty=a.pop()),o},hr=dr,mr={propertyAliases:cr,operatorData:pr,evaluate:async(e,r)=>{const t=r.httpClient;if(!t)throw new Error("No HTTP client provided");const[a,s,n,i,o]=await F([e.url,await $(e.parameters,r),e.returnProperty,await $(e.headers,r),e.useCache],r),{url:l,headers:u}=a instanceof Object?a:{url:a,headers:null};r.typeChecker([...j(pr.parameters,{url:l,returnProperty:n,headers:i,parameters:s,useCache:o}),{name:"headers",value:u,expectedType:["object","null"]}]);const c=r.options.baseEndpoint??"",p={...r.options?.headers,...u,...i},d=o??r.options.useCache??!0,h=await r.cache.useCache(d,(async(e,r,a,s)=>{const n=await D(t,{url:e,params:r,headers:a});return I(n,s)}),U(l)?l:R(c,l),s,p,n);return h},parseChildren:dr},fr=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string",default:"https://jsonplaceholder.typicode.com/posts"},{name:"returnProperty",description:"Property path from request result",aliases:["outputProperty"],required:!1,type:"string",default:"result.path"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object",default:{}},{name:"parameters",description:"JSON Body parameters (key-value)",aliases:["bodyJson","data"],required:!1,type:"object",default:{}},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],yr=N(fr),gr={description:"HTTP POST Request",aliases:["POST","post"],parameters:fr},vr={propertyAliases:yr,operatorData:gr,evaluate:async(e,r)=>{const t=r.httpClient;if(!t)throw new Error("No HTTP client provided");const[a,s,n,i,o]=await F([e.url,await $(e.parameters,r),e.returnProperty,await $(e.headers,r),e.useCache],r),{url:l,headers:u}=a instanceof Object?a:{url:a,headers:null};r.typeChecker([...j(gr.parameters,{url:l,headers:i,data:s,returnProperty:n,useCache:o}),{name:"headers",value:u,expectedType:["object","null"]}]);const c=r.options.baseEndpoint??"",p={...r.options?.headers,...u,...i},d=o??r.options.useCache??!1,h=await r.cache.useCache(d,(async(e,r,a,s)=>{const n=await D(t,{url:e,data:r,headers:a,method:"post"});return I(n,s)}),U(l)?l:R(c,l),s,p,n);return h},parseChildren:hr},br=[{name:"properties",description:'An array of objects, each with a "key" property and a "value" property',aliases:["values","keyValPairs","keyValuePairs"],required:!0,type:"array",default:["firstKey","firstValue","secondKey","secondValue"]}],Tr=N(br),wr={description:"Construct an object using objects defining keys and values",aliases:["buildObject","build","object"],parameters:br},Cr=e=>{const r=e.children;if(r.every((e=>f(e))))return{...e,properties:r};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}},Er={propertyAliases:Tr,operatorData:wr,evaluate:async(e,r)=>{const t=await F(e.properties,r);r.typeChecker(j(wr.parameters,{properties:t}));const{properties:a}=t.some((e=>!f(e)))?Cr({...e,children:t}):{properties:t},s=a.filter((e=>e instanceof Object&&"key"in e&&"value"in e)).map((({key:e,value:t})=>(async e=>{const[t,a]=await F(e,r);return r.typeChecker({name:"key",value:t,expectedType:["string","number","boolean"]}),[t,a]})([e,t])));return Object.fromEntries(await Promise.all(s))},parseChildren:Cr},Ar=[{name:"matchExpression",description:"Expression to match against",aliases:["matchValue"],required:!0,type:["string","number","boolean"],default:"matchMe"},{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"],default:{matchMe:"YES",nonMatch:"NO"}},{name:"[...branches]",description:"Branch properties can optionally be placed at the operator root",aliases:[],required:!1,type:["object","array"]}],Sr={propertyAliases:N(Ar),operatorData:{description:"Return different values depending on a matching expression",aliases:["match","switch"],parameters:Ar},evaluate:async(e,r)=>{const a=await Q(e.matchExpression,r);r.typeChecker({name:"matchExpression",value:a,expectedType:["string","number","boolean"]});const s=Array.isArray(e.branches)?L(e.branches):e.branches??{},n=t(s)?await Q(s,r):s;if(!f(n))throw new Error("Branches don't evaluate to an object");if(a in n)return await Q(n[a],r);if("fallback"in n)return await Q(n.fallback,r);if(a in e)return await Q(e[a],r);throw new Error(`No match found for ${a}`)},parseChildren:e=>{const[r,...t]=e.children,a=L(t);return{...e,matchExpression:r,branches:a}}},qr=[{name:"functionName",description:"Path (in options.functions) to the required function",aliases:["functionPath","funcName","function","path","name"],required:!0,type:"string",default:null},{name:"args",description:"Arguments for the function",aliases:["arguments","variables"],required:!1,type:["array","any"],default:[]},{name:"input",description:"Argument for the function if a single input parameter",aliases:["arg"],required:!1,type:"any",default:"input"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!1}],Or=N(qr),xr={description:"Call a custom function (defined in options)",aliases:["customFunctions","customFunction","objectFunctions","function","functions","runFunction"],parameters:qr},Nr={propertyAliases:Or,operatorData:xr,evaluate:async(r,t)=>{const[a,s=[],n,i]=await F([r.functionName,r.args,r.input,r.useCache],t);t.typeChecker(j(xr.parameters,{functionName:a,args:s}));const{data:o,functions:l}=t.options;if(!l)throw new Error("- No functions defined");const u=e(l,`${a}.function`,null)??e(l,a,null)??e(t.options,`${a}.function`,null)??e(t.options,a,null)??e(o,a,null);if(!u||"function"!=typeof u)throw new Error(`- No function found: "${a}"`);const c=i??t.options.useCache??!1,p=[...void 0===n?[]:[await $(n,t)],...Array.isArray(s)?s:[s]];return await t.cache.useCache(c,(async(e,...r)=>await u(...r)),a,...p)},parseChildren:e=>{const[r,...t]=e.children;return{...e,functionName:r,args:t}}},jr=[{name:"value",description:"Value to pass through",aliases:["_","data"],required:!0,type:"any",default:null}],Pr=N(jr),Lr={description:"Pass through a value unchanged (or change its type)",aliases:["pass","_","passThru","passthru","ignore","coerce","convert"],parameters:jr},kr={propertyAliases:Pr,operatorData:Lr,evaluate:async(e,r)=>(r.typeChecker(j(Lr.parameters,{value:e.value})),await Q(e.value,r)),parseChildren:e=>{const[...r]=e.children,t=1===r?.length?r[0]:r;return{...e,value:t}}};var Ir=Object.freeze({__proto__:null,AND:z,BUILD_OBJECT:Er,CONDITIONAL:Le,COUNT:Ve,CUSTOM_FUNCTIONS:Nr,DIVIDE:Te,EQUAL:ee,GET:mr,GRAPHQL:lr,GREATER_THAN:Ae,LESS_THAN:xe,MATCH:Sr,MULTIPLY:ye,NOT_EQUAL:se,OBJECT_PROPERTIES:_e,OR:Y,PASSTHRU:kr,PLUS:le,POST:vr,REGEX:Re,SPLIT:er,SQL:sr,STRING_SUBSTITUTION:Ge,SUBTRACT:de});const Ur=(e,r,s)=>{const{fragments:n,functionNames:i,evaluateFullObject:o,useShorthand:l}=r;if(f(e)){const c=v(e,n,i,l);if(t(c)||a(c))return!0;if(!o)return!1;const p=new Set([...s,...Object.keys(e).filter(u)]);return Object.values(e).some((e=>Ur(e,r,p)))}return Array.isArray(e)?e.some((e=>Ur(e,r,s))):!("string"!=typeof e||!u(e))&&s.has(e)};class Rr{constructor(e){this.useCache=async(e,r,...t)=>{if(!e)return await r(...t);const a=Dr(t),s=a in this.store,n=Date.now(),i=s&&n-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=n,i&&(this.store[a].result=await r(...t)),this.store[a].result;const o=await r(...t);return this.store[a]={result:o,timestamp:n},this.queue.unshift(a),this.resizeCache(),o},this.getMax=()=>this.maxSize,this.setMax=e=>{this.maxSize=e,this.resizeCache()},this.getMaxTime=()=>this.maxTime,this.setMaxTime=e=>{this.maxTime=e},this.getCache=()=>this.store,this.setCache=e=>this.store=e,this.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)}},this.store={},this.queue=[],this.maxSize=e?.maxSize??50,this.maxTime=e?.maxTime??1800}}const Dr=e=>e.map((e=>"object"==typeof e?JSON.stringify(e):e)).join("_"),Qr=e=>e||("undefined"!=typeof window&&"document"in window&&"fetch"in window?Fr(window.fetch):void 0),Fr=e=>({get:async r=>{const{url:t,headers:a,params:s={}}=r,n=Object.keys(s).length>0?`?${new URLSearchParams(s).toString()}`:"",i=await e(t+n,{headers:a,method:"GET"}),o=await i.json();if(!i.ok){const e=new Error("Problem with GET request");throw e.name="FetchError",e.errorData={status:i.status,error:i.statusText,url:i.url,response:o},console.log(e.errorData),e}return o},post:async r=>{const{url:t,headers:a,params:s,data:n}=r,i=new URLSearchParams(s),o=i.size>0?`?${i.toString()}`:"",l=await e(t+o,{headers:a,body:JSON.stringify(n),method:"POST"}),u=await l.json();if(!l.ok){const e=new Error("Problem with POST request");throw e.name="FetchError",e.errorData={status:l.status,error:l.statusText,url:l.url,response:u},console.log(e.errorData),e}return u},throwError:e=>{throw e}});class _r{constructor(e={}){this.typeChecker=(...e)=>{const r=1===e.length&&Array.isArray(e[0])?e[0]:e,t=S(...r);if(!0===t)return;const a=new Error(t);throw a.name="Type Error",a},this.getCache=()=>this.cache.getCache(),this.setCache=e=>this.cache.setCache(e),this.getVersion=()=>"2.23.1",this.options=$r(e),this.operators=i(Ir,this.options?.excludeOperators??[],y),this.operatorAliases=y,this.cache=new Rr({maxSize:e.maxCacheSize,maxTime:e.maxCacheTime}),this.graphQLClient=Qr(e.graphQLConnection?.httpClient),this.httpClient=Qr(e.httpClient)}async evaluate(e,r={}){const t=p(this.options,$r(r),!0);return r.httpClient&&(this.httpClient=Qr(r.httpClient)),r.graphQLConnection?.httpClient&&(this.graphQLClient=Qr(r.graphQLConnection.httpClient)),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 Q(e,{options:t,operators:r.excludeOperators?i(Ir,r.excludeOperators,y):this.operators,operatorAliases:this.operatorAliases,typeChecker:t.skipRuntimeTypeCheck?()=>{}:this.typeChecker,resolvedAliasNodes:{},cache:this.cache,graphQLClient:this.graphQLClient,httpClient:this.httpClient})}isFigTreeExpression(e){return((e,r)=>Ur(e,r,new Set))(e,{fragments:this.options.fragments??{},functionNames:Object.keys(this.options.functions??{}),evaluateFullObject:this.options.evaluateFullObject??!1,useShorthand:!this.options.noShorthand})}getOptions(){return this.options}updateOptions(e){this.options=p(this.options,$r(e),!1),this.options.excludeOperators&&(this.operators=i(Ir,this.options.excludeOperators,y))}getOperators(){const e=this.options.excludeOperators?i(Ir,this.options.excludeOperators,y):this.operators,r=Object.entries(e).map((([e,r])=>({name:e,...r.operatorData,parseChildren:r.parseChildren}))),t=[...new Set(Object.values(y))];return r.sort(((e,r)=>t.indexOf(e.name)-t.indexOf(r.name)))}getFragments(){return Object.entries(this.options.fragments??{}).map((([e,r])=>({name:e,...r?.metadata})))}getCustomFunctions(){return Object.entries(this.options.functions??{}).map((([e,r])=>{const t="function"==typeof r?r:r?.function,a={name:e,numRequiredArgs:t?.length};if("function"!=typeof r){const{description:e,argsDefault:t,inputDefault:s,textColor:n,backgroundColor:i}=r;return e&&(a.description=e),void 0!==t&&(a.argsDefault=t),void 0!==s&&(a.inputDefault=s),n&&(a.textColor=n),i&&(a.backgroundColor=i),a}return a}))}getConfig(){return{options:this.options,operators:this.options.excludeOperators?i(Ir,this.options.excludeOperators,y):this.operators,operatorAliases:this.operatorAliases,typeChecker:this.options.skipRuntimeTypeCheck?()=>{}:this.typeChecker,resolvedAliasNodes:{},cache:this.cache,graphQLClient:this.graphQLClient,httpClient:this.httpClient}}}const $r=e=>"objects"in e?{...e,data:e.objects}:e,Hr=e=>f(e)&&"operator"in e&&"children"in e&&Array.isArray(e.children),Mr=(e,r,t)=>{const a=t.find((r=>r.name===e||r.aliases.includes(e)));if(!a)throw new Error("Invalid operator: "+e);const s=[];switch(a.name){case"OBJECT_PROPERTIES":{if(Br("additionalData",r,a.parameters))return Object.fromEntries(r);const e=Br("property",r,a.parameters);if(!e)throw new Error("Missing required property for operator $getData: property");const t=r.find((([e])=>"fallback"===e));return t?[e[1],t[1]]:e[1]}case"GET":case"POST":case"GRAPHQL":return Object.fromEntries(r);default:{const t=new Set;for(const{name:n,aliases:i,required:o}of a.parameters){const a=[n,...i],l=r.find((([e])=>a.includes(e)));if(void 0===l&&o)throw new Error(`Missing required property for operator ${e}: ${n}`);if(void 0===l)break;s.push(l[1]),t.add(l[0])}if(r.some((([e])=>!t.has(e))))return Object.fromEntries(r)}}return s},Gr=(e,r,t)=>{if(!e)return!1;const a=s(e),n=t.find((e=>e.name===a||e.aliases.includes(a)))?.parameters[0];if(!n)return!1;return!!("array"===n.type||Array.isArray(n.type)&&n.type.includes("array"))&&[n.name,...n.aliases].some((e=>e in r))},Br=(e,r,t)=>{const a=t.find((r=>r.name===e));if(!a)return;const s=[a.name,...a.aliases];return r.find((([e])=>s.includes(e)))},zr=(e,r)=>u(e)&&!r.has(e),Wr=(e,r)=>{if(!e)return;const t=r.find((r=>e===r.name||r.aliases.includes(s(e))));return t?.aliases.find((e=>/^[A-Za-z_]{2,}$/.test(e)))},Jr=(e,r={})=>{const t=r[e];if(!t)throw new Error("Fragment referenced in expression that is not defined in FigTree: "+e);const a=JSON.stringify(t).match(/"(\$\w+)"/gm);if(!a)return[];const s=new Set;return a.forEach((e=>s.add(e.replace(/"/g,"")))),Array.from(s)},Vr=(e,r)=>{const t=r.parameters.map((e=>[e.name,...e.aliases])).flat();return Object.keys(e).some((e=>t.includes(e)))};Object.defineProperty(exports,"dequal",{enumerable:!0,get:function(){return r.dequal}}),exports.AxiosClient=e=>({get:async r=>(await e({...r,method:"get"})).data,post:async r=>(await e({...r,method:"post"})).data,throwError:r=>{if(e.isAxiosError(r)&&r.response)throw r.errorData={status:r.response?.status,error:r.response?.statusText,url:r.config?.url,response:r.response?.data},r;throw new Error("Network error: "+r?.message)}}),exports.FetchClient=Fr,exports.FigTreeError=w,exports.FigTreeEvaluator=_r,exports.SQLNodePostgres=e=>({query:async({query:r,values:t=[]})=>{const a={text:r,values:t??[]};try{const r=await e.query(a);if(r?.error)throw new Error(r.error);return r.rows}catch(e){throw e.name="Node-Postgres error",e}}}),exports.SQLite=e=>({query:async({query:r,values:t=[]})=>{try{return await e.all(r,t)}catch(e){throw e.name="SQLite error",e}}}),exports.convertFromShorthand=(e,r)=>{const n=r.getOperators(),i=r.getFragments(),o=r.getCustomFunctions(),l=i.map((e=>e.name)),u=o.map((e=>e.name)),c=e=>{if(Array.isArray(e))return e.map((e=>c(e)));if(!f(e))return e;const i=Object.entries(e);if(0===i.length)return e;const o=i[0][0].replace("$",""),d=s(o),h=n.find((e=>e.name===d||e.aliases.includes(d))),m=l.includes(o),y=u.includes(o);if(h){const e=h.aliases[0],s=i[0][1];if(Array.isArray(s)){const t=s.map((e=>c(e))),a=h.parseChildren({operator:e,children:t},r.getConfig());return delete a.children,{...a,...p(i)}}const n=c(s);if(!f(n)||!Vr(n,h)||t(n)||a(n)){return{operator:e,[h.parameters[0].name]:n}}return{operator:e,...n,...p(i)}}if(m){const r=c(e[i[0][0]]);if(!f(r))throw new Error("Invalid shorthand Fragment");return{fragment:o,...r,...p(i)}}if(y){const e=o,r=i[0][1],s=c(r);if(!f(s)||t(s)||a(s)){return{operator:e,["args"]:s}}return{operator:e,...s,...p(i)}}return Object.fromEntries(i.map((([e,r])=>[e,c(r)])))},p=e=>{const r=e.slice(1);return Object.fromEntries(r.map((([e,r])=>[e,c(r)])))};return c(e)},exports.convertToShorthand=(e,r,t=2)=>{const a=r.getOperators(),n=r.getFragments(),i=r.getCustomFunctions(),o=r.getOptions().fragments,l=a.map((e=>[e.name,...e.aliases])).flat(),u=n.map((e=>e.name)),c=i.map((e=>e.name)),p=new Set([...l,...u,...c]),d=e=>{if(Array.isArray(e))return e.map((e=>d(e)));if(!f(e))return e;const{operator:n,fragment:i,...l}=e;if(!n&&!i)return Object.fromEntries(Object.entries(e).map((([e,r])=>[e,d(r)])));if(n&&Array.isArray(l.children)){const e=s(n),t=a.find((r=>r.name===e||r.aliases.includes(e)));if(t){const e=t.parseChildren({...l,operator:n},r.getConfig());return delete e.children,d(e)}}const u=c.includes(n);i&&l?.parameters&&(Object.entries(l.parameters).forEach((([e,r])=>{l[e]=r})),delete l.parameters);const h=u?n:Wr(n,a),m=`$${h??i}`,y=i?Jr(i,o):[],g=Object.keys(l).filter((e=>zr(e,p)&&!y.includes(e))),v=Object.entries(l).filter((([e])=>!g.includes(e)&&!y.includes(e))).map((([e,r])=>[e,d(r)])),b=Object.fromEntries(g.map((e=>[e,d(l[e])]))),T=Object.fromEntries(y.map((e=>[e,d(l[e])])));switch(!0){case Object.keys(T).length>0:return{[m]:T,...b};case u:return 1!==v.length||"input"in l?{[m]:Object.fromEntries(v),...b}:{[m]:v[0][1]};case Gr(n,l,a):return 1===v.length?{[m]:v[0][1]}:{[m]:Object.fromEntries(v),...b};case"match"===h:return{[m]:Object.fromEntries(v),...b};case v.length>t||!!i||v.some((([e])=>"useCache"===e||"outputType"===e))||v.some((e=>Array.isArray(e[1]))):return{[m]:Object.fromEntries(v),...b};case 1===v.length:return{[m]:v[0][1],...b};default:return{[m]:Mr(s(n),v,a),...b}}};return d(e)},exports.convertV1ToV2=(e,r)=>{const t=r.getOperators(),a=e=>{if(!f(e))return e;const n=Hr(e)?(()=>{const{operator:a}=e,n=s(a),i=t.find((e=>e.name===n||e.aliases.includes(n)));if(i){const t=i.parseChildren(e,r.getConfig());delete t.children;const a=i.aliases[0];return t.operator=a,t}throw new Error("Invalid operator: "+a)})():e,i={};for(const[e,r]of Object.entries(n)){const t="type"===e?"outputType":e;Array.isArray(r)?i[t]=r.map((e=>a(e))):i[t]=a(r)}return i};return a(e)},exports.evaluateExpression=(e,r)=>new _r(r).evaluate(e),exports.isAliasString=u,exports.isFigTreeError=e=>e instanceof w,exports.isFigTreeExpression=e=>t(e)||a(e)||"string"==typeof e&&u(e)||f(e)&&1===Object.keys(e).length&&u(Object.keys(e)[0]),exports.isFragmentNode=a,exports.isObject=f,exports.isOperatorNode=t,exports.isV1Node=Hr,exports.preProcessShorthand=v,exports.standardiseOperatorName=s,exports.truncateString=o;
|
package/build/index.d.ts
CHANGED
|
@@ -145,7 +145,7 @@ interface FunctionDefinition {
|
|
|
145
145
|
function: UnknownFunction;
|
|
146
146
|
description?: string;
|
|
147
147
|
argsDefault?: unknown[];
|
|
148
|
-
inputDefault?:
|
|
148
|
+
inputDefault?: unknown;
|
|
149
149
|
textColor?: string;
|
|
150
150
|
backgroundColor?: string;
|
|
151
151
|
}
|
|
@@ -207,6 +207,7 @@ declare class FigTreeEvaluator {
|
|
|
207
207
|
constructor(options?: FigTreeOptions);
|
|
208
208
|
private typeChecker;
|
|
209
209
|
evaluate(expression: EvaluatorNode, options?: FigTreeOptions): Promise<EvaluatorOutput>;
|
|
210
|
+
isFigTreeExpression(expression: EvaluatorNode): boolean;
|
|
210
211
|
getOptions(): FigTreeOptions;
|
|
211
212
|
updateOptions(options: FigTreeOptions): void;
|
|
212
213
|
getCache: () => Store;
|
package/build/index.esm.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import e from"object-property-extractor";import{dequal as r}from"dequal/lite";export{dequal}from"dequal/lite";const t=e=>e instanceof Object&&"operator"in e,a=e=>e instanceof Object&&"fragment"in e,s=e=>{const r=m(e);return r||e},i=(e,r)=>r[s(e)],n=(e,r,t)=>{const a={...e};return r.forEach((e=>{t[s(e)]||console.warn(`Invalid operator exclusion: ${e}`),delete a[t[s(e)]]})),a},o=(e,r=200)=>e.length<r?e:`${e.slice(0,r-2).trim()}...`,l=(e,r)=>{const t=Object.entries(e).map((([e,t])=>[r(e),t]));return Object.fromEntries(t)},u=e=>/^\$.+/.test(e),c=(e,{resolvedAliasNodes:r})=>"string"==typeof e&&u(e)?r?.[e]??e:e,p=(e,r,t)=>{const a={...e,...r};return t?((e.data||r.data)&&(a.data={...e.data,...r.data}),(e.functions||r.functions)&&(a.functions={...e.functions,...r.functions}),(e.fragments||r.fragments)&&(a.fragments={...e.fragments,...r.fragments}),(e.headers||r.headers)&&(a.headers={...e.headers,...r.headers}),a):a},d={number:e=>h(e),string:e=>String(e),array:e=>Array.isArray(e)?e:[e],boolean:e=>Boolean(e),bool:e=>Boolean(e)},h=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},m=e=>e.replace(/[^A-Za-z\d _-]/g,"").split(/[-_ ]/).map((e=>e.match(/[a-z]+|[A-Z]+[a-z]*/g)??e)).flat().filter((e=>""!==e)).map(((e,r)=>0===r?e.toLowerCase():e.charAt(0).toUpperCase()+e.slice(1).toLowerCase())).join(""),f=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),y=e=>t(e)||a(e)||"string"==typeof e&&u(e)||f(e)&&1===Object.keys(e).length&&u(Object.keys(e)[0]),g={and:"AND","&":"AND","&&":"AND",or:"OR","|":"OR","||":"OR","=":"EQUAL",eq:"EQUAL",equal:"EQUAL",equals:"EQUAL","!=":"NOT_EQUAL",notEqual:"NOT_EQUAL","!":"NOT_EQUAL",ne:"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",getData:"OBJECT_PROPERTIES",dataProperties:"OBJECT_PROPERTIES",data:"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",get:"GET",api:"GET",POST:"POST",post:"POST",sql:"SQL",pgSql:"SQL",postgres:"SQL",pg:"SQL",sqLite:"SQL",sqlite:"SQL",mySql:"SQL",graphQL:"GRAPHQL",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",pass:"PASSTHRU",_:"PASSTHRU",passThru:"PASSTHRU",passthru:"PASSTHRU",ignore:"PASSTHRU",coerce:"PASSTHRU",convert:"PASSTHRU"},v=g,b=(e,r={},t,a=!0)=>a&&f(e)?T(e,r,t):e,T=(e,r,s)=>{if(t(e)||a(e))return e;const i=Object.entries(e),n=i.filter((([e])=>u(e))),o=i.filter((([e])=>!u(e)));return{...n.reduce(((e,[t,a])=>e={...e,...w(t,a,r,s)}),{}),...Object.fromEntries(o)}},w=(e,r,t,a)=>{const s=e.slice(1),n=i(s,v);return n?Array.isArray(r)?{operator:n,children:r}:f(r)&&!Object.keys(r).some((e=>u(e)))?{operator:n,...r}:{operator:n,children:[r]}:s in t?{fragment:s,parameters:{...r}}:a.includes(s)?Array.isArray(r)?{operator:s,args:r}:f(r)?"input"in r||"args"in r?{operator:s,...r}:{operator:s,input:r}:{operator:s,args:[r]}:{[e]:r}};class C extends Error{constructor(e,r,t,a){super(e.message),Object.assign(this,e),this.operator=r,this.expression=a,this.errorData=e.errorData,t&&(this.name=t),"Error"===this.name&&(this.name="FigTreeError");const s=(r?"Operator: "+r:"")+("FigTreeError"===this.name?"":` - ${this.name}`),i=this.errorData?"\n"+JSON.stringify(this.errorData,null,2):"";this.prettyPrint=`${""!==s?s+"\n":""}${this.message}${"\n{}"===i?"":i}`}}const E=e=>e instanceof C,A=({fallback:e,operator:r,name:t,error:a,expression:s,returnErrorAsString:i=!1})=>{if(void 0!==e)return e;if(a instanceof C){if(!i)throw a;return a.prettyPrint}const n=new C("string"==typeof a?new Error(a):a,r,t,s);if(i)return n.prettyPrint;throw n},S=e=>f(e)&&"literal"in e,q=({value:e,name:r,expectedType:t})=>{if(S(t)){const{literal:a}=t;return!!a.includes(e)||j(r,e,`Literal(${a.map((e=>void 0===e?"undefined":`"${e}"`)).join(", ")})`)}if(Array.isArray(t))return!!t.some((t=>!0===q({value:e,name:r,expectedType:t})))||j(r,e,t.join("|"));return!!(0,N[t])(e)||j(r,e,t)},O=(...e)=>{const r=[];return e.forEach((e=>{const t=q(e);!0!==t&&r.push(t)})),!(r.length>0)||r.join("\n")},N={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=>f(e),undefined:e=>void 0===e},j=(e,r,t)=>void 0===r&&e?`- Missing required property "${e}" (type: ${t})`:void 0!==e?`- Property "${e}" (value: ${P(r)}) is not of type: ${t}`:`- ${P(r)} is not of type: ${t}`,P=e=>{const r=void 0===e||Number.isNaN(e)?String(e):JSON.stringify(e);return o(r,50)},x=e=>{const r={};return e.forEach((e=>{e.aliases.forEach((t=>r[t]=e.name))})),r},L=(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}})),k=(e,r)=>{const t=e.map(((e,t)=>[e,r[t]]));return Object.fromEntries(t)},I=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=O(...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},U=e=>f(e)&&1===Object.keys(e).length?Object.values(e)[0]:e,R=(r,t,a=void 0)=>{const s=t?e(r,t,a):r;return Array.isArray(s)?s.map((e=>U(e))):t?null===s?null:U(s):s},D=e=>/^https?:\/\/.+/.test(e),Q=(...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}),""),_=async(e,r)=>{const{url:t,params:a={},data:s={},headers:i={},method:n="get"}=r;if(!t||""===t)throw new Error("Invalid url");try{return await e[n]({url:t,headers:{"Content-Type":"application/json",Accept:"application/json",...i},params:a,data:s})}catch(r){e.throwError(r)}},$=async(e,r)=>{const{options:s,operators:n,operatorAliases:o}=r;let u=s?.allowJSONStringInput?(e=>{if("string"!=typeof e)return e;try{const r=JSON.parse(e);return t(r)?r:e}catch(r){return e}})(e):e;const p=Object.keys(r.options?.functions??{});u=b(u,r.options?.fragments,p,!s.noShorthand),Array.isArray(u)&&(u=await F(u,r));const h=t(u),m=a(u);if(h&&(u=await(async(e,r)=>{if(!(e.operator in(r.options?.functions??{})))return e;const{operator:t,fallback:a,outputType:s,type:i,useCache:n,input:o,args:l,...u}=e,c={operator:"CUSTOM_FUNCTIONS",function:t};return void 0!==a&&(c.fallback=a),void 0!==s&&(c.outputType=s),void 0!==i&&(c.type=i),void 0!==n&&(c.useCache=n),void 0!==l&&(c.args=l),void 0!==o?c.input=o:Object.keys(u).length>0&&(c.input=u),c})(u,r)),s.evaluateFullObject&&!h&&!m)return c(await M(u,r),r);if(!h&&!m)return s.supportDeprecatedValueNodes&&f(u)&&"value"in u?u.value:c(u,r);const{fallback:y}=u,g=s?.returnErrorAsString??!1;if(m){const e={...u},a=s?.fragments?.[e.fragment]?.metadata?.parameters?.filter((e=>void 0!==e.default));void 0===e.parameters&&(e.parameters={}),a?.forEach((r=>{void 0===e.parameters?.[r.name]&&void 0===e?.[r.name]&&(e.parameters[r.name]=r.default)}));const[i,n]=await F([e.fragment,e.parameters],r),o=b(s?.fragments?.[i],s.fragments,p,!s.noShorthand);if(void 0===o)return A({fallback:await $(y,r),error:`Fragment not defined: ${i}`,expression:u,returnErrorAsString:g});if(!t(o))return c(o,r);u={...e,...o,...n},delete u.fragment}const v=u,T=i(v.operator,o);if(!T)return A({fallback:await $(y,r),error:`Invalid operator: ${v.operator}`,expression:u,returnErrorAsString:g});if(!r.operators[T])return A({fallback:await $(y,r),error:`Excluded operator: ${v.operator}`,expression:u,returnErrorAsString:g});const{propertyAliases:w,evaluate:C,parseChildren:E}=n[T];let S=((e,r)=>l(r,(r=>r in e?e[r]:r)))(w,v);const q=await H(S,r);m||Object.entries(q).forEach((([e,t])=>r.resolvedAliasNodes[e]=t));const O=m?{...r,resolvedAliasNodes:{...r.resolvedAliasNodes,...q}}:r;if("children"in S){if(Array.isArray(S.children)||(S.children=await $(S.children,O)),!Array.isArray(S.children))return A({fallback:await $(y,r),operator:T,name:"Type Error",error:'- Property "children" is not of type: array',expression:u,returnErrorAsString:g});try{S=E(S,O),delete S.children}catch(e){return A({fallback:await $(S.fallback,r),operator:T,error:e,expression:S,returnErrorAsString:g})}}let N;try{N=await C(S,O)}catch(e){return A({fallback:await $(S.fallback,r),operator:T,error:e,expression:S,returnErrorAsString:g})}const j=S?.outputType??S?.type;if(!j)return N;const P=await $(j,r);return P in d?d[P](N):A({fallback:await $(y,r),operator:T,error:`- Invalid output type: ${P}`,expression:S,returnErrorAsString:g})},F=async(e,r)=>Array.isArray(e)?await Promise.all(e.map((e=>$(e,r)))):await $(e,r),H=async(e,r)=>{const t=Object.keys(e).filter(u);if(0===t.length)return{};const a=[];t.forEach((t=>a.push($(e[t],r))));const s=await Promise.all(a),i=k(t,await Promise.all(a));for(const[e,r]of s.entries())"string"==typeof r&&u(r)&&(i[t[e]]=i?.[r]??r);return i},M=async(e,r)=>{const t=Object.keys(r.options?.functions??{}),a=b(e,r.options?.fragments,t);if(!f(a))return e;const s=[],i=[];Object.entries(a).forEach((([e,t])=>{u(e)&&(i.push(e,$(t,r)),delete a[e])}));const n=await Promise.all(i);r.resolvedAliasNodes={...r.resolvedAliasNodes,...I(n)},Object.entries(a).forEach((([e,t])=>{s.push(e,$(t,r))}));const o=await Promise.all(s);return c(I(o),r)},G=[{name:"values",description:"Returns true if all values are true",aliases:[],required:!0,type:"array",default:[!0,!0]}],B=x(G),z={description:"Logical AND",aliases:["and","&","&&"],parameters:G},W=e=>{const r=e.children;return{...e,values:r}},J={propertyAliases:B,operatorData:z,evaluate:async(e,r)=>{const t=await F(e.values,r);return r.typeChecker(L(z.parameters,{values:t})),t.reduce(((e,r)=>e&&!!r),!0)},parseChildren:W},V=[{name:"values",description:"Returns true if any values are true",aliases:[],required:!0,type:"array",default:[!0,!1]}],Y=x(V),X={description:"Logical OR",aliases:["or","|","||"],parameters:V},Z={propertyAliases:Y,operatorData:X,evaluate:async(e,r)=>{const t=await F(e.values,r);return r.typeChecker(L(X.parameters,{values:t})),t.reduce(((e,r)=>e||!!r),!1)},parseChildren:W},K=[{name:"values",description:"Array of values to check for equality",aliases:[],required:!0,type:"array",default:["These are equal","These are equal"]},{name:"caseInsensitive",description:"If the values are strings, ignore the case (default: false)",aliases:[],required:!1,type:"boolean",default:!1},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],ee=x(K),re={description:"Test multiple values are equal",aliases:["=","eq","equal","equals"],parameters:K},te={propertyAliases:ee,operatorData:re,evaluate:async(e,t)=>{const[a,s,i]=await F([e.values,e.caseInsensitive,e.nullEqualsUndefined],t);t.typeChecker(L(re.parameters,{values:a,caseInsensitive:s,nullEqualsUndefined:i}));const n=(void 0!==s?s:t.options?.caseInsensitive??!1)&&a.every((e=>"string"==typeof e))?a.map((e=>e.toLowerCase())):a;return!(void 0!==i?i:void 0!==t.options?.nullEqualsUndefined&&t.options.nullEqualsUndefined)||null!==n[0]&&void 0!==n[0]?n.every((e=>r(e,n[0]))):n.every((e=>null==e))},parseChildren:W},ae=[{name:"values",description:"Array of values to check for inequality",aliases:[],required:!0,type:"array",default:["These items","don't match"]},{name:"caseInsensitive",description:"If the values are strings, ignore the case (default: false)",aliases:[],required:!1,type:"boolean",default:!1},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],se=x(ae),ie={description:"Test if any values are different",aliases:["!=","notEqual","!","ne"],parameters:ae},ne={propertyAliases:se,operatorData:ie,evaluate:async(e,t)=>{const[a,s,i]=await F([e.values,e.caseInsensitive,e.nullEqualsUndefined],t);t.typeChecker(L(ie.parameters,{values:a,caseInsensitive:s,nullEqualsUndefined:i}));const n=(void 0!==s?s:t.options?.caseInsensitive??!1)&&a.every((e=>"string"==typeof e))?a.map((e=>e.toLowerCase())):a;return!(void 0!==i?i:void 0!==t.options?.nullEqualsUndefined&&t.options.nullEqualsUndefined)||null!==n[0]&&void 0!==n[0]?n.some((e=>!r(e,n[0]))):n.some((e=>null===e&&void 0===e))},parseChildren:W},oe=[{name:"values",description:"Array of values to check to add together",aliases:[],required:!0,type:"array",default:[1,2,3]},{name:"type",description:"Data type to coerce input values to before addition",aliases:[],required:!1,type:{literal:["string","array","number","boolean","bool"]},default:"string"}],le=x(oe),ue={description:"Add, concatenate or merge multiple values",aliases:["+","plus","add","concat","join","merge"],parameters:oe},ce={propertyAliases:le,operatorData:ue,evaluate:async(e,r)=>{const t=await F(e.values,r);return r.typeChecker(L(ue.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=>f(e)))?t.reduce(((e,r)=>({...e,...r})),{}):t.reduce(((e,r)=>e+r))},parseChildren:W},pe=[{name:"values",description:"Array of values - 2nd element will be subtracted from the first",aliases:[],required:!1,type:"array",default:[10,5]},{name:"from",description:"Numerical value that will be subtracted from",aliases:["subtractFrom"],required:!1,type:"number",default:100},{name:"subtract",description:"Numerical value to subtract",aliases:[],required:!1,type:"number",default:50}],de=x(pe),he={description:"Subtract one numerical value from another",aliases:["-","subtract","minus","takeaway"],parameters:pe},me={propertyAliases:de,operatorData:he,evaluate:async(e,r)=>{const[t,a,s]=await F([e.values,e.from,e.subtract],r);r.typeChecker(L(he.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:W},fe=[{name:"values",description:"Array of values whose product will be calculated",aliases:[],required:!0,type:"array",default:[5,5]}],ye=x(fe),ge={description:"Multiply several numerical values together",aliases:["*","x","multiply","times"],parameters:fe},ve={propertyAliases:ye,operatorData:ge,evaluate:async(e,r)=>{const t=await F(e.values,r);if(r.typeChecker(L(ge.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:W},be=[{name:"values",description:"Array of values - 1st element will be divided by the first",aliases:[],required:!1,type:"array",default:[100,10]},{name:"dividend",description:"The number that will be divided",aliases:["divide"],required:!1,type:"number",default:99},{name:"divisor",description:"The number that dividend will be divided by",aliases:["by","divideBy"],required:!1,type:"number",default:3},{name:"output",description:"Whether to output a quotient, remainder or decimal",aliases:[],required:!1,type:{literal:["quotient","remainder"]},default:"quotient"}],Te=x(be),we={description:"Divide one numerical value by another",aliases:["/","divide","÷"],parameters:be},Ce={propertyAliases:Te,operatorData:we,evaluate:async(e,r)=>{const[t,a,s,i]=await F([e.values,e.dividend,e.divisor,e.output],r);r.typeChecker(L(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:W},Ee=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array",default:[10,9]},{name:"strict",description:"Whether value must be strictly greater than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],Ae=x(Ee),Se={description:"Test if a value is greater than (or equal to) another value",aliases:[">","greaterThan","higher","larger"],parameters:Ee},qe={propertyAliases:Ae,operatorData:Se,evaluate:async(e,r)=>{const[t,a=!0]=await F([e.values,e.strict],r);if(r.typeChecker(L(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:W},Oe=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array",default:[9,10]},{name:"strict",description:"Whether value must be strictly smaller than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],Ne=x(Oe),je={description:"Test if a value is smaller than (or equal to) another value",aliases:["<","lessThan","lower","smaller"],parameters:Oe},Pe={propertyAliases:Ne,operatorData:je,evaluate:async(e,r)=>{const[t,a=!0]=await F([e.values,e.strict],r);if(r.typeChecker(L(je.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:W},xe=[{name:"condition",description:"The expression to check for truthiness",aliases:[],required:!0,type:"any",default:!0},{name:"valueIfTrue",description:"Value to return if condition is true",aliases:["ifTrue"],required:!0,type:"any",default:"The condition is true"},{name:"valueIfFalse",description:"Value to return if condition is false",aliases:["ifFalse","ifNot"],required:!0,type:"any",default:"The condition is false"}],Le=x(xe),ke={description:"Return a value based on a condition",aliases:["?","conditional","ifThen"],parameters:xe},Ie={propertyAliases:Le,operatorData:ke,evaluate:async(e,r)=>{r.typeChecker(L(ke.parameters,{condition:e.condition,valueIfTrue:e.valueIfTrue,valueIfFalse:e.valueIfFalse}));return await $(e.condition,r)?await $(e.valueIfTrue,r):await $(e.valueIfFalse,r)},parseChildren:e=>{const[r,t,a]=e.children;return{...e,condition:r,valueIfTrue:t,valueIfFalse:a}}},Ue=[{name:"testString",description:"The string to test",aliases:["string","value"],required:!0,type:"string",default:"test-this"},{name:"pattern",description:"The regular expression pattern",aliases:["regex","regexp","regExp","re"],required:!0,type:"string",default:"^[a-z]{4}-[a-z]{4}$"}],Re=x(Ue),De={description:"Compare a string against a regex pattern",aliases:["regex","patternMatch","regexp","matchPattern"],parameters:Ue},Qe={propertyAliases:Re,operatorData:De,evaluate:async(e,r)=>{const[t,a]=await F([e.testString,e.pattern],r);r.typeChecker(L(De.parameters,{testString:t,pattern:a}));return new RegExp(a).test(t)},parseChildren:e=>{const[r,t]=e.children;return{...e,testString:r,pattern:t}}},_e=[{name:"property",description:'The path to the required property (e.g. "user.firstName")',aliases:["path","propertyName"],required:!0,type:"string",default:"path.to[0].my.data"},{name:"additionalData",description:"Additional data objects to be considered",aliases:["additional","objects","data","additionalObjects"],required:!1,type:["object","array"],default:{}}],$e=x(_e),Fe={description:"Extract values from data objects",aliases:["getData","dataProperties","data","objectProperties","objProps","getProperty","getObjProp"],parameters:_e},He={propertyAliases:$e,operatorData:Fe,evaluate:async(r,t)=>{const[a,s={}]=await F([r.property,r.additionalData],t);t.typeChecker(L(Fe.parameters,{property:a,additionalData:s}));const i={...t.options?.data??{},...s};return e(i,a)},parseChildren:e=>{const[r,t]=e.children,a={...e,property:r};return void 0!==t&&(a.fallback=t),a}},Me=[{name:"string",description:"A parameterised (%1, %2) string where the parameters are to be replaced",aliases:[],required:!0,type:"string",default:"Hello, %1"},{name:"substitutions",description:"An array of substitution values for the parameterised string",aliases:["replacements","values"],required:!1,type:["array","object"],default:{}},{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",default:!0},{name:"substitutionCharacter",description:'Which character to search for in original string for replacement -- can be "%" or "$" (default: "%")',aliases:["subCharacter","subChar"],required:!1,type:"string",default:"$"},{name:"numberMapping",description:"Rules for mapping number values to text strings, such as pluralisation.",aliases:["numMap","numberMap","pluralisation","pluralization","plurals"],required:!1,type:"object",default:{}}],Ge=x(Me),Be={description:"Replace values in a string using simple parameter substitution",aliases:["stringSubstitution","substitute","stringSub","replace"],parameters:Me},ze={propertyAliases:Ge,operatorData:Be,evaluate:async(e,r)=>{const[t,a={},s=!0,i="%",n={}]=await F([e.string,e.substitutions,e.trimWhiteSpace,e.substitutionCharacter,e.numberMapping],r);if(r.typeChecker(L(Be.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),l=k(Array.from(o),a.map((e=>s?String(e).trim():e)));return t.split(r).map((e=>e in l?l[e]:e)).join("").replace(`\\${e}`,e)}const o=/(?<!\\)({{(?:[A-Za-z0-9_.]|\[[0-9]+\])+}})/g,l=[];for(const e of t.split(o)){if(!/(?<!\\){{(.+)}}/.exec(e)){l.push(e.replace("\\{{","{{"));continue}const t=await We(e,a,n,r);l.push(s?String(t).trim():t)}return l.join("")},parseChildren:e=>{const[r,...t]=e.children;return{...e,string:r,substitutions:t}}},We=async(r,t,a,s)=>{const i=s.options?.data??{},n=r.replace(/{{(.+)}}/,"$1"),o=await $(e(t,n,e(i,n,"")),s);if("number"!=typeof o)return o;if(!(n in a))return o;const l=a[n];if(o in l)return l[o].replace("{}",String(o));const u=Object.keys(a[n]),c=u.find((e=>e.startsWith(">")));if(c){if(o>Number(c.slice(1)))return l?.[c]}const p=u.find((e=>e.startsWith("<")));if(p){if(o<Number(p.slice(1)))return l?.[p]}return l.other?l.other.replace("{}",String(o)):o},Je=[{name:"values",description:"An array to count",aliases:[],required:!0,type:"array",default:[1,2,3,4,5]}],Ve=x(Je),Ye={description:"Count elements in an array",aliases:["count","length"],parameters:Je},Xe={propertyAliases:Ve,operatorData:Ye,evaluate:async(e,r)=>{const t=await F(e.values,r);return r.typeChecker(L(Ye.parameters,{values:t})),t.length},parseChildren:W},Ze=[{name:"value",description:"The string to be split",aliases:["string"],required:!0,type:"string",default:"Alpha, Bravo, Charlie"},{name:"delimiter",description:"The value to split the string on (default is white space)",aliases:["separator"],required:!1,type:"string",default:","},{name:"trimWhiteSpace",description:"Whether to trim white space from around the resulting elements (default: true)",aliases:["trim","trimWhitespace"],required:!1,type:"boolean",default:!0},{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",default:!0}],Ke=x(Ze),er={description:"Split a string into an array",aliases:["split","arraySplit"],parameters:Ze},rr=" ",tr={propertyAliases:Ke,operatorData:er,evaluate:async(e,r)=>{const[t,a,s,i]=await F([e.value,e.delimiter??rr,e.trimWhiteSpace??!0,e.excludeTrailing??!0],r);r.typeChecker(L(er.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=rr]=e.children;return{...e,value:r,delimiter:t}}},ar=[{name:"query",description:"SQL query string, with parameterised replacements (e.g. $1, $2, etc)",aliases:["text"],required:!0,type:"string"},{name:"values",description:"An array/object of values to replace the SQL string parameters, as per SQL connection specifications ",aliases:["replacements"],required:!1,type:["array","object"]},{name:"single",description:"Specify if returning a single record",aliases:["singleRecord"],required:!1,type:"boolean"},{name:"flatten",description:"Specify whether to flatten resulting record objects to arrays of values",aliases:["flat","array"],required:!1,type:"boolean"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],sr=x(ar),ir={description:"Query an SQL database",aliases:["sql","pgSql","postgres","pg","sqLite","sqlite","mySql"],parameters:ar},nr={propertyAliases:sr,operatorData:ir,evaluate:async(e,r)=>{const t=r.options?.sqlConnection;if(!t)throw new Error("No SQL database connection provided");const[a,s,i,n,o,l]=await F([e.query,e.values||[],e.single,e.flatten,e.useCache,e.type],r);r.typeChecker(L(ir.parameters,{query:a,single:i,flatten:n,values:s,useCache:o}));const u=e.useCache??r.options.useCache??!0;{const e=r.cache.useCache(u,(async(e,r,a,s,i)=>{const n=await t.query({query:e,values:r})||[];["array","string","number"].includes(i??"")&&(s=!0);const o=s?n.map((e=>{const r=Object.values(e);return r.length<=1?r[0]:r})):n;return a?o[0]:o}),a,s,i,n,l);return e}},parseChildren:e=>{const[r,...t]=e.children;return{...e,query:r,values:t}}},or=[{name:"query",description:"GraphQL query string",aliases:[],required:!0,type:"string",default:'query getCountries {\n countries(filter: {continent: {eq: "OC"}}) {\n name\n }\n }'},{name:"url",description:"Endpoint for the GraphQL request (if not already provided in options)",aliases:["endpoint"],required:!1,type:["string","null"],default:"https://countries.trevorblades.com/"},{name:"headers",description:"HTTP Headers (if not already provided in options)",aliases:[],required:!1,type:"object",default:{}},{name:"variables",description:"Values for the variables used in query (key-value pairs)",aliases:[],required:!1,type:"object",default:{}},{name:"returnNode",description:"Property path to extract from the query response",aliases:["outputNode","returnProperty"],required:!1,type:"string",default:"data.countries[1].name"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],lr=x(or),ur={description:"GraphQL request",aliases:["graphQL","graphQl","graphql","gql"],parameters:or},cr={propertyAliases:lr,operatorData:ur,evaluate:async(e,r)=>{const t=r.graphQLClient??r.httpClient;if(!t)throw new Error("No HTTP client provided for GraphQL connection");const[a,s,i,n,o,l]=await F([e.query,e.url,await M(e.variables,r),e.returnNode,e.headers,e.useCache],r),{url:u,headers:c}=s instanceof Object?s:{url:s,headers:null};r.typeChecker([...L(ur.parameters,{url:u,query:a,variables:i,returnNode:n,headers:o,useCache:l}),{name:"headers",value:c,expectedType:["object","null"]}]);const p=u&&"graphqlendpoint"!==u.toLowerCase()?u:"",d=r.options.graphQLConnection?.endpoint??r.options.baseEndpoint??"",h=D(p)?p:Q(d,p),m={query:a,variables:i},f=l??r.options.useCache??!0,y=await r.cache.useCache(f,(async(e,r,a,s)=>{const i=await _(t,{url:e,method:"post",data:r,headers:a});return R(i?.data,s)}),h,m,{...r.options.graphQLConnection?.headers,...r.options?.headers,...c,...o},n);return y},parseChildren:e=>{const[r,t="",a,...s]=e.children,i=Array.isArray(a)?a:[a],n=s.slice(0,i.length),o=k(i,n),l={...e,query:r,url:t,variables:o};return s.length>i.length&&(l.returnNode=s.pop()),l}},pr=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string",default:"https://restcountries.com/v3.1/name/zealand"},{name:"returnProperty",description:"Property from request result",aliases:["outputProperty"],required:!1,type:"string",default:"result.path"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object",default:{}},{name:"parameters",description:"Query parameters (key-value)",aliases:["queryParams","queryParameters","urlQueries"],required:!1,type:"object",default:{}},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],dr=x(pr),hr={description:"HTTP GET Request",aliases:["GET","get","api"],parameters:pr},mr=e=>{const[r="",t,...a]=e.children,s=Array.isArray(t)?t:[t],i=a.slice(0,s.length),n=k(s,i),o={...e,url:r,parameters:n};return a.length>s.length&&(o.returnProperty=a.pop()),o},fr=mr,yr={propertyAliases:dr,operatorData:hr,evaluate:async(e,r)=>{const t=r.httpClient;if(!t)throw new Error("No HTTP client provided");const[a,s,i,n,o]=await F([e.url,await M(e.parameters,r),e.returnProperty,await M(e.headers,r),e.useCache],r),{url:l,headers:u}=a instanceof Object?a:{url:a,headers:null};r.typeChecker([...L(hr.parameters,{url:l,returnProperty:i,headers:n,parameters:s,useCache:o}),{name:"headers",value:u,expectedType:["object","null"]}]);const c=r.options.baseEndpoint??"",p={...r.options?.headers,...u,...n},d=o??r.options.useCache??!0,h=await r.cache.useCache(d,(async(e,r,a,s)=>{const i=await _(t,{url:e,params:r,headers:a});return R(i,s)}),D(l)?l:Q(c,l),s,p,i);return h},parseChildren:mr},gr=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string",default:"https://jsonplaceholder.typicode.com/posts"},{name:"returnProperty",description:"Property path from request result",aliases:["outputProperty"],required:!1,type:"string",default:"result.path"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object",default:{}},{name:"parameters",description:"JSON Body parameters (key-value)",aliases:["bodyJson","data"],required:!1,type:"object",default:{}},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],vr=x(gr),br={description:"HTTP POST Request",aliases:["POST","post"],parameters:gr},Tr={propertyAliases:vr,operatorData:br,evaluate:async(e,r)=>{const t=r.httpClient;if(!t)throw new Error("No HTTP client provided");const[a,s,i,n,o]=await F([e.url,await M(e.parameters,r),e.returnProperty,await M(e.headers,r),e.useCache],r),{url:l,headers:u}=a instanceof Object?a:{url:a,headers:null};r.typeChecker([...L(br.parameters,{url:l,headers:n,data:s,returnProperty:i,useCache:o}),{name:"headers",value:u,expectedType:["object","null"]}]);const c=r.options.baseEndpoint??"",p={...r.options?.headers,...u,...n},d=o??r.options.useCache??!1,h=await r.cache.useCache(d,(async(e,r,a,s)=>{const i=await _(t,{url:e,data:r,headers:a,method:"post"});return R(i,s)}),D(l)?l:Q(c,l),s,p,i);return h},parseChildren:fr},wr=[{name:"properties",description:'An array of objects, each with a "key" property and a "value" property',aliases:["values","keyValPairs","keyValuePairs"],required:!0,type:"array",default:["firstKey","firstValue","secondKey","secondValue"]}],Cr=x(wr),Er={description:"Construct an object using objects defining keys and values",aliases:["buildObject","build","object"],parameters:wr},Ar=e=>{const r=e.children;if(r.every((e=>f(e))))return{...e,properties:r};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}},Sr={propertyAliases:Cr,operatorData:Er,evaluate:async(e,r)=>{const t=await F(e.properties,r);r.typeChecker(L(Er.parameters,{properties:t}));const{properties:a}=t.some((e=>!f(e)))?Ar({...e,children:t}):{properties:t},s=a.filter((e=>e instanceof Object&&"key"in e&&"value"in e)).map((({key:e,value:t})=>(async e=>{const[t,a]=await F(e,r);return r.typeChecker({name:"key",value:t,expectedType:["string","number","boolean"]}),[t,a]})([e,t])));return Object.fromEntries(await Promise.all(s))},parseChildren:Ar},qr=[{name:"matchExpression",description:"Expression to match against",aliases:["matchValue"],required:!0,type:["string","number","boolean"],default:"matchMe"},{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"],default:{matchMe:"YES",nonMatch:"NO"}},{name:"[...branches]",description:"Branch properties can optionally be placed at the operator root",aliases:[],required:!1,type:["object","array"]}],Or={propertyAliases:x(qr),operatorData:{description:"Return different values depending on a matching expression",aliases:["match","switch"],parameters:qr},evaluate:async(e,r)=>{const a=await $(e.matchExpression,r);r.typeChecker({name:"matchExpression",value:a,expectedType:["string","number","boolean"]});const s=Array.isArray(e.branches)?I(e.branches):e.branches??{},i=t(s)?await $(s,r):s;if(!f(i))throw new Error("Branches don't evaluate to an object");if(a in i)return await $(i[a],r);if("fallback"in i)return await $(i.fallback,r);if(a in e)return await $(e[a],r);throw new Error(`No match found for ${a}`)},parseChildren:e=>{const[r,...t]=e.children,a=I(t);return{...e,matchExpression:r,branches:a}}},Nr=[{name:"functionName",description:"Path (in options.functions) to the required function",aliases:["functionPath","funcName","function","path","name"],required:!0,type:"string",default:null},{name:"args",description:"Arguments for the function",aliases:["arguments","variables"],required:!1,type:["array","any"],default:[]},{name:"input",description:"Argument for the function if a single input parameter",aliases:["arg"],required:!1,type:"any",default:"input"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!1}],jr=x(Nr),Pr={description:"Call a custom function (defined in options)",aliases:["customFunctions","customFunction","objectFunctions","function","functions","runFunction"],parameters:Nr},xr={propertyAliases:jr,operatorData:Pr,evaluate:async(r,t)=>{const[a,s=[],i,n]=await F([r.functionName,r.args,r.input,r.useCache],t);t.typeChecker(L(Pr.parameters,{functionName:a,args:s}));const{data:o,functions:l}=t.options;if(!l)throw new Error("- No functions defined");const u=e(l,`${a}.function`,null)??e(l,a,null)??e(t.options,`${a}.function`,null)??e(t.options,a,null)??e(o,a,null);if(!u||"function"!=typeof u)throw new Error(`- No function found: "${a}"`);const c=n??t.options.useCache??!1,p=[...void 0===i?[]:[await M(i,t)],...Array.isArray(s)?s:[s]];return await t.cache.useCache(c,(async(e,...r)=>await u(...r)),a,...p)},parseChildren:e=>{const[r,...t]=e.children;return{...e,functionName:r,args:t}}},Lr=[{name:"value",description:"Value to pass through",aliases:["_","data"],required:!0,type:"any",default:null}],kr=x(Lr),Ir={description:"Pass through a value unchanged (or change its type)",aliases:["pass","_","passThru","passthru","ignore","coerce","convert"],parameters:Lr},Ur={propertyAliases:kr,operatorData:Ir,evaluate:async(e,r)=>(r.typeChecker(L(Ir.parameters,{value:e.value})),await $(e.value,r)),parseChildren:e=>{const[...r]=e.children,t=1===r?.length?r[0]:r;return{...e,value:t}}};var Rr=Object.freeze({__proto__:null,AND:J,BUILD_OBJECT:Sr,CONDITIONAL:Ie,COUNT:Xe,CUSTOM_FUNCTIONS:xr,DIVIDE:Ce,EQUAL:te,GET:yr,GRAPHQL:cr,GREATER_THAN:qe,LESS_THAN:Pe,MATCH:Or,MULTIPLY:ve,NOT_EQUAL:ne,OBJECT_PROPERTIES:He,OR:Z,PASSTHRU:Ur,PLUS:ce,POST:Tr,REGEX:Qe,SPLIT:tr,SQL:nr,STRING_SUBSTITUTION:ze,SUBTRACT:me});class Dr{constructor(e){this.useCache=async(e,r,...t)=>{if(!e)return await r(...t);const a=Qr(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},this.getMax=()=>this.maxSize,this.setMax=e=>{this.maxSize=e,this.resizeCache()},this.getMaxTime=()=>this.maxTime,this.setMaxTime=e=>{this.maxTime=e},this.getCache=()=>this.store,this.setCache=e=>this.store=e,this.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)}},this.store={},this.queue=[],this.maxSize=e?.maxSize??50,this.maxTime=e?.maxTime??1800}}const Qr=e=>e.map((e=>"object"==typeof e?JSON.stringify(e):e)).join("_"),_r=e=>e||("undefined"!=typeof window&&"document"in window&&"fetch"in window?Fr(window.fetch):void 0),$r=e=>({get:async r=>(await e({...r,method:"get"})).data,post:async r=>(await e({...r,method:"post"})).data,throwError:r=>{if(e.isAxiosError(r)&&r.response)throw r.errorData={status:r.response?.status,error:r.response?.statusText,url:r.config?.url,response:r.response?.data},r;throw new Error("Network error: "+r?.message)}}),Fr=e=>({get:async r=>{const{url:t,headers:a,params:s={}}=r,i=Object.keys(s).length>0?`?${new URLSearchParams(s).toString()}`:"",n=await e(t+i,{headers:a,method:"GET"}),o=await n.json();if(!n.ok){const e=new Error("Problem with GET request");throw e.name="FetchError",e.errorData={status:n.status,error:n.statusText,url:n.url,response:o},console.log(e.errorData),e}return o},post:async r=>{const{url:t,headers:a,params:s,data:i}=r,n=new URLSearchParams(s),o=n.size>0?`?${n.toString()}`:"",l=await e(t+o,{headers:a,body:JSON.stringify(i),method:"POST"}),u=await l.json();if(!l.ok){const e=new Error("Problem with POST request");throw e.name="FetchError",e.errorData={status:l.status,error:l.statusText,url:l.url,response:u},console.log(e.errorData),e}return u},throwError:e=>{throw e}});class Hr{constructor(e={}){this.typeChecker=(...e)=>{const r=1===e.length&&Array.isArray(e[0])?e[0]:e,t=O(...r);if(!0===t)return;const a=new Error(t);throw a.name="Type Error",a},this.getCache=()=>this.cache.getCache(),this.setCache=e=>this.cache.setCache(e),this.getVersion=()=>"2.22.1",this.options=Gr(e),this.operators=n(Rr,this.options?.excludeOperators??[],g),this.operatorAliases=g,this.cache=new Dr({maxSize:e.maxCacheSize,maxTime:e.maxCacheTime}),this.graphQLClient=_r(e.graphQLConnection?.httpClient),this.httpClient=_r(e.httpClient)}async evaluate(e,r={}){const t=p(this.options,Gr(r),!0);return r.httpClient&&(this.httpClient=_r(r.httpClient)),r.graphQLConnection?.httpClient&&(this.graphQLClient=_r(r.graphQLConnection.httpClient)),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 $(e,{options:t,operators:r.excludeOperators?n(Rr,r.excludeOperators,g):this.operators,operatorAliases:this.operatorAliases,typeChecker:t.skipRuntimeTypeCheck?()=>{}:this.typeChecker,resolvedAliasNodes:{},cache:this.cache,graphQLClient:this.graphQLClient,httpClient:this.httpClient})}getOptions(){return this.options}updateOptions(e){this.options=p(this.options,Gr(e),!1),this.options.excludeOperators&&(this.operators=n(Rr,this.options.excludeOperators,g))}getOperators(){const e=this.options.excludeOperators?n(Rr,this.options.excludeOperators,g):this.operators,r=Object.entries(e).map((([e,r])=>({name:e,...r.operatorData,parseChildren:r.parseChildren}))),t=[...new Set(Object.values(g))];return r.sort(((e,r)=>t.indexOf(e.name)-t.indexOf(r.name)))}getFragments(){return Object.entries(this.options.fragments??{}).map((([e,r])=>({name:e,...r?.metadata})))}getCustomFunctions(){return Object.entries(this.options.functions??{}).map((([e,r])=>{const t="function"==typeof r?r:r?.function,a={name:e,numRequiredArgs:t?.length};if("function"!=typeof r){const{description:e,argsDefault:t,inputDefault:s,textColor:i,backgroundColor:n}=r;return e&&(a.description=e),t&&(a.argsDefault=t),s&&(a.inputDefault=s),i&&(a.textColor=i),n&&(a.backgroundColor=n),a}return a}))}getConfig(){return{options:this.options,operators:this.options.excludeOperators?n(Rr,this.options.excludeOperators,g):this.operators,operatorAliases:this.operatorAliases,typeChecker:this.options.skipRuntimeTypeCheck?()=>{}:this.typeChecker,resolvedAliasNodes:{},cache:this.cache,graphQLClient:this.graphQLClient,httpClient:this.httpClient}}}const Mr=(e,r)=>new Hr(r).evaluate(e),Gr=e=>"objects"in e?{...e,data:e.objects}:e,Br=e=>({query:async({query:r,values:t=[]})=>{const a={text:r,values:t??[]};try{const r=await e.query(a);if(r?.error)throw new Error(r.error);return r.rows}catch(e){throw e.name="Node-Postgres error",e}}}),zr=e=>({query:async({query:r,values:t=[]})=>{try{return await e.all(r,t)}catch(e){throw e.name="SQLite error",e}}}),Wr=(e,r)=>{const t=r.getOperators(),a=e=>{if(!f(e))return e;const i=Jr(e)?(()=>{const{operator:a}=e,i=s(a),n=t.find((e=>e.name===i||e.aliases.includes(i)));if(n){const t=n.parseChildren(e,r.getConfig());delete t.children;const a=n.aliases[0];return t.operator=a,t}throw new Error("Invalid operator: "+a)})():e,n={};for(const[e,r]of Object.entries(i)){const t="type"===e?"outputType":e;Array.isArray(r)?n[t]=r.map((e=>a(e))):n[t]=a(r)}return n};return a(e)},Jr=e=>f(e)&&"operator"in e&&"children"in e&&Array.isArray(e.children),Vr=(e,r,t=2)=>{const a=r.getOperators(),i=r.getFragments(),n=r.getCustomFunctions(),o=r.getOptions().fragments,l=a.map((e=>[e.name,...e.aliases])).flat(),u=i.map((e=>e.name)),c=n.map((e=>e.name)),p=new Set([...l,...u,...c]),d=e=>{if(Array.isArray(e))return e.map((e=>d(e)));if(!f(e))return e;const{operator:i,fragment:n,...l}=e;if(!i&&!n)return Object.fromEntries(Object.entries(e).map((([e,r])=>[e,d(r)])));if(i&&Array.isArray(l.children)){const e=s(i),t=a.find((r=>r.name===e||r.aliases.includes(e)));if(t){const e=t.parseChildren({...l,operator:i},r.getConfig());return delete e.children,d(e)}}const u=c.includes(i);n&&l?.parameters&&(Object.entries(l.parameters).forEach((([e,r])=>{l[e]=r})),delete l.parameters);const h=u?i:et(i,a),m=`$${h??n}`,y=n?rt(n,o):[],g=Object.keys(l).filter((e=>Kr(e,p)&&!y.includes(e))),v=Object.entries(l).filter((([e])=>!g.includes(e)&&!y.includes(e))).map((([e,r])=>[e,d(r)])),b=Object.fromEntries(g.map((e=>[e,d(l[e])]))),T=Object.fromEntries(y.map((e=>[e,d(l[e])])));switch(!0){case Object.keys(T).length>0:return{[m]:T,...b};case u:return 1!==v.length||"input"in l?{[m]:Object.fromEntries(v),...b}:{[m]:v[0][1]};case Xr(i,l,a):return 1===v.length?{[m]:v[0][1]}:{[m]:Object.fromEntries(v),...b};case"match"===h:return{[m]:Object.fromEntries(v),...b};case v.length>t||!!n||v.some((([e])=>"useCache"===e||"outputType"===e))||v.some((e=>Array.isArray(e[1]))):return{[m]:Object.fromEntries(v),...b};case 1===v.length:return{[m]:v[0][1],...b};default:return{[m]:Yr(s(i),v,a),...b}}};return d(e)},Yr=(e,r,t)=>{const a=t.find((r=>r.name===e||r.aliases.includes(e)));if(!a)throw new Error("Invalid operator: "+e);const s=[];switch(a.name){case"OBJECT_PROPERTIES":{if(Zr("additionalData",r,a.parameters))return Object.fromEntries(r);const e=Zr("property",r,a.parameters);if(!e)throw new Error("Missing required property for operator $getData: property");const t=r.find((([e])=>"fallback"===e));return t?[e[1],t[1]]:e[1]}case"GET":case"POST":case"GRAPHQL":return Object.fromEntries(r);default:{const t=new Set;for(const{name:i,aliases:n,required:o}of a.parameters){const a=[i,...n],l=r.find((([e])=>a.includes(e)));if(void 0===l&&o)throw new Error(`Missing required property for operator ${e}: ${i}`);if(void 0===l)break;s.push(l[1]),t.add(l[0])}if(r.some((([e])=>!t.has(e))))return Object.fromEntries(r)}}return s},Xr=(e,r,t)=>{if(!e)return!1;const a=s(e),i=t.find((e=>e.name===a||e.aliases.includes(a)))?.parameters[0];if(!i)return!1;return!!("array"===i.type||Array.isArray(i.type)&&i.type.includes("array"))&&[i.name,...i.aliases].some((e=>e in r))},Zr=(e,r,t)=>{const a=t.find((r=>r.name===e));if(!a)return;const s=[a.name,...a.aliases];return r.find((([e])=>s.includes(e)))},Kr=(e,r)=>u(e)&&!r.has(e),et=(e,r)=>{if(!e)return;const t=r.find((r=>e===r.name||r.aliases.includes(s(e))));return t?.aliases.find((e=>/^[A-Za-z_]{2,}$/.test(e)))},rt=(e,r={})=>{const t=r[e];if(!t)throw new Error("Fragment referenced in expression that is not defined in FigTree: "+e);const a=JSON.stringify(t).match(/"(\$\w+)"/gm);if(!a)return[];const s=new Set;return a.forEach((e=>s.add(e.replace(/"/g,"")))),Array.from(s)},tt=(e,r)=>{const i=r.getOperators(),n=r.getFragments(),o=r.getCustomFunctions(),l=n.map((e=>e.name)),u=o.map((e=>e.name)),c=e=>{if(Array.isArray(e))return e.map((e=>c(e)));if(!f(e))return e;const n=Object.entries(e);if(0===n.length)return e;const o=n[0][0].replace("$",""),d=s(o),h=i.find((e=>e.name===d||e.aliases.includes(d))),m=l.includes(o),y=u.includes(o);if(h){const e=h.aliases[0],s=n[0][1];if(Array.isArray(s)){const t=s.map((e=>c(e))),a=h.parseChildren({operator:e,children:t},r.getConfig());return delete a.children,{...a,...p(n)}}const i=c(s);if(!f(i)||!at(i,h)||t(i)||a(i)){return{operator:e,[h.parameters[0].name]:i}}return{operator:e,...i,...p(n)}}if(m){const r=c(e[n[0][0]]);if(!f(r))throw new Error("Invalid shorthand Fragment");return{fragment:o,...r,...p(n)}}if(y){const e=o,r=n[0][1],s=c(r);if(!f(s)||t(s)||a(s)){return{operator:e,["args"]:s}}return{operator:e,...s,...p(n)}}return Object.fromEntries(n.map((([e,r])=>[e,c(r)])))},p=e=>{const r=e.slice(1);return Object.fromEntries(r.map((([e,r])=>[e,c(r)])))};return c(e)},at=(e,r)=>{const t=r.parameters.map((e=>[e.name,...e.aliases])).flat();return Object.keys(e).some((e=>t.includes(e)))};export{$r as AxiosClient,Fr as FetchClient,C as FigTreeError,Hr as FigTreeEvaluator,Br as SQLNodePostgres,zr as SQLite,tt as convertFromShorthand,Vr as convertToShorthand,Wr as convertV1ToV2,Mr as evaluateExpression,u as isAliasString,E as isFigTreeError,y as isFigTreeExpression,a as isFragmentNode,f as isObject,t as isOperatorNode,Jr as isV1Node,b as preProcessShorthand,s as standardiseOperatorName,o as truncateString};
|
|
1
|
+
import e from"object-property-extractor";import{dequal as r}from"dequal/lite";export{dequal}from"dequal/lite";const t=e=>e instanceof Object&&"operator"in e,a=e=>e instanceof Object&&"fragment"in e,s=e=>{const r=m(e);return r||e},n=(e,r)=>r[s(e)],i=(e,r,t)=>{const a={...e};return r.forEach((e=>{t[s(e)]||console.warn(`Invalid operator exclusion: ${e}`),delete a[t[s(e)]]})),a},o=(e,r=200)=>e.length<r?e:`${e.slice(0,r-2).trim()}...`,l=(e,r)=>{const t=Object.entries(e).map((([e,t])=>[r(e),t]));return Object.fromEntries(t)},u=e=>/^\$.+/.test(e),c=(e,{resolvedAliasNodes:r})=>"string"==typeof e&&u(e)?r?.[e]??e:e,p=(e,r,t)=>{const a={...e,...r};return t?((e.data||r.data)&&(a.data={...e.data,...r.data}),(e.functions||r.functions)&&(a.functions={...e.functions,...r.functions}),(e.fragments||r.fragments)&&(a.fragments={...e.fragments,...r.fragments}),(e.headers||r.headers)&&(a.headers={...e.headers,...r.headers}),a):a},d={number:e=>h(e),string:e=>String(e),array:e=>Array.isArray(e)?e:[e],boolean:e=>Boolean(e),bool:e=>Boolean(e)},h=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},m=e=>e.replace(/[^A-Za-z\d _-]/g,"").split(/[-_ ]/).map((e=>e.match(/[a-z]+|[A-Z]+[a-z]*/g)??e)).flat().filter((e=>""!==e)).map(((e,r)=>0===r?e.toLowerCase():e.charAt(0).toUpperCase()+e.slice(1).toLowerCase())).join(""),f=e=>"object"==typeof e&&null!==e&&!Array.isArray(e),y=e=>t(e)||a(e)||"string"==typeof e&&u(e)||f(e)&&1===Object.keys(e).length&&u(Object.keys(e)[0]),g={and:"AND","&":"AND","&&":"AND",or:"OR","|":"OR","||":"OR","=":"EQUAL",eq:"EQUAL",equal:"EQUAL",equals:"EQUAL","!=":"NOT_EQUAL",notEqual:"NOT_EQUAL","!":"NOT_EQUAL",ne:"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",getData:"OBJECT_PROPERTIES",dataProperties:"OBJECT_PROPERTIES",data:"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",get:"GET",api:"GET",POST:"POST",post:"POST",sql:"SQL",pgSql:"SQL",postgres:"SQL",pg:"SQL",sqLite:"SQL",sqlite:"SQL",mySql:"SQL",graphQL:"GRAPHQL",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",pass:"PASSTHRU",_:"PASSTHRU",passThru:"PASSTHRU",passthru:"PASSTHRU",ignore:"PASSTHRU",coerce:"PASSTHRU",convert:"PASSTHRU"},v=g,b=(e,r={},t,a=!0)=>a&&f(e)?T(e,r,t):e,T=(e,r,s)=>{if(t(e)||a(e))return e;const n=Object.entries(e),i=n.filter((([e])=>u(e))),o=n.filter((([e])=>!u(e)));return{...i.reduce(((e,[t,a])=>e={...e,...w(t,a,r,s)}),{}),...Object.fromEntries(o)}},w=(e,r,t,a)=>{const s=e.slice(1),i=n(s,v);return i?Array.isArray(r)?{operator:i,children:r}:f(r)&&!Object.keys(r).some((e=>u(e)))?{operator:i,...r}:{operator:i,children:[r]}:s in t?{fragment:s,parameters:{...r}}:a.includes(s)?Array.isArray(r)?{operator:s,args:r}:f(r)?"input"in r||"args"in r?{operator:s,...r}:{operator:s,input:r}:{operator:s,args:[r]}:{[e]:r}};class C extends Error{constructor(e,r,t,a){super(e.message),Object.assign(this,e),this.operator=r,this.expression=a,this.errorData=e.errorData,t&&(this.name=t),"Error"===this.name&&(this.name="FigTreeError");const s=(r?"Operator: "+r:"")+("FigTreeError"===this.name?"":` - ${this.name}`),n=this.errorData?"\n"+JSON.stringify(this.errorData,null,2):"";this.prettyPrint=`${""!==s?s+"\n":""}${this.message}${"\n{}"===n?"":n}`}}const E=e=>e instanceof C,A=({fallback:e,operator:r,name:t,error:a,expression:s,returnErrorAsString:n=!1})=>{if(void 0!==e)return e;if(a instanceof C){if(!n)throw a;return a.prettyPrint}const i=new C("string"==typeof a?new Error(a):a,r,t,s);if(n)return i.prettyPrint;throw i},S=e=>f(e)&&"literal"in e,q=({value:e,name:r,expectedType:t})=>{if(S(t)){const{literal:a}=t;return!!a.includes(e)||j(r,e,`Literal(${a.map((e=>void 0===e?"undefined":`"${e}"`)).join(", ")})`)}if(Array.isArray(t))return!!t.some((t=>!0===q({value:e,name:r,expectedType:t})))||j(r,e,t.join("|"));return!!(0,N[t])(e)||j(r,e,t)},O=(...e)=>{const r=[];return e.forEach((e=>{const t=q(e);!0!==t&&r.push(t)})),!(r.length>0)||r.join("\n")},N={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=>f(e),undefined:e=>void 0===e},j=(e,r,t)=>void 0===r&&e?`- Missing required property "${e}" (type: ${t})`:void 0!==e?`- Property "${e}" (value: ${P(r)}) is not of type: ${t}`:`- ${P(r)} is not of type: ${t}`,P=e=>{const r=void 0===e||Number.isNaN(e)?String(e):JSON.stringify(e);return o(r,50)},x=e=>{const r={};return e.forEach((e=>{e.aliases.forEach((t=>r[t]=e.name))})),r},k=(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 n=1===s.length?s[0]:s;return{name:e,value:r[e],expectedType:n}})),L=(e,r)=>{const t=e.map(((e,t)=>[e,r[t]]));return Object.fromEntries(t)},I=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=O(...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},U=e=>f(e)&&1===Object.keys(e).length?Object.values(e)[0]:e,R=(r,t,a=void 0)=>{const s=t?e(r,t,a):r;return Array.isArray(s)?s.map((e=>U(e))):t?null===s?null:U(s):s},D=e=>/^https?:\/\/.+/.test(e),Q=(...e)=>e.reduce(((e,r,t)=>{const a="/"===r[0]?1:0,s="/"===r.slice(-1)?-1:void 0,n=r.slice(a,s);return""===n?e:e+(0===t?"":"/")+n}),""),_=async(e,r)=>{const{url:t,params:a={},data:s={},headers:n={},method:i="get"}=r;if(!t||""===t)throw new Error("Invalid url");try{return await e[i]({url:t,headers:{"Content-Type":"application/json",Accept:"application/json",...n},params:a,data:s})}catch(r){e.throwError(r)}},F=async(e,r)=>{const{options:s,operators:i,operatorAliases:o}=r;let u=s?.allowJSONStringInput?(e=>{if("string"!=typeof e)return e;try{const r=JSON.parse(e);return t(r)?r:e}catch(r){return e}})(e):e;const p=Object.keys(r.options?.functions??{});u=b(u,r.options?.fragments,p,!s.noShorthand),Array.isArray(u)&&(u=await $(u,r));const h=t(u),m=a(u);if(h&&(u=await(async(e,r)=>{if(!(e.operator in(r.options?.functions??{})))return e;const{operator:t,fallback:a,outputType:s,type:n,useCache:i,input:o,args:l,...u}=e,c={operator:"CUSTOM_FUNCTIONS",function:t};return void 0!==a&&(c.fallback=a),void 0!==s&&(c.outputType=s),void 0!==n&&(c.type=n),void 0!==i&&(c.useCache=i),void 0!==l&&(c.args=l),void 0!==o?c.input=o:Object.keys(u).length>0&&(c.input=u),c})(u,r)),s.evaluateFullObject&&!h&&!m)return c(await M(u,r),r);if(!h&&!m)return s.supportDeprecatedValueNodes&&f(u)&&"value"in u?u.value:c(u,r);const{fallback:y}=u,g=s?.returnErrorAsString??!1;if(m){const e={...u},a=s?.fragments?.[e.fragment]?.metadata?.parameters?.filter((e=>void 0!==e.default));void 0===e.parameters&&(e.parameters={}),a?.forEach((r=>{void 0===e.parameters?.[r.name]&&void 0===e?.[r.name]&&(e.parameters[r.name]=r.default)}));const[n,i]=await $([e.fragment,e.parameters],r),o=b(s?.fragments?.[n],s.fragments,p,!s.noShorthand);if(void 0===o)return A({fallback:await F(y,r),error:`Fragment not defined: ${n}`,expression:u,returnErrorAsString:g});if(!t(o))return c(o,r);u={...e,...o,...i},delete u.fragment}const v=u,T=n(v.operator,o);if(!T)return A({fallback:await F(y,r),error:`Invalid operator: ${v.operator}`,expression:u,returnErrorAsString:g});if(!r.operators[T])return A({fallback:await F(y,r),error:`Excluded operator: ${v.operator}`,expression:u,returnErrorAsString:g});const{propertyAliases:w,evaluate:C,parseChildren:E}=i[T];let S=((e,r)=>l(r,(r=>r in e?e[r]:r)))(w,v);const q=await H(S,r);m||Object.entries(q).forEach((([e,t])=>r.resolvedAliasNodes[e]=t));const O=m?{...r,resolvedAliasNodes:{...r.resolvedAliasNodes,...q}}:r;if("children"in S){if(Array.isArray(S.children)||(S.children=await F(S.children,O)),!Array.isArray(S.children))return A({fallback:await F(y,r),operator:T,name:"Type Error",error:'- Property "children" is not of type: array',expression:u,returnErrorAsString:g});try{S=E(S,O),delete S.children}catch(e){return A({fallback:await F(S.fallback,r),operator:T,error:e,expression:S,returnErrorAsString:g})}}let N;try{N=await C(S,O)}catch(e){return A({fallback:await F(S.fallback,r),operator:T,error:e,expression:S,returnErrorAsString:g})}const j=S?.outputType??S?.type;if(!j)return N;const P=await F(j,r);return P in d?d[P](N):A({fallback:await F(y,r),operator:T,error:`- Invalid output type: ${P}`,expression:S,returnErrorAsString:g})},$=async(e,r)=>Array.isArray(e)?await Promise.all(e.map((e=>F(e,r)))):await F(e,r),H=async(e,r)=>{const t=Object.keys(e).filter(u);if(0===t.length)return{};const a=[];t.forEach((t=>a.push(F(e[t],r))));const s=await Promise.all(a),n=L(t,await Promise.all(a));for(const[e,r]of s.entries())"string"==typeof r&&u(r)&&(n[t[e]]=n?.[r]??r);return n},M=async(e,r)=>{const t=Object.keys(r.options?.functions??{}),a=b(e,r.options?.fragments,t);if(!f(a))return e;const s=[],n=[];Object.entries(a).forEach((([e,t])=>{u(e)&&(n.push(e,F(t,r)),delete a[e])}));const i=await Promise.all(n);r.resolvedAliasNodes={...r.resolvedAliasNodes,...I(i)},Object.entries(a).forEach((([e,t])=>{s.push(e,F(t,r))}));const o=await Promise.all(s);return c(I(o),r)},G=[{name:"values",description:"Returns true if all values are true",aliases:[],required:!0,type:"array",default:[!0,!0]}],B=x(G),z={description:"Logical AND",aliases:["and","&","&&"],parameters:G},W=e=>{const r=e.children;return{...e,values:r}},J={propertyAliases:B,operatorData:z,evaluate:async(e,r)=>{const t=await $(e.values,r);return r.typeChecker(k(z.parameters,{values:t})),t.reduce(((e,r)=>e&&!!r),!0)},parseChildren:W},V=[{name:"values",description:"Returns true if any values are true",aliases:[],required:!0,type:"array",default:[!0,!1]}],Y=x(V),X={description:"Logical OR",aliases:["or","|","||"],parameters:V},Z={propertyAliases:Y,operatorData:X,evaluate:async(e,r)=>{const t=await $(e.values,r);return r.typeChecker(k(X.parameters,{values:t})),t.reduce(((e,r)=>e||!!r),!1)},parseChildren:W},K=[{name:"values",description:"Array of values to check for equality",aliases:[],required:!0,type:"array",default:["These are equal","These are equal"]},{name:"caseInsensitive",description:"If the values are strings, ignore the case (default: false)",aliases:[],required:!1,type:"boolean",default:!1},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],ee=x(K),re={description:"Test multiple values are equal",aliases:["=","eq","equal","equals"],parameters:K},te={propertyAliases:ee,operatorData:re,evaluate:async(e,t)=>{const[a,s,n]=await $([e.values,e.caseInsensitive,e.nullEqualsUndefined],t);t.typeChecker(k(re.parameters,{values:a,caseInsensitive:s,nullEqualsUndefined:n}));const i=(void 0!==s?s:t.options?.caseInsensitive??!1)&&a.every((e=>"string"==typeof e))?a.map((e=>e.toLowerCase())):a;return!(void 0!==n?n:void 0!==t.options?.nullEqualsUndefined&&t.options.nullEqualsUndefined)||null!==i[0]&&void 0!==i[0]?i.every((e=>r(e,i[0]))):i.every((e=>null==e))},parseChildren:W},ae=[{name:"values",description:"Array of values to check for inequality",aliases:[],required:!0,type:"array",default:["These items","don't match"]},{name:"caseInsensitive",description:"If the values are strings, ignore the case (default: false)",aliases:[],required:!1,type:"boolean",default:!1},{name:"nullEqualsUndefined",description:"Whether a null value should be considered equal to an undefined value (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],se=x(ae),ne={description:"Test if any values are different",aliases:["!=","notEqual","!","ne"],parameters:ae},ie={propertyAliases:se,operatorData:ne,evaluate:async(e,t)=>{const[a,s,n]=await $([e.values,e.caseInsensitive,e.nullEqualsUndefined],t);t.typeChecker(k(ne.parameters,{values:a,caseInsensitive:s,nullEqualsUndefined:n}));const i=(void 0!==s?s:t.options?.caseInsensitive??!1)&&a.every((e=>"string"==typeof e))?a.map((e=>e.toLowerCase())):a;return!(void 0!==n?n:void 0!==t.options?.nullEqualsUndefined&&t.options.nullEqualsUndefined)||null!==i[0]&&void 0!==i[0]?i.some((e=>!r(e,i[0]))):i.some((e=>!(null==e)))},parseChildren:W},oe=[{name:"values",description:"Array of values to check to add together",aliases:[],required:!0,type:"array",default:[1,2,3]},{name:"type",description:"Data type to coerce input values to before addition",aliases:[],required:!1,type:{literal:["string","array","number","boolean","bool"]},default:"string"}],le=x(oe),ue={description:"Add, concatenate or merge multiple values",aliases:["+","plus","add","concat","join","merge"],parameters:oe},ce={propertyAliases:le,operatorData:ue,evaluate:async(e,r)=>{const t=await $(e.values,r);return r.typeChecker(k(ue.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=>f(e)))?t.reduce(((e,r)=>({...e,...r})),{}):t.reduce(((e,r)=>e+r))},parseChildren:W},pe=[{name:"values",description:"Array of values - 2nd element will be subtracted from the first",aliases:[],required:!1,type:"array",default:[10,5]},{name:"from",description:"Numerical value that will be subtracted from",aliases:["subtractFrom"],required:!1,type:"number",default:100},{name:"subtract",description:"Numerical value to subtract",aliases:[],required:!1,type:"number",default:50}],de=x(pe),he={description:"Subtract one numerical value from another",aliases:["-","subtract","minus","takeaway"],parameters:pe},me={propertyAliases:de,operatorData:he,evaluate:async(e,r)=>{const[t,a,s]=await $([e.values,e.from,e.subtract],r);r.typeChecker(k(he.parameters,{values:t,from:a,subtract:s}));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");return n[0]-n[1]},parseChildren:W},fe=[{name:"values",description:"Array of values whose product will be calculated",aliases:[],required:!0,type:"array",default:[5,5]}],ye=x(fe),ge={description:"Multiply several numerical values together",aliases:["*","x","multiply","times"],parameters:fe},ve={propertyAliases:ye,operatorData:ge,evaluate:async(e,r)=>{const t=await $(e.values,r);if(r.typeChecker(k(ge.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:W},be=[{name:"values",description:"Array of values - 1st element will be divided by the second",aliases:[],required:!1,type:"array",default:[100,10]},{name:"dividend",description:"The number that will be divided",aliases:["divide"],required:!1,type:"number",default:99},{name:"divisor",description:"The number that dividend will be divided by",aliases:["by","divideBy"],required:!1,type:"number",default:3},{name:"output",description:"Whether to output a quotient, remainder or decimal",aliases:[],required:!1,type:{literal:["quotient","remainder","decimal"]},default:"decimal"}],Te=x(be),we={description:"Divide one numerical value by another",aliases:["/","divide","÷"],parameters:be},Ce={propertyAliases:Te,operatorData:we,evaluate:async(e,r)=>{const[t,a,s,n]=await $([e.values,e.dividend,e.divisor,e.output],r);r.typeChecker(k(we.parameters,{values:t,dividend:a,divisor:s,output:n}));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");if(0===i[1])throw new Error("Division by zero!");switch(n){case"quotient":return Math.floor(i[0]/i[1]);case"remainder":return i[0]%i[1];default:return i[0]/i[1]}},parseChildren:W},Ee=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array",default:[10,9]},{name:"strict",description:"Whether value must be strictly greater than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],Ae=x(Ee),Se={description:"Test if a value is greater than (or equal to) another value",aliases:[">","greaterThan","higher","larger"],parameters:Ee},qe={propertyAliases:Ae,operatorData:Se,evaluate:async(e,r)=>{const[t,a=!0]=await $([e.values,e.strict],r);if(r.typeChecker(k(Se.parameters,{values:t,strict:a})),t.length<2)throw new Error("- Not enough values provided");const[s,n]=t;return s===n&&!a||s>n},parseChildren:W},Oe=[{name:"values",description:"Array of values - 1st element will be compared to the second",aliases:[],required:!0,type:"array",default:[9,10]},{name:"strict",description:"Whether value must be strictly smaller than (i.e. not equal) (default: false)",aliases:[],required:!1,type:"boolean",default:!1}],Ne=x(Oe),je={description:"Test if a value is smaller than (or equal to) another value",aliases:["<","lessThan","lower","smaller"],parameters:Oe},Pe={propertyAliases:Ne,operatorData:je,evaluate:async(e,r)=>{const[t,a=!0]=await $([e.values,e.strict],r);if(r.typeChecker(k(je.parameters,{values:t,strict:a})),t.length<2)throw new Error("- Not enough values provided");const[s,n]=t;return s===n&&!a||s<n},parseChildren:W},xe=[{name:"condition",description:"The expression to check for truthiness",aliases:[],required:!0,type:"any",default:!0},{name:"valueIfTrue",description:"Value to return if condition is true",aliases:["ifTrue"],required:!0,type:"any",default:"The condition is true"},{name:"valueIfFalse",description:"Value to return if condition is false",aliases:["ifFalse","ifNot"],required:!0,type:"any",default:"The condition is false"}],ke=x(xe),Le={description:"Return a value based on a condition",aliases:["?","conditional","ifThen"],parameters:xe},Ie={propertyAliases:ke,operatorData:Le,evaluate:async(e,r)=>{r.typeChecker(k(Le.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}}},Ue=[{name:"testString",description:"The string to test",aliases:["string","value"],required:!0,type:"string",default:"test-this"},{name:"pattern",description:"The regular expression pattern",aliases:["regex","regexp","regExp","re"],required:!0,type:"string",default:"^[a-z]{4}-[a-z]{4}$"}],Re=x(Ue),De={description:"Compare a string against a regex pattern",aliases:["regex","patternMatch","regexp","matchPattern"],parameters:Ue},Qe={propertyAliases:Re,operatorData:De,evaluate:async(e,r)=>{const[t,a]=await $([e.testString,e.pattern],r);r.typeChecker(k(De.parameters,{testString:t,pattern:a}));return new RegExp(a).test(t)},parseChildren:e=>{const[r,t]=e.children;return{...e,testString:r,pattern:t}}},_e=[{name:"property",description:'The path to the required property (e.g. "user.firstName")',aliases:["path","propertyName"],required:!0,type:"string",default:"path.to[0].my.data"},{name:"additionalData",description:"Additional data objects to be considered",aliases:["additional","objects","data","additionalObjects"],required:!1,type:["object","array"],default:{}}],Fe=x(_e),$e={description:"Extract values from data objects",aliases:["getData","dataProperties","data","objectProperties","objProps","getProperty","getObjProp"],parameters:_e},He={propertyAliases:Fe,operatorData:$e,evaluate:async(r,t)=>{const[a,s={}]=await $([r.property,r.additionalData],t);t.typeChecker(k($e.parameters,{property:a,additionalData:s}));const n={...t.options?.data??{},...s};return e(n,a)},parseChildren:e=>{const[r,t]=e.children,a={...e,property:r};return void 0!==t&&(a.fallback=t),a}},Me=[{name:"string",description:"A parameterised (%1, %2) string where the parameters are to be replaced",aliases:[],required:!0,type:"string",default:"Hello, %1"},{name:"substitutions",description:"An array of substitution values for the parameterised string",aliases:["replacements","values"],required:!1,type:["array","object"],default:{}},{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",default:!0},{name:"substitutionCharacter",description:'Which character to search for in original string for replacement -- can be "%" or "$" (default: "%")',aliases:["subCharacter","subChar"],required:!1,type:"string",default:"$"},{name:"numberMapping",description:"Rules for mapping number values to text strings, such as pluralisation.",aliases:["numMap","numberMap","pluralisation","pluralization","plurals"],required:!1,type:"object",default:{}}],Ge=x(Me),Be={description:"Replace values in a string using simple parameter substitution",aliases:["stringSubstitution","substitute","stringSub","replace"],parameters:Me},ze={propertyAliases:Ge,operatorData:Be,evaluate:async(e,r)=>{const[t,a={},s=!0,n="%",i={}]=await $([e.string,e.substitutions,e.trimWhiteSpace,e.substitutionCharacter,e.numberMapping],r);if(r.typeChecker(k(Be.parameters,{string:t,substitutions:a,trimWhiteSpace:s,substitutionCharacter:n,numberMapping:i})),Array.isArray(a)){const e="$"===n?"$":"%",r=new RegExp(`(?<!\\\\)(${"%"===e?"%":"\\$"}[\\d]+)`,"g"),i=(t.match(r)||[]).sort(((e,r)=>Number(e.slice(1))-Number(r.slice(1)))),o=new Set(i),l=L(Array.from(o),a.map((e=>s?String(e).trim():e)));return t.split(r).map((e=>e in l?l[e]:e)).join("").replace(new RegExp(`\\\\${"$"===e?"\\$":e}`,"g"),e)}const o=/(?<!\\)({{(?:[A-Za-z0-9_.]|\[[0-9]+\])+}})/g,l=[];for(const e of t.split(o)){if(!/(?<!\\){{(.+)}}/.exec(e)){l.push(e.replace(/\\\{\{/g,"{{"));continue}const t=await We(e,a,i,r);l.push(s?String(t).trim():t)}return l.join("")},parseChildren:e=>{const[r,...t]=e.children;return{...e,string:r,substitutions:t}}},We=async(r,t,a,s)=>{const n=s.options?.data??{},i=r.replace(/{{(.+)}}/,"$1"),o=await F(e(t,i,e(n,i,"")),s);if("number"!=typeof o)return o;if(!(i in a))return o;const l=a[i];if(o in l)return l[o].replace("{}",String(o));const u=Object.keys(a[i]),c=u.find((e=>e.startsWith(">")));if(c){if(o>Number(c.slice(1)))return l?.[c]}const p=u.find((e=>e.startsWith("<")));if(p){if(o<Number(p.slice(1)))return l?.[p]}return l.other?l.other.replace("{}",String(o)):o},Je=[{name:"values",description:"An array to count",aliases:[],required:!0,type:"array",default:[1,2,3,4,5]}],Ve=x(Je),Ye={description:"Count elements in an array",aliases:["count","length"],parameters:Je},Xe={propertyAliases:Ve,operatorData:Ye,evaluate:async(e,r)=>{const t=await $(e.values,r);return r.typeChecker(k(Ye.parameters,{values:t})),t.length},parseChildren:W},Ze=[{name:"value",description:"The string to be split",aliases:["string"],required:!0,type:"string",default:"Alpha, Bravo, Charlie"},{name:"delimiter",description:"The value to split the string on (default is white space)",aliases:["separator"],required:!1,type:"string",default:","},{name:"trimWhiteSpace",description:"Whether to trim white space from around the resulting elements (default: true)",aliases:["trim","trimWhitespace"],required:!1,type:"boolean",default:!0},{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",default:!0}],Ke=x(Ze),er={description:"Split a string into an array",aliases:["split","arraySplit"],parameters:Ze},rr=" ",tr={propertyAliases:Ke,operatorData:er,evaluate:async(e,r)=>{const[t,a,s,n]=await $([e.value,e.delimiter??rr,e.trimWhiteSpace??!0,e.excludeTrailing??!0],r);r.typeChecker(k(er.parameters,{value:t,delimiter:a,trimWhiteSpace:s,excludeTrailing:n}));let i=t.split((e=>e.replace(/\\n/g,"\n").replace(/\\t/g,"\t").replace(/\\r/g,"\r"))(a));return s&&(i=i.map((e=>e.trim()))),n&&""===i[i.length-1]&&i.pop(),i},parseChildren:e=>{const[r,t=rr]=e.children;return{...e,value:r,delimiter:t}}},ar=[{name:"query",description:"SQL query string, with parameterised replacements (e.g. $1, $2, etc)",aliases:["text"],required:!0,type:"string"},{name:"values",description:"An array/object of values to replace the SQL string parameters, as per SQL connection specifications ",aliases:["replacements"],required:!1,type:["array","object"]},{name:"single",description:"Specify if returning a single record",aliases:["singleRecord"],required:!1,type:"boolean"},{name:"flatten",description:"Specify whether to flatten resulting record objects to arrays of values",aliases:["flat","array"],required:!1,type:"boolean"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean"}],sr=x(ar),nr={description:"Query an SQL database",aliases:["sql","pgSql","postgres","pg","sqLite","sqlite","mySql"],parameters:ar},ir={propertyAliases:sr,operatorData:nr,evaluate:async(e,r)=>{const t=r.options?.sqlConnection;if(!t)throw new Error("No SQL database connection provided");const[a,s,n,i,o,l]=await $([e.query,e.values||[],e.single,e.flatten,e.useCache,e.type],r);r.typeChecker(k(nr.parameters,{query:a,single:n,flatten:i,values:s,useCache:o}));const u=e.useCache??r.options.useCache??!0;{const e=r.cache.useCache(u,(async(e,r,a,s,n)=>{const i=await t.query({query:e,values:r})||[];["array","string","number"].includes(n??"")&&(s=!0);const o=s?i.map((e=>{const r=Object.values(e);return r.length<=1?r[0]:r})):i;return a?o[0]:o}),a,s,n,i,l);return e}},parseChildren:e=>{const[r,...t]=e.children;return{...e,query:r,values:t}}},or=[{name:"query",description:"GraphQL query string",aliases:[],required:!0,type:"string",default:'query getCountries {\n countries(filter: {continent: {eq: "OC"}}) {\n name\n }\n }'},{name:"url",description:"Endpoint for the GraphQL request (if not already provided in options)",aliases:["endpoint"],required:!1,type:["string","null"],default:"https://countries.trevorblades.com/"},{name:"headers",description:"HTTP Headers (if not already provided in options)",aliases:[],required:!1,type:"object",default:{}},{name:"variables",description:"Values for the variables used in query (key-value pairs)",aliases:[],required:!1,type:"object",default:{}},{name:"returnNode",description:"Property path to extract from the query response",aliases:["outputNode","returnProperty"],required:!1,type:"string",default:"data.countries[1].name"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],lr=x(or),ur={description:"GraphQL request",aliases:["graphQL","graphQl","graphql","gql"],parameters:or},cr={propertyAliases:lr,operatorData:ur,evaluate:async(e,r)=>{const t=r.graphQLClient??r.httpClient;if(!t)throw new Error("No HTTP client provided for GraphQL connection");const[a,s,n,i,o,l]=await $([e.query,e.url,await M(e.variables,r),e.returnNode,e.headers,e.useCache],r),{url:u,headers:c}=s instanceof Object?s:{url:s,headers:null};r.typeChecker([...k(ur.parameters,{url:u,query:a,variables:n,returnNode:i,headers:o,useCache:l}),{name:"headers",value:c,expectedType:["object","null"]}]);const p=u&&"graphqlendpoint"!==u.toLowerCase()?u:"",d=r.options.graphQLConnection?.endpoint??r.options.baseEndpoint??"",h=D(p)?p:Q(d,p),m={query:a,variables:n},f=l??r.options.useCache??!0,y=await r.cache.useCache(f,(async(e,r,a,s)=>{const n=await _(t,{url:e,method:"post",data:r,headers:a});return R(n?.data,s)}),h,m,{...r.options.graphQLConnection?.headers,...r.options?.headers,...c,...o},i);return y},parseChildren:e=>{const[r,t="",a,...s]=e.children,n=Array.isArray(a)?a:[a],i=s.slice(0,n.length),o=L(n,i),l={...e,query:r,url:t,variables:o};return s.length>n.length&&(l.returnNode=s.pop()),l}},pr=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string",default:"https://restcountries.com/v3.1/name/zealand"},{name:"returnProperty",description:"Property from request result",aliases:["outputProperty"],required:!1,type:"string",default:"result.path"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object",default:{}},{name:"parameters",description:"Query parameters (key-value)",aliases:["queryParams","queryParameters","urlQueries"],required:!1,type:"object",default:{}},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],dr=x(pr),hr={description:"HTTP GET Request",aliases:["GET","get","api"],parameters:pr},mr=e=>{const[r="",t,...a]=e.children,s=Array.isArray(t)?t:[t],n=a.slice(0,s.length),i=L(s,n),o={...e,url:r,parameters:i};return a.length>s.length&&(o.returnProperty=a.pop()),o},fr=mr,yr={propertyAliases:dr,operatorData:hr,evaluate:async(e,r)=>{const t=r.httpClient;if(!t)throw new Error("No HTTP client provided");const[a,s,n,i,o]=await $([e.url,await M(e.parameters,r),e.returnProperty,await M(e.headers,r),e.useCache],r),{url:l,headers:u}=a instanceof Object?a:{url:a,headers:null};r.typeChecker([...k(hr.parameters,{url:l,returnProperty:n,headers:i,parameters:s,useCache:o}),{name:"headers",value:u,expectedType:["object","null"]}]);const c=r.options.baseEndpoint??"",p={...r.options?.headers,...u,...i},d=o??r.options.useCache??!0,h=await r.cache.useCache(d,(async(e,r,a,s)=>{const n=await _(t,{url:e,params:r,headers:a});return R(n,s)}),D(l)?l:Q(c,l),s,p,n);return h},parseChildren:mr},gr=[{name:"url",description:"Endpoint URL",aliases:["endpoint"],required:!0,type:"string",default:"https://jsonplaceholder.typicode.com/posts"},{name:"returnProperty",description:"Property path from request result",aliases:["outputProperty"],required:!1,type:"string",default:"result.path"},{name:"headers",description:"HTTP Headers",aliases:[],required:!1,type:"object",default:{}},{name:"parameters",description:"JSON Body parameters (key-value)",aliases:["bodyJson","data"],required:!1,type:"object",default:{}},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!0}],vr=x(gr),br={description:"HTTP POST Request",aliases:["POST","post"],parameters:gr},Tr={propertyAliases:vr,operatorData:br,evaluate:async(e,r)=>{const t=r.httpClient;if(!t)throw new Error("No HTTP client provided");const[a,s,n,i,o]=await $([e.url,await M(e.parameters,r),e.returnProperty,await M(e.headers,r),e.useCache],r),{url:l,headers:u}=a instanceof Object?a:{url:a,headers:null};r.typeChecker([...k(br.parameters,{url:l,headers:i,data:s,returnProperty:n,useCache:o}),{name:"headers",value:u,expectedType:["object","null"]}]);const c=r.options.baseEndpoint??"",p={...r.options?.headers,...u,...i},d=o??r.options.useCache??!1,h=await r.cache.useCache(d,(async(e,r,a,s)=>{const n=await _(t,{url:e,data:r,headers:a,method:"post"});return R(n,s)}),D(l)?l:Q(c,l),s,p,n);return h},parseChildren:fr},wr=[{name:"properties",description:'An array of objects, each with a "key" property and a "value" property',aliases:["values","keyValPairs","keyValuePairs"],required:!0,type:"array",default:["firstKey","firstValue","secondKey","secondValue"]}],Cr=x(wr),Er={description:"Construct an object using objects defining keys and values",aliases:["buildObject","build","object"],parameters:wr},Ar=e=>{const r=e.children;if(r.every((e=>f(e))))return{...e,properties:r};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}},Sr={propertyAliases:Cr,operatorData:Er,evaluate:async(e,r)=>{const t=await $(e.properties,r);r.typeChecker(k(Er.parameters,{properties:t}));const{properties:a}=t.some((e=>!f(e)))?Ar({...e,children:t}):{properties:t},s=a.filter((e=>e instanceof Object&&"key"in e&&"value"in e)).map((({key:e,value:t})=>(async e=>{const[t,a]=await $(e,r);return r.typeChecker({name:"key",value:t,expectedType:["string","number","boolean"]}),[t,a]})([e,t])));return Object.fromEntries(await Promise.all(s))},parseChildren:Ar},qr=[{name:"matchExpression",description:"Expression to match against",aliases:["matchValue"],required:!0,type:["string","number","boolean"],default:"matchMe"},{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"],default:{matchMe:"YES",nonMatch:"NO"}},{name:"[...branches]",description:"Branch properties can optionally be placed at the operator root",aliases:[],required:!1,type:["object","array"]}],Or={propertyAliases:x(qr),operatorData:{description:"Return different values depending on a matching expression",aliases:["match","switch"],parameters:qr},evaluate:async(e,r)=>{const a=await F(e.matchExpression,r);r.typeChecker({name:"matchExpression",value:a,expectedType:["string","number","boolean"]});const s=Array.isArray(e.branches)?I(e.branches):e.branches??{},n=t(s)?await F(s,r):s;if(!f(n))throw new Error("Branches don't evaluate to an object");if(a in n)return await F(n[a],r);if("fallback"in n)return await F(n.fallback,r);if(a in e)return await F(e[a],r);throw new Error(`No match found for ${a}`)},parseChildren:e=>{const[r,...t]=e.children,a=I(t);return{...e,matchExpression:r,branches:a}}},Nr=[{name:"functionName",description:"Path (in options.functions) to the required function",aliases:["functionPath","funcName","function","path","name"],required:!0,type:"string",default:null},{name:"args",description:"Arguments for the function",aliases:["arguments","variables"],required:!1,type:["array","any"],default:[]},{name:"input",description:"Argument for the function if a single input parameter",aliases:["arg"],required:!1,type:"any",default:"input"},{name:"useCache",description:"Whether or not the FigTree cache is used",aliases:[],required:!1,type:"boolean",default:!1}],jr=x(Nr),Pr={description:"Call a custom function (defined in options)",aliases:["customFunctions","customFunction","objectFunctions","function","functions","runFunction"],parameters:Nr},xr={propertyAliases:jr,operatorData:Pr,evaluate:async(r,t)=>{const[a,s=[],n,i]=await $([r.functionName,r.args,r.input,r.useCache],t);t.typeChecker(k(Pr.parameters,{functionName:a,args:s}));const{data:o,functions:l}=t.options;if(!l)throw new Error("- No functions defined");const u=e(l,`${a}.function`,null)??e(l,a,null)??e(t.options,`${a}.function`,null)??e(t.options,a,null)??e(o,a,null);if(!u||"function"!=typeof u)throw new Error(`- No function found: "${a}"`);const c=i??t.options.useCache??!1,p=[...void 0===n?[]:[await M(n,t)],...Array.isArray(s)?s:[s]];return await t.cache.useCache(c,(async(e,...r)=>await u(...r)),a,...p)},parseChildren:e=>{const[r,...t]=e.children;return{...e,functionName:r,args:t}}},kr=[{name:"value",description:"Value to pass through",aliases:["_","data"],required:!0,type:"any",default:null}],Lr=x(kr),Ir={description:"Pass through a value unchanged (or change its type)",aliases:["pass","_","passThru","passthru","ignore","coerce","convert"],parameters:kr},Ur={propertyAliases:Lr,operatorData:Ir,evaluate:async(e,r)=>(r.typeChecker(k(Ir.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 Rr=Object.freeze({__proto__:null,AND:J,BUILD_OBJECT:Sr,CONDITIONAL:Ie,COUNT:Xe,CUSTOM_FUNCTIONS:xr,DIVIDE:Ce,EQUAL:te,GET:yr,GRAPHQL:cr,GREATER_THAN:qe,LESS_THAN:Pe,MATCH:Or,MULTIPLY:ve,NOT_EQUAL:ie,OBJECT_PROPERTIES:He,OR:Z,PASSTHRU:Ur,PLUS:ce,POST:Tr,REGEX:Qe,SPLIT:tr,SQL:ir,STRING_SUBSTITUTION:ze,SUBTRACT:me});const Dr=(e,r,s)=>{const{fragments:n,functionNames:i,evaluateFullObject:o,useShorthand:l}=r;if(f(e)){const c=b(e,n,i,l);if(t(c)||a(c))return!0;if(!o)return!1;const p=new Set([...s,...Object.keys(e).filter(u)]);return Object.values(e).some((e=>Dr(e,r,p)))}return Array.isArray(e)?e.some((e=>Dr(e,r,s))):!("string"!=typeof e||!u(e))&&s.has(e)};class Qr{constructor(e){this.useCache=async(e,r,...t)=>{if(!e)return await r(...t);const a=_r(t),s=a in this.store,n=Date.now(),i=s&&n-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=n,i&&(this.store[a].result=await r(...t)),this.store[a].result;const o=await r(...t);return this.store[a]={result:o,timestamp:n},this.queue.unshift(a),this.resizeCache(),o},this.getMax=()=>this.maxSize,this.setMax=e=>{this.maxSize=e,this.resizeCache()},this.getMaxTime=()=>this.maxTime,this.setMaxTime=e=>{this.maxTime=e},this.getCache=()=>this.store,this.setCache=e=>this.store=e,this.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)}},this.store={},this.queue=[],this.maxSize=e?.maxSize??50,this.maxTime=e?.maxTime??1800}}const _r=e=>e.map((e=>"object"==typeof e?JSON.stringify(e):e)).join("_"),Fr=e=>e||("undefined"!=typeof window&&"document"in window&&"fetch"in window?Hr(window.fetch):void 0),$r=e=>({get:async r=>(await e({...r,method:"get"})).data,post:async r=>(await e({...r,method:"post"})).data,throwError:r=>{if(e.isAxiosError(r)&&r.response)throw r.errorData={status:r.response?.status,error:r.response?.statusText,url:r.config?.url,response:r.response?.data},r;throw new Error("Network error: "+r?.message)}}),Hr=e=>({get:async r=>{const{url:t,headers:a,params:s={}}=r,n=Object.keys(s).length>0?`?${new URLSearchParams(s).toString()}`:"",i=await e(t+n,{headers:a,method:"GET"}),o=await i.json();if(!i.ok){const e=new Error("Problem with GET request");throw e.name="FetchError",e.errorData={status:i.status,error:i.statusText,url:i.url,response:o},console.log(e.errorData),e}return o},post:async r=>{const{url:t,headers:a,params:s,data:n}=r,i=new URLSearchParams(s),o=i.size>0?`?${i.toString()}`:"",l=await e(t+o,{headers:a,body:JSON.stringify(n),method:"POST"}),u=await l.json();if(!l.ok){const e=new Error("Problem with POST request");throw e.name="FetchError",e.errorData={status:l.status,error:l.statusText,url:l.url,response:u},console.log(e.errorData),e}return u},throwError:e=>{throw e}});class Mr{constructor(e={}){this.typeChecker=(...e)=>{const r=1===e.length&&Array.isArray(e[0])?e[0]:e,t=O(...r);if(!0===t)return;const a=new Error(t);throw a.name="Type Error",a},this.getCache=()=>this.cache.getCache(),this.setCache=e=>this.cache.setCache(e),this.getVersion=()=>"2.23.1",this.options=Br(e),this.operators=i(Rr,this.options?.excludeOperators??[],g),this.operatorAliases=g,this.cache=new Qr({maxSize:e.maxCacheSize,maxTime:e.maxCacheTime}),this.graphQLClient=Fr(e.graphQLConnection?.httpClient),this.httpClient=Fr(e.httpClient)}async evaluate(e,r={}){const t=p(this.options,Br(r),!0);return r.httpClient&&(this.httpClient=Fr(r.httpClient)),r.graphQLConnection?.httpClient&&(this.graphQLClient=Fr(r.graphQLConnection.httpClient)),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?i(Rr,r.excludeOperators,g):this.operators,operatorAliases:this.operatorAliases,typeChecker:t.skipRuntimeTypeCheck?()=>{}:this.typeChecker,resolvedAliasNodes:{},cache:this.cache,graphQLClient:this.graphQLClient,httpClient:this.httpClient})}isFigTreeExpression(e){return((e,r)=>Dr(e,r,new Set))(e,{fragments:this.options.fragments??{},functionNames:Object.keys(this.options.functions??{}),evaluateFullObject:this.options.evaluateFullObject??!1,useShorthand:!this.options.noShorthand})}getOptions(){return this.options}updateOptions(e){this.options=p(this.options,Br(e),!1),this.options.excludeOperators&&(this.operators=i(Rr,this.options.excludeOperators,g))}getOperators(){const e=this.options.excludeOperators?i(Rr,this.options.excludeOperators,g):this.operators,r=Object.entries(e).map((([e,r])=>({name:e,...r.operatorData,parseChildren:r.parseChildren}))),t=[...new Set(Object.values(g))];return r.sort(((e,r)=>t.indexOf(e.name)-t.indexOf(r.name)))}getFragments(){return Object.entries(this.options.fragments??{}).map((([e,r])=>({name:e,...r?.metadata})))}getCustomFunctions(){return Object.entries(this.options.functions??{}).map((([e,r])=>{const t="function"==typeof r?r:r?.function,a={name:e,numRequiredArgs:t?.length};if("function"!=typeof r){const{description:e,argsDefault:t,inputDefault:s,textColor:n,backgroundColor:i}=r;return e&&(a.description=e),void 0!==t&&(a.argsDefault=t),void 0!==s&&(a.inputDefault=s),n&&(a.textColor=n),i&&(a.backgroundColor=i),a}return a}))}getConfig(){return{options:this.options,operators:this.options.excludeOperators?i(Rr,this.options.excludeOperators,g):this.operators,operatorAliases:this.operatorAliases,typeChecker:this.options.skipRuntimeTypeCheck?()=>{}:this.typeChecker,resolvedAliasNodes:{},cache:this.cache,graphQLClient:this.graphQLClient,httpClient:this.httpClient}}}const Gr=(e,r)=>new Mr(r).evaluate(e),Br=e=>"objects"in e?{...e,data:e.objects}:e,zr=e=>({query:async({query:r,values:t=[]})=>{const a={text:r,values:t??[]};try{const r=await e.query(a);if(r?.error)throw new Error(r.error);return r.rows}catch(e){throw e.name="Node-Postgres error",e}}}),Wr=e=>({query:async({query:r,values:t=[]})=>{try{return await e.all(r,t)}catch(e){throw e.name="SQLite error",e}}}),Jr=(e,r)=>{const t=r.getOperators(),a=e=>{if(!f(e))return e;const n=Vr(e)?(()=>{const{operator:a}=e,n=s(a),i=t.find((e=>e.name===n||e.aliases.includes(n)));if(i){const t=i.parseChildren(e,r.getConfig());delete t.children;const a=i.aliases[0];return t.operator=a,t}throw new Error("Invalid operator: "+a)})():e,i={};for(const[e,r]of Object.entries(n)){const t="type"===e?"outputType":e;Array.isArray(r)?i[t]=r.map((e=>a(e))):i[t]=a(r)}return i};return a(e)},Vr=e=>f(e)&&"operator"in e&&"children"in e&&Array.isArray(e.children),Yr=(e,r,t=2)=>{const a=r.getOperators(),n=r.getFragments(),i=r.getCustomFunctions(),o=r.getOptions().fragments,l=a.map((e=>[e.name,...e.aliases])).flat(),u=n.map((e=>e.name)),c=i.map((e=>e.name)),p=new Set([...l,...u,...c]),d=e=>{if(Array.isArray(e))return e.map((e=>d(e)));if(!f(e))return e;const{operator:n,fragment:i,...l}=e;if(!n&&!i)return Object.fromEntries(Object.entries(e).map((([e,r])=>[e,d(r)])));if(n&&Array.isArray(l.children)){const e=s(n),t=a.find((r=>r.name===e||r.aliases.includes(e)));if(t){const e=t.parseChildren({...l,operator:n},r.getConfig());return delete e.children,d(e)}}const u=c.includes(n);i&&l?.parameters&&(Object.entries(l.parameters).forEach((([e,r])=>{l[e]=r})),delete l.parameters);const h=u?n:rt(n,a),m=`$${h??i}`,y=i?tt(i,o):[],g=Object.keys(l).filter((e=>et(e,p)&&!y.includes(e))),v=Object.entries(l).filter((([e])=>!g.includes(e)&&!y.includes(e))).map((([e,r])=>[e,d(r)])),b=Object.fromEntries(g.map((e=>[e,d(l[e])]))),T=Object.fromEntries(y.map((e=>[e,d(l[e])])));switch(!0){case Object.keys(T).length>0:return{[m]:T,...b};case u:return 1!==v.length||"input"in l?{[m]:Object.fromEntries(v),...b}:{[m]:v[0][1]};case Zr(n,l,a):return 1===v.length?{[m]:v[0][1]}:{[m]:Object.fromEntries(v),...b};case"match"===h:return{[m]:Object.fromEntries(v),...b};case v.length>t||!!i||v.some((([e])=>"useCache"===e||"outputType"===e))||v.some((e=>Array.isArray(e[1]))):return{[m]:Object.fromEntries(v),...b};case 1===v.length:return{[m]:v[0][1],...b};default:return{[m]:Xr(s(n),v,a),...b}}};return d(e)},Xr=(e,r,t)=>{const a=t.find((r=>r.name===e||r.aliases.includes(e)));if(!a)throw new Error("Invalid operator: "+e);const s=[];switch(a.name){case"OBJECT_PROPERTIES":{if(Kr("additionalData",r,a.parameters))return Object.fromEntries(r);const e=Kr("property",r,a.parameters);if(!e)throw new Error("Missing required property for operator $getData: property");const t=r.find((([e])=>"fallback"===e));return t?[e[1],t[1]]:e[1]}case"GET":case"POST":case"GRAPHQL":return Object.fromEntries(r);default:{const t=new Set;for(const{name:n,aliases:i,required:o}of a.parameters){const a=[n,...i],l=r.find((([e])=>a.includes(e)));if(void 0===l&&o)throw new Error(`Missing required property for operator ${e}: ${n}`);if(void 0===l)break;s.push(l[1]),t.add(l[0])}if(r.some((([e])=>!t.has(e))))return Object.fromEntries(r)}}return s},Zr=(e,r,t)=>{if(!e)return!1;const a=s(e),n=t.find((e=>e.name===a||e.aliases.includes(a)))?.parameters[0];if(!n)return!1;return!!("array"===n.type||Array.isArray(n.type)&&n.type.includes("array"))&&[n.name,...n.aliases].some((e=>e in r))},Kr=(e,r,t)=>{const a=t.find((r=>r.name===e));if(!a)return;const s=[a.name,...a.aliases];return r.find((([e])=>s.includes(e)))},et=(e,r)=>u(e)&&!r.has(e),rt=(e,r)=>{if(!e)return;const t=r.find((r=>e===r.name||r.aliases.includes(s(e))));return t?.aliases.find((e=>/^[A-Za-z_]{2,}$/.test(e)))},tt=(e,r={})=>{const t=r[e];if(!t)throw new Error("Fragment referenced in expression that is not defined in FigTree: "+e);const a=JSON.stringify(t).match(/"(\$\w+)"/gm);if(!a)return[];const s=new Set;return a.forEach((e=>s.add(e.replace(/"/g,"")))),Array.from(s)},at=(e,r)=>{const n=r.getOperators(),i=r.getFragments(),o=r.getCustomFunctions(),l=i.map((e=>e.name)),u=o.map((e=>e.name)),c=e=>{if(Array.isArray(e))return e.map((e=>c(e)));if(!f(e))return e;const i=Object.entries(e);if(0===i.length)return e;const o=i[0][0].replace("$",""),d=s(o),h=n.find((e=>e.name===d||e.aliases.includes(d))),m=l.includes(o),y=u.includes(o);if(h){const e=h.aliases[0],s=i[0][1];if(Array.isArray(s)){const t=s.map((e=>c(e))),a=h.parseChildren({operator:e,children:t},r.getConfig());return delete a.children,{...a,...p(i)}}const n=c(s);if(!f(n)||!st(n,h)||t(n)||a(n)){return{operator:e,[h.parameters[0].name]:n}}return{operator:e,...n,...p(i)}}if(m){const r=c(e[i[0][0]]);if(!f(r))throw new Error("Invalid shorthand Fragment");return{fragment:o,...r,...p(i)}}if(y){const e=o,r=i[0][1],s=c(r);if(!f(s)||t(s)||a(s)){return{operator:e,["args"]:s}}return{operator:e,...s,...p(i)}}return Object.fromEntries(i.map((([e,r])=>[e,c(r)])))},p=e=>{const r=e.slice(1);return Object.fromEntries(r.map((([e,r])=>[e,c(r)])))};return c(e)},st=(e,r)=>{const t=r.parameters.map((e=>[e.name,...e.aliases])).flat();return Object.keys(e).some((e=>t.includes(e)))};export{$r as AxiosClient,Hr as FetchClient,C as FigTreeError,Mr as FigTreeEvaluator,zr as SQLNodePostgres,Wr as SQLite,at as convertFromShorthand,Yr as convertToShorthand,Jr as convertV1ToV2,Gr as evaluateExpression,u as isAliasString,E as isFigTreeError,y as isFigTreeExpression,a as isFragmentNode,f as isObject,t as isOperatorNode,Vr as isV1Node,b as preProcessShorthand,s as standardiseOperatorName,o as truncateString};
|