@statedelta-libs/expressions 1.2.1 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +121 -434
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +75 -92
- package/dist/index.d.ts +75 -92
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var omniAst=require('omni-ast');var rn=Object.defineProperty;var sn=(n,e)=>{for(var i in e)rn(n,i,{get:e[i],enumerable:true});};var h=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,A=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,$=n=>n!==null&&typeof n=="object"&&"$fn"in n&&typeof n.$fn=="string",fn=n=>n!==null&&typeof n=="object"&&"$fn"in n&&typeof n.$fn=="string",k=n=>n!==null&&typeof n=="object"&&"$pipe"in n&&Array.isArray(n.$pipe),F=new Set(["eq","neq","gt","gte","lt","lte","in","notIn","contains","notContains","exists","notExists","matches","notMatches","startsWith","endsWith"]),E=n=>n!==null&&typeof n=="object"&&"left"in n&&"op"in n&&F.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),T=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,un=n=>E(n)||T(n),M=n=>{if(n===null)return true;let e=typeof n;if(e==="string"||e==="number"||e==="boolean"||Array.isArray(n))return true;if(e==="object"&&n!==null){let i=n,f="left"in i&&"op"in i&&F.has(i.op);return !("$"in i)&&!("$if"in i)&&!("$fn"in i)&&!("$pipe"in i)&&!f&&!("logic"in i)}return false};var x=new Map;function J(n){let e=[],i=n.length,f=0,o="";for(;f<i;){let s=n[f];if(s===".")o&&(e.push({type:"key",value:o}),o=""),f++;else if(s==="["){o&&(e.push({type:"key",value:o}),o=""),f++;let t=f;for(;f<i&&n[f]!=="]";)f++;let r=n.slice(t,f);if(f++,r==="*")e.push({type:"wildcard",value:"*"});else {let u=parseInt(r,10);e.push({type:"index",value:isNaN(u)?r:u});}}else o+=s,f++;}return o&&e.push({type:"key",value:o}),e}function B(n){return n.includes("[*]")}function O(n){let e=x.get(n);return e||(e=B(n)?ln(n):cn(n),x.set(n,e),e)}function cn(n){if(!n.includes(".")&&!n.includes("["))return o=>o?.[n];let e=J(n),i=e.length;if(i===2){let[o,s]=e,t=o.value,r=s.value;return u=>u?.[t]?.[r]}if(i===3){let[o,s,t]=e,r=o.value,u=s.value,l=t.value;return a=>a?.[r]?.[u]?.[l]}let f=e.map(o=>o.value);return o=>{let s=o;for(let t=0;t<i&&s!=null;t++)s=s[f[t]];return s}}function ln(n){let e=J(n),i=[];for(let f=0;f<e.length;f++)e[f].type==="wildcard"&&i.push(f);return i.length===1?an(e,i[0]):pn(e,i)}function an(n,e){let i=n.slice(0,e).map(t=>t.value),f=n.slice(e+1).map(t=>t.value),o=i.length,s=f.length;if(s===0){if(o===1){let t=i[0];return r=>r?.[t]}return t=>{let r=t;for(let u=0;u<o&&r!=null;u++)r=r[i[u]];return r}}if(s===1){let t=f[0];if(o===1){let r=i[0];return u=>{let l=u?.[r];if(Array.isArray(l))return l.map(a=>a?.[t])}}return r=>{let u=r;for(let l=0;l<o&&u!=null;l++)u=u[i[l]];if(Array.isArray(u))return u.map(l=>l?.[t])}}return t=>{let r=t;for(let u=0;u<o&&r!=null;u++)r=r[i[u]];if(Array.isArray(r))return r.map(u=>{let l=u;for(let a=0;a<s&&l!=null;a++)l=l[f[a]];return l})}}function pn(n,e){let i=[],f=0;for(let s=0;s<e.length;s++){let t=e[s],r=s===e.length-1,u=n.slice(f,t).map(l=>l.value);u.length>0&&i.push({type:"access",keys:u}),i.push({type:r?"map":"flatMap",keys:[]}),f=t+1;}let o=n.slice(f).map(s=>s.value);return s=>{let t=s;for(let r of i){if(t==null)return;if(r.type==="access")for(let u of r.keys){if(t==null)return;t=t[u];}else if(r.type==="flatMap"){if(!Array.isArray(t))return;t=t.flatMap(u=>{let l=u;return Array.isArray(l)?l:[l]});}else if(r.type==="map"){if(!Array.isArray(t))return;o.length>0&&(t=t.map(u=>{let l=u;for(let a of o){if(l==null)return;l=l[a];}return l}));}}return t}}function dn(n,e){return O(e)(n)}function j(n){let e=n.indexOf("[*]");return e===-1?n:n.slice(0,e)}function gn(){x.clear();}function yn(){return x.size}function w(n,e){let i=new Set;return b(n,i,e),Array.from(i)}function b(n,e,i){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let s=0;s<n.length;s++)b(n[s],e,i);return}if(h(n)){e.add(j(n.$));return}if(A(n)){if(typeof n.$if=="string"){let s=n.$if.startsWith("!")?n.$if.slice(1):n.$if;e.add(j(s));}else b(n.$if,e,i);b(n.then,e,i),n.else!==void 0&&b(n.else,e,i);return}if(k(n)){for(let s=0;s<n.$pipe.length;s++)b(n.$pipe[s],e,i);return}if($(n)){if(n.args)for(let s=0;s<n.args.length;s++){let t=n.args[s];typeof t!="function"&&b(t,e,i);}return}if(E(n)){b(n.left,e,i),n.right!==void 0&&b(n.right,e,i);return}if(T(n)){for(let s=0;s<n.conditions.length;s++)b(n.conditions[s],e,i);return}if(i){let s=n,t=Object.keys(s);for(let r=0;r<t.length;r++){let u=t[r];if(u in i){let l=i[u](s);if(typeof l=="object"&&l!==null&&u in l)throw new Error(`Transform "${u}" returned object with same key \u2014 infinite loop`);b(l,e,i);return}}}let f=n,o=Object.keys(f);for(let s=0;s<o.length;s++)b(f[o[s]],e,i);}function mn(n){return w(n).length>0}function hn(n){return w(n).length===0}function En(n){return JSON.stringify(n)}function N(n,e={}){let i=e.scope??{},f=e.accessor,o=e.transforms,s=m(n,i,f,o),t=w(n,o),r=En(n);return {fn:s,deps:t,hash:r}}function m(n,e,i,f){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let o=n.map(s=>m(s,e,i,f));return s=>o.map(t=>t(s))}if(h(n))return Tn(n,i);if(A(n))return bn(n,e,i,f);if(k(n))return Cn(n,e,i,f);if($(n))return An(n,e,i,f);if(E(n))return $n(n,e,i,f);if(T(n))return kn(n,e,i,f);if(f){let o=n,s=Object.keys(o);for(let t=0;t<s.length;t++){let r=s[t];if(r in f){let u=f[r](o);if(typeof u=="object"&&u!==null&&r in u)throw new Error(`Transform "${r}" returned object with same key \u2014 infinite loop`);return m(u,e,i,f)}}}if(M(n)){let o=n,s=Object.keys(o),t=s.map(r=>m(o[r],e,i,f));return r=>{let u={};for(let l=0;l<s.length;l++)u[s[l]]=t[l](r);return u}}return ()=>n}function K(n,e){return e?i=>e(n,i):O(n)}function Tn(n,e){return K(n.$,e)}function bn(n,e,i,f){let o;if(typeof n.$if=="string"){let r=n.$if.startsWith("!")?n.$if.slice(1):n.$if,u=K(r,i);o=n.$if.startsWith("!")?a=>!u(a):a=>!!u(a);}else {let r=m(n.$if,e,i,f);o=u=>!!r(u);}let s=m(n.then,e,i,f),t=n.else!==void 0?m(n.else,e,i,f):()=>{};return r=>o(r)?s(r):t(r)}function Cn(n,e,i,f){let o=n.$pipe;if(o.length===0)return ()=>{};if(o.length===1)return m(o[0],e,i,f);let s=m(o[0],e,i,f),t=o.slice(1).map(u=>m(u,e,i,f)),r=t.length;if(r===1){let[u]=t;return l=>{let a=s(l),p=u(l);return typeof p=="function"?p(a):p}}if(r===2){let[u,l]=t;return a=>{let p=s(a),d=u(a);return p=typeof d=="function"?d(p):d,d=l(a),typeof d=="function"?d(p):d}}if(r===3){let[u,l,a]=t;return p=>{let d=s(p),g=u(p);return d=typeof g=="function"?g(d):g,g=l(p),d=typeof g=="function"?g(d):g,g=a(p),typeof g=="function"?g(d):g}}return u=>{let l=s(u);for(let a=0;a<r;a++){let p=t[a](u);l=typeof p=="function"?p(l):p;}return l}}function An(n,e,i,f){let o=n.$fn,s=n.args;if(s===void 0)return ()=>{let u=e[o];if(!u)throw new Error(`Function not found in scope: ${o}`);return u};let t=s.map(u=>typeof u=="function"?()=>u:m(u,e,i,f)),r=t.length;if(r===0)return u=>{let l=e[o];if(!l)throw new Error(`Function not found in scope: ${o}`);return l()};if(r===1){let[u]=t;return l=>{let a=e[o];if(!a)throw new Error(`Function not found in scope: ${o}`);return a(u(l))}}if(r===2){let[u,l]=t;return a=>{let p=e[o];if(!p)throw new Error(`Function not found in scope: ${o}`);return p(u(a),l(a))}}if(r===3){let[u,l,a]=t;return p=>{let d=e[o];if(!d)throw new Error(`Function not found in scope: ${o}`);return d(u(p),l(p),a(p))}}return u=>{let l=e[o];if(!l)throw new Error(`Function not found in scope: ${o}`);return l(...t.map(a=>a(u)))}}function $n(n,e,i,f){let o=m(n.left,e,i,f),s=n.right!==void 0?m(n.right,e,i,f):()=>{};switch(n.op){case "eq":return t=>o(t)===s(t);case "neq":return t=>o(t)!==s(t);case "gt":return t=>o(t)>s(t);case "gte":return t=>o(t)>=s(t);case "lt":return t=>o(t)<s(t);case "lte":return t=>o(t)<=s(t);case "in":return t=>{let r=s(t);return Array.isArray(r)&&r.includes(o(t))};case "notIn":return t=>{let r=s(t);return !Array.isArray(r)||!r.includes(o(t))};case "contains":return t=>{let r=o(t);return Array.isArray(r)&&r.includes(s(t))};case "notContains":return t=>{let r=o(t);return !Array.isArray(r)||!r.includes(s(t))};case "exists":return t=>o(t)!==void 0;case "notExists":return t=>o(t)===void 0;case "matches":return t=>{let r=o(t),u=s(t);return typeof r!="string"||typeof u!="string"?false:new RegExp(u).test(r)};case "notMatches":return t=>{let r=o(t),u=s(t);return typeof r!="string"||typeof u!="string"?true:!new RegExp(u).test(r)};case "startsWith":return t=>{let r=o(t),u=s(t);return typeof r=="string"&&typeof u=="string"&&r.startsWith(u)};case "endsWith":return t=>{let r=o(t),u=s(t);return typeof r=="string"&&typeof u=="string"&&r.endsWith(u)}}}function kn(n,e,i,f){let o=n.conditions.map(t=>m(t,e,i,f)),s=o.length;if(s===1)return t=>!!o[0](t);if(s===2){let[t,r]=o;return n.logic==="AND"?u=>!!t(u)&&!!r(u):u=>!!t(u)||!!r(u)}if(s===3){let[t,r,u]=o;return n.logic==="AND"?l=>!!t(l)&&!!r(l)&&!!u(l):l=>!!t(l)||!!r(l)||!!u(l)}return n.logic==="AND"?t=>{for(let r=0;r<s;r++)if(!o[r](t))return false;return true}:t=>{for(let r=0;r<s;r++)if(o[r](t))return true;return false}}function Sn(n,e,i={}){return N(n,i).fn(e)}var v=class{constructor(e=1e3){this.cache=new Map,this._maxSize=e;}get(e,i={}){let f=JSON.stringify(e),o=this.cache.get(f);if(o)return this.cache.delete(f),this.cache.set(f,o),o;let s=N(e,i);if(this.cache.size>=this._maxSize){let t=this.cache.keys().next().value;t&&this.cache.delete(t);}return this.cache.set(f,s),s}has(e){return this.cache.has(JSON.stringify(e))}delete(e){return this.cache.delete(JSON.stringify(e))}clear(){this.cache.clear();}get size(){return this.cache.size}get maxSize(){return this._maxSize}set maxSize(e){for(this._maxSize=e;this.cache.size>this._maxSize;){let i=this.cache.keys().next().value;i&&this.cache.delete(i);}}},Y=new v;function wn(n,e={}){return Y.get(n,e)}function z(n,e="root",i={}){let f=[];return S(n,e,f,i),{valid:f.length===0,errors:f}}function S(n,e,i,f){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let t=0;t<n.length;t++)S(n[t],`${e}[${t}]`,i,f);return}if(h(n)){(!n.$||typeof n.$!="string")&&i.push(`${e}: invalid reference, $ must be non-empty string`);return}if(A(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||i.push(`${e}.$if: empty path in string shorthand`):S(n.$if,`${e}.$if`,i,f),S(n.then,`${e}.then`,i,f),n.else!==void 0&&S(n.else,`${e}.else`,i,f);return}if(k(n)){if(!Array.isArray(n.$pipe)){i.push(`${e}.$pipe: must be an array`);return}if(n.$pipe.length===0){i.push(`${e}.$pipe: must have at least one element`);return}for(let t=0;t<n.$pipe.length;t++)S(n.$pipe[t],`${e}.$pipe[${t}]`,i,f);return}if($(n)){if(!n.$fn||typeof n.$fn!="string"){i.push(`${e}: invalid function, $fn must be non-empty string`);return}if(f.scope&&!(n.$fn in f.scope)&&i.push(`${e}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))i.push(`${e}.args: must be an array`);else for(let t=0;t<n.args.length;t++){let r=n.args[t];typeof r!="function"&&S(r,`${e}.args[${t}]`,i,f);}return}if(E(n)){F.has(n.op)||i.push(`${e}: invalid operator "${n.op}"`),S(n.left,`${e}.left`,i,f),n.right!==void 0&&S(n.right,`${e}.right`,i,f);return}if(T(n)){if(n.logic!=="AND"&&n.logic!=="OR"&&i.push(`${e}: invalid logic "${n.logic}", must be "AND" or "OR"`),!Array.isArray(n.conditions)){i.push(`${e}.conditions: must be an array`);return}for(let t=0;t<n.conditions.length;t++)S(n.conditions[t],`${e}.conditions[${t}]`,i,f);return}let o=n,s=Object.keys(o);for(let t=0;t<s.length;t++){let r=s[t];S(o[r],`${e}.${r}`,i,f);}}function Rn(n,e={}){let i=z(n,"root",e);if(!i.valid)throw new Error(`Invalid expression: ${i.errors.join("; ")}`)}function Fn(n,e={}){return z(n,"root",e).valid}var Z={};sn(Z,{$:()=>H,$cond:()=>X,$fn:()=>Q,$if:()=>jn,$pipe:()=>U,cond:()=>vn,fn:()=>On,pipe:()=>Nn,ref:()=>xn});function H(n){return {$:n}}var xn=H;function Q(n,e){return e===void 0||e.length===0?{$fn:n}:{$fn:n,args:e}}var On=Q;function jn(n,e,i){return i===void 0?{$if:n,then:e}:{$if:n,then:e,else:i}}function U(...n){return {$pipe:n}}var Nn=U;function X(n,e,i){return i===void 0?{left:n,op:e}:{left:n,op:e,right:i}}var vn=X;var L="data",nn="scope",Gn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function W(n,e={}){let{dataParam:i=L,scopeParam:f=nn,noPrefixes:o=false,useAccessor:s=false,lexicalPrefix:t,transforms:r}=e;return y(n,i,f,o,s,t,r)}function y(n,e,i,f,o,s,t){if(n===null)return omniAst.builders.literal(null);if(typeof n=="string")return omniAst.builders.literal(n);if(typeof n=="number")return omniAst.builders.literal(n);if(typeof n=="boolean")return omniAst.builders.literal(n);if(Array.isArray(n))return omniAst.builders.arrayExpression(n.map(r=>y(r,e,i,f,o,s,t)));if(h(n))return Wn(n.$,e,f,o,s);if(A(n))return In(n,e,i,f,o,s,t);if(k(n))return zn(n.$pipe,e,i,f,o,s,t);if($(n))return Mn(n,e,i,f,o,s,t);if(E(n))return Ln(n,e,i,f,o,s,t);if(T(n))return Vn(n,e,i,f,o,s,t);if(t&&typeof n=="object"){let r=n,u=Object.keys(r);for(let l=0;l<u.length;l++){let a=u[l];if(a in t){let p=t[a](r);if(typeof p=="object"&&p!==null&&a in p)throw new Error(`Transform "${a}" returned object with same key \u2014 infinite loop`);return y(p,e,i,f,o,s,t)}}}if(typeof n=="object"){let u=Object.entries(n).map(([l,a])=>omniAst.builders.property(omniAst.builders.identifier(l),y(a,e,i,f,o,s,t)));return omniAst.builders.objectExpression(u)}return omniAst.builders.literal(null)}var V="accessor";function _(n,e){return e?n===e||n.startsWith(e+"."):false}function Wn(n,e,i,f,o){return f?_(n,o)?R(n,e,true):omniAst.builders.callExpression(omniAst.builders.identifier(V),[omniAst.builders.literal(n),omniAst.builders.identifier(e)]):n.includes("[*]")?Dn(n,e,i):R(n,e,i)}function R(n,e,i){let f=G(n);if(f.length===0)return i?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(e);let o;if(i){let s=f[0];o=omniAst.builders.identifier(s.value);for(let t=1;t<f.length;t++){let r=f[t];r.type==="key"?o=omniAst.builders.memberExpression(o,omniAst.builders.identifier(r.value),false,true):o=omniAst.builders.memberExpression(o,omniAst.builders.literal(r.value),true,true);}}else {o=omniAst.builders.identifier(e);for(let s of f)s.type==="key"?o=omniAst.builders.memberExpression(o,omniAst.builders.identifier(s.value),false,true):o=omniAst.builders.memberExpression(o,omniAst.builders.literal(s.value),true,true);}return o}function Dn(n,e,i){let f=n.indexOf("[*]"),o=n.slice(0,f),s=n.slice(f+3),t;if(o?t=R(o,e,i):t=i?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(e),!s||s==="")return t;if(s.includes("[*]"))return en(t,s);let r="_i",u=s.startsWith(".")?s.slice(1):s,l=omniAst.builders.identifier(r);if(u){let a=G(u);for(let p of a)p.type==="key"?l=omniAst.builders.memberExpression(l,omniAst.builders.identifier(p.value),false,true):l=omniAst.builders.memberExpression(l,omniAst.builders.literal(p.value),true,true);}return omniAst.builders.callExpression(omniAst.builders.memberExpression(t,omniAst.builders.identifier("map"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(r)],l)])}function en(n,e){let i=e.indexOf("[*]"),f=e.slice(0,i),o=e.slice(i+3),s="_i",t=f.startsWith(".")?f.slice(1):f,r=omniAst.builders.identifier(s);if(t){let l=G(t);for(let a of l)a.type==="key"&&(r=omniAst.builders.memberExpression(r,omniAst.builders.identifier(a.value),false,true));}if(o.includes("[*]")){let l=en(r,o);return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(s)],l)])}let u=o.startsWith(".")?o.slice(1):o;if(u){let l=G(u);for(let a of l)a.type==="key"&&(r=omniAst.builders.memberExpression(r,omniAst.builders.identifier(a.value),false,true));}return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(s)],r)])}function In(n,e,i,f,o,s,t){let r;if(typeof n.$if=="string"){let a=n.$if.startsWith("!"),p=a?n.$if.slice(1):n.$if,d;o?_(p,s)?d=R(p,e,true):d=omniAst.builders.callExpression(omniAst.builders.identifier(V),[omniAst.builders.literal(p),omniAst.builders.identifier(e)]):d=R(p,e,f),r=a?omniAst.builders.unaryExpression("!",d):d;}else r=y(n.$if,e,i,f,o,s,t);let u=y(n.then,e,i,f,o,s,t),l=n.else!==void 0?y(n.else,e,i,f,o,s,t):omniAst.builders.identifier("undefined");return omniAst.builders.conditionalExpression(r,u,l)}function Mn(n,e,i,f,o,s,t){let r=f?omniAst.builders.identifier(n.$fn):omniAst.builders.memberExpression(omniAst.builders.identifier(i),omniAst.builders.identifier(n.$fn),false,false);if(n.args===void 0)return r;let u=n.args.map(l=>typeof l=="function"?omniAst.builders.literal(null):y(l,e,i,f,o,s,t));return omniAst.builders.callExpression(r,u)}function zn(n,e,i,f,o,s,t){if(n.length===0)return omniAst.builders.identifier("undefined");if(n.length===1)return y(n[0],e,i,f,o,s,t);let r=y(n[0],e,i,f,o,s,t);for(let u=1;u<n.length;u++){let l=y(n[u],e,i,f,o,s,t);r=omniAst.builders.callExpression(l,[r]);}return r}function P(n,e,i,f,o,s,t){if(h(n)){let r=n.$;return o?_(r,s)?R(r,e,true):omniAst.builders.callExpression(omniAst.builders.identifier(V),[omniAst.builders.literal(r),omniAst.builders.identifier(e)]):R(r,e,f)}return y(n,e,i,f,o,s,t)}function Ln(n,e,i,f,o,s,t){let r=P(n.left,e,i,f,o,s,t),u=n.right!==void 0?P(n.right,e,i,f,o,s,t):omniAst.builders.literal(null),l=Gn[n.op];if(l)return omniAst.builders.binaryExpression(l,r,u);switch(n.op){case "in":return omniAst.builders.callExpression(omniAst.builders.memberExpression(u,omniAst.builders.identifier("includes")),[r]);case "notIn":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(u,omniAst.builders.identifier("includes")),[r]));case "contains":return omniAst.builders.callExpression(omniAst.builders.memberExpression(r,omniAst.builders.identifier("includes"),false,true),[u]);case "notContains":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(r,omniAst.builders.identifier("includes"),false,true),[u]));case "exists":return omniAst.builders.binaryExpression("!=",r,omniAst.builders.literal(null));case "notExists":return omniAst.builders.binaryExpression("==",r,omniAst.builders.literal(null));case "matches":return omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[u]),omniAst.builders.identifier("test")),[r]);case "notMatches":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[u]),omniAst.builders.identifier("test")),[r]));case "startsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(r,omniAst.builders.identifier("startsWith"),false,true),[u]);case "endsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(r,omniAst.builders.identifier("endsWith"),false,true),[u]);default:return omniAst.builders.binaryExpression("===",r,u)}}function Vn(n,e,i,f,o,s,t){let{logic:r,conditions:u}=n,l=r==="AND"?"&&":"||";if(u.length===0)return omniAst.builders.literal(r==="AND");if(u.length===1)return y(u[0],e,i,f,o,s,t);let a=y(u[0],e,i,f,o,s,t);for(let p=1;p<u.length;p++){let d=y(u[p],e,i,f,o,s,t);a=omniAst.builders.logicalExpression(l,a,d);}return a}function G(n){let e=[],i=n.length,f=0,o="";for(;f<i;){let s=n[f];if(s===".")o&&(e.push({type:"key",value:o}),o=""),f++;else if(s==="["){o&&(e.push({type:"key",value:o}),o=""),f++;let t=f;for(;f<i&&n[f]!=="]";)f++;let r=n.slice(t,f);if(f++,r!=="*"){let u=parseInt(r,10);e.push({type:"index",value:isNaN(u)?r:u});}}else o+=s,f++;}return o&&e.push({type:"key",value:o}),e}function tn(n,e=[L]){return omniAst.builders.arrowFunctionExpression(e.map(i=>omniAst.builders.identifier(i)),n)}function D(n,e){let i=new Set;return C(n,i,e),i}function C(n,e,i){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let o of n)C(o,e,i);return}if(h(n))return;if(A(n)){C(n.$if,e,i),C(n.then,e,i),n.else!==void 0&&C(n.else,e,i);return}if(k(n)){for(let o of n.$pipe)C(o,e,i);return}if($(n)){if(e.add(n.$fn),n.args)for(let o of n.args)typeof o!="function"&&C(o,e,i);return}if(E(n)){n.left!==void 0&&typeof n.left=="object"&&C(n.left,e,i),n.right!==void 0&&typeof n.right=="object"&&C(n.right,e,i);return}if(T(n)){for(let o of n.conditions)C(o,e,i);return}if(i){let o=n,s=Object.keys(o);for(let t=0;t<s.length;t++){let r=s[t];if(r in i){let u=i[r](o);if(typeof u=="object"&&u!==null&&r in u)throw new Error(`Transform "${r}" returned object with same key \u2014 infinite loop`);C(u,e,i);return}}}let f=n;for(let o of Object.keys(f))C(f[o],e,i);}function I(n){let e=new Set;for(let i of n){let f=i.indexOf("."),o=i.indexOf("["),s=i.length;f!==-1&&(s=Math.min(s,f)),o!==-1&&(s=Math.min(s,o));let t=i.slice(0,s);t&&e.add(t);}return e}function qn(n){return JSON.stringify(n)}function Jn(n,e,i,f,o,s){let t=W(n,{noPrefixes:true,useAccessor:f,lexicalPrefix:o,transforms:s}),r=omniAst.generate(t),u="";f?o&&(u=`const{${o}}=data??{};`):e.size>0&&(u=`const{${[...e].join(",")}}=data??{};`);let l=f?new Set([...i,"accessor"]):i,a=l.size>0?`const{${[...l].join(",")}}=scope;`:"";return a?`(function(scope){${a}return function(data){${u}return ${r}}})`:`(function(){return function(data){${u}return ${r}}})`}function q(n,e={}){let{scope:i={},returnCode:f=false,useAccessor:o=false,lexicalPrefix:s,transforms:t}=e,r=w(n,t),u=I(r),l=D(n,t),a=qn(n),p=Jn(n,u,l,o,s,t);if(f)return {code:p,deps:r,hash:a,dataRoots:[...u],scopeFns:[...l]};let d;try{d=new Function(`return ${p}`)()(i);}catch(g){throw new Error(`AST compilation failed. If this is due to CSP, use the standard compile() function instead. Error: ${g instanceof Error?g.message:String(g)}`)}return {fn:d,deps:r,hash:a}}function on(n,e,i={}){let{fn:f}=q(n,i);return f(e)}var Te="1.2.1";exports.ExpressionCache=v;exports.VERSION=Te;exports.assertValid=Rn;exports.builders=Z;exports.cache=Y;exports.cached=wn;exports.clearPathCache=gn;exports.compile=N;exports.compileAST=q;exports.compilePath=O;exports.dslToAST=W;exports.evaluate=Sn;exports.evaluateAST=on;exports.extractDataRoots=I;exports.extractDeps=w;exports.extractScopeFns=D;exports.get=dn;exports.getPathCacheSize=yn;exports.hasDeps=mn;exports.hasWildcard=B;exports.isCondition=E;exports.isConditionExpr=un;exports.isConditionGroup=T;exports.isConditional=A;exports.isFn=$;exports.isLiteral=M;exports.isPipe=k;exports.isPure=hn;exports.isRef=h;exports.isTransformResult=fn;exports.isValid=Fn;exports.normalizePath=j;exports.validate=z;exports.wrapInFunction=tn;
|
|
1
|
+
'use strict';var omniAst=require('omni-ast');var rn=Object.defineProperty;var sn=(n,t)=>{for(var s in t)rn(n,s,{get:t[s],enumerable:true});};var y=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,T=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,b=n=>n!==null&&typeof n=="object"&&"$fn"in n&&typeof n.$fn=="string",C=n=>n!==null&&typeof n=="object"&&"$pipe"in n&&Array.isArray(n.$pipe),x=new Set(["eq","neq","gt","gte","lt","lte","in","notIn","contains","notContains","exists","notExists","matches","notMatches","startsWith","endsWith"]),E=n=>n!==null&&typeof n=="object"&&"left"in n&&"op"in n&&x.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),h=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,fn=n=>E(n)||h(n),I=n=>{if(n===null)return true;let t=typeof n;if(t==="string"||t==="number"||t==="boolean"||Array.isArray(n))return true;if(t==="object"&&n!==null){let s=n,i="left"in s&&"op"in s&&x.has(s.op);return !("$"in s)&&!("$if"in s)&&!("$fn"in s)&&!("$pipe"in s)&&!i&&!("logic"in s)}return false};var R=new Map;function J(n){let t=[],s=n.length,i=0,r="";for(;i<s;){let o=n[i];if(o===".")r&&(t.push({type:"key",value:r}),r=""),i++;else if(o==="["){r&&(t.push({type:"key",value:r}),r=""),i++;let e=i;for(;i<s&&n[i]!=="]";)i++;let f=n.slice(e,i);if(i++,f==="*")t.push({type:"wildcard",value:"*"});else {let l=parseInt(f,10);t.push({type:"index",value:isNaN(l)?f:l});}}else r+=o,i++;}return r&&t.push({type:"key",value:r}),t}function B(n){return n.includes("[*]")}function O(n){let t=R.get(n);return t||(t=B(n)?ln(n):un(n),R.set(n,t),t)}function un(n){if(!n.includes(".")&&!n.includes("["))return r=>r?.[n];let t=J(n),s=t.length;if(s===2){let[r,o]=t,e=r.value,f=o.value;return l=>l?.[e]?.[f]}if(s===3){let[r,o,e]=t,f=r.value,l=o.value,c=e.value;return a=>a?.[f]?.[l]?.[c]}let i=t.map(r=>r.value);return r=>{let o=r;for(let e=0;e<s&&o!=null;e++)o=o[i[e]];return o}}function ln(n){let t=J(n),s=[];for(let i=0;i<t.length;i++)t[i].type==="wildcard"&&s.push(i);return s.length===1?cn(t,s[0]):an(t,s)}function cn(n,t){let s=n.slice(0,t).map(e=>e.value),i=n.slice(t+1).map(e=>e.value),r=s.length,o=i.length;if(o===0){if(r===1){let e=s[0];return f=>f?.[e]}return e=>{let f=e;for(let l=0;l<r&&f!=null;l++)f=f[s[l]];return f}}if(o===1){let e=i[0];if(r===1){let f=s[0];return l=>{let c=l?.[f];if(Array.isArray(c))return c.map(a=>a?.[e])}}return f=>{let l=f;for(let c=0;c<r&&l!=null;c++)l=l[s[c]];if(Array.isArray(l))return l.map(c=>c?.[e])}}return e=>{let f=e;for(let l=0;l<r&&f!=null;l++)f=f[s[l]];if(Array.isArray(f))return f.map(l=>{let c=l;for(let a=0;a<o&&c!=null;a++)c=c[i[a]];return c})}}function an(n,t){let s=[],i=0;for(let o=0;o<t.length;o++){let e=t[o],f=o===t.length-1,l=n.slice(i,e).map(c=>c.value);l.length>0&&s.push({type:"access",keys:l}),s.push({type:f?"map":"flatMap",keys:[]}),i=e+1;}let r=n.slice(i).map(o=>o.value);return o=>{let e=o;for(let f of s){if(e==null)return;if(f.type==="access")for(let l of f.keys){if(e==null)return;e=e[l];}else if(f.type==="flatMap"){if(!Array.isArray(e))return;e=e.flatMap(l=>{let c=l;return Array.isArray(c)?c:[c]});}else if(f.type==="map"){if(!Array.isArray(e))return;r.length>0&&(e=e.map(l=>{let c=l;for(let a of r){if(c==null)return;c=c[a];}return c}));}}return e}}function pn(n,t){return O(t)(n)}function F(n){let t=n.indexOf("[*]");return t===-1?n:n.slice(0,t)}function dn(){R.clear();}function gn(){return R.size}function w(n){let t=new Set;return A(n,t),Array.from(t)}function A(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r=0;r<n.length;r++)A(n[r],t);return}if(y(n)){t.add(F(n.$));return}if(T(n)){if(typeof n.$if=="string"){let r=n.$if.startsWith("!")?n.$if.slice(1):n.$if;t.add(F(r));}else A(n.$if,t);A(n.then,t),n.else!==void 0&&A(n.else,t);return}if(C(n)){for(let r=0;r<n.$pipe.length;r++)A(n.$pipe[r],t);return}if(b(n)){if(n.args)for(let r=0;r<n.args.length;r++)A(n.args[r],t);return}if(E(n)){A(n.left,t),n.right!==void 0&&A(n.right,t);return}if(h(n)){for(let r=0;r<n.conditions.length;r++)A(n.conditions[r],t);return}let s=n,i=Object.keys(s);for(let r=0;r<i.length;r++)A(s[i[r]],t);}function mn(n){return w(n).length>0}function yn(n){return w(n).length===0}function En(n){return JSON.stringify(n)}function N(n,t={}){let s=t.scope??{},i=t.accessor,r=m(n,s,i),o=w(n),e=En(n);return {fn:r,deps:o,hash:e}}function m(n,t,s){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let i=n.map(r=>m(r,t,s));return r=>i.map(o=>o(r))}if(y(n))return hn(n,s);if(T(n))return Tn(n,t,s);if(C(n))return bn(n,t,s);if(b(n))return Cn(n,t,s);if(E(n))return An(n,t,s);if(h(n))return $n(n,t,s);if(I(n)){let i=n,r=Object.keys(i),o=r.map(e=>m(i[e],t,s));return e=>{let f={};for(let l=0;l<r.length;l++)f[r[l]]=o[l](e);return f}}return ()=>n}function K(n,t){return t?s=>t(n,s):O(n)}function hn(n,t){return K(n.$,t)}function Tn(n,t,s){let i;if(typeof n.$if=="string"){let e=n.$if.startsWith("!")?n.$if.slice(1):n.$if,f=K(e,s);i=n.$if.startsWith("!")?c=>!f(c):c=>!!f(c);}else {let e=m(n.$if,t,s);i=f=>!!e(f);}let r=m(n.then,t,s),o=n.else!==void 0?m(n.else,t,s):()=>{};return e=>i(e)?r(e):o(e)}function bn(n,t,s){let i=n.$pipe;if(i.length===0)return ()=>{};if(i.length===1)return m(i[0],t,s);let r=m(i[0],t,s),o=i.slice(1).map(f=>m(f,t,s)),e=o.length;if(e===1){let[f]=o;return l=>{let c=r(l),a=f(l);return typeof a=="function"?a(c):a}}if(e===2){let[f,l]=o;return c=>{let a=r(c),p=f(c);return a=typeof p=="function"?p(a):p,p=l(c),typeof p=="function"?p(a):p}}if(e===3){let[f,l,c]=o;return a=>{let p=r(a),d=f(a);return p=typeof d=="function"?d(p):d,d=l(a),p=typeof d=="function"?d(p):d,d=c(a),typeof d=="function"?d(p):d}}return f=>{let l=r(f);for(let c=0;c<e;c++){let a=o[c](f);l=typeof a=="function"?a(l):a;}return l}}function Cn(n,t,s){let i=n.$fn,r=n.args;if(r===void 0)return ()=>{let f=t[i];if(!f)throw new Error(`Function not found in scope: ${i}`);return f};let o=r.map(f=>m(f,t,s)),e=o.length;if(e===0)return f=>{let l=t[i];if(!l)throw new Error(`Function not found in scope: ${i}`);return l()};if(e===1){let[f]=o;return l=>{let c=t[i];if(!c)throw new Error(`Function not found in scope: ${i}`);return c(f(l))}}if(e===2){let[f,l]=o;return c=>{let a=t[i];if(!a)throw new Error(`Function not found in scope: ${i}`);return a(f(c),l(c))}}if(e===3){let[f,l,c]=o;return a=>{let p=t[i];if(!p)throw new Error(`Function not found in scope: ${i}`);return p(f(a),l(a),c(a))}}return f=>{let l=t[i];if(!l)throw new Error(`Function not found in scope: ${i}`);return l(...o.map(c=>c(f)))}}function An(n,t,s){let i=m(n.left,t,s),r=n.right!==void 0?m(n.right,t,s):()=>{};switch(n.op){case "eq":return o=>i(o)===r(o);case "neq":return o=>i(o)!==r(o);case "gt":return o=>i(o)>r(o);case "gte":return o=>i(o)>=r(o);case "lt":return o=>i(o)<r(o);case "lte":return o=>i(o)<=r(o);case "in":return o=>{let e=r(o);return Array.isArray(e)&&e.includes(i(o))};case "notIn":return o=>{let e=r(o);return !Array.isArray(e)||!e.includes(i(o))};case "contains":return o=>{let e=i(o);return Array.isArray(e)&&e.includes(r(o))};case "notContains":return o=>{let e=i(o);return !Array.isArray(e)||!e.includes(r(o))};case "exists":return o=>i(o)!==void 0;case "notExists":return o=>i(o)===void 0;case "matches":return o=>{let e=i(o),f=r(o);return typeof e!="string"||typeof f!="string"?false:new RegExp(f).test(e)};case "notMatches":return o=>{let e=i(o),f=r(o);return typeof e!="string"||typeof f!="string"?true:!new RegExp(f).test(e)};case "startsWith":return o=>{let e=i(o),f=r(o);return typeof e=="string"&&typeof f=="string"&&e.startsWith(f)};case "endsWith":return o=>{let e=i(o),f=r(o);return typeof e=="string"&&typeof f=="string"&&e.endsWith(f)}}}function $n(n,t,s){let i=n.conditions.map(o=>m(o,t,s)),r=i.length;if(r===1)return o=>!!i[0](o);if(r===2){let[o,e]=i;return n.logic==="AND"?f=>!!o(f)&&!!e(f):f=>!!o(f)||!!e(f)}if(r===3){let[o,e,f]=i;return n.logic==="AND"?l=>!!o(l)&&!!e(l)&&!!f(l):l=>!!o(l)||!!e(l)||!!f(l)}return n.logic==="AND"?o=>{for(let e=0;e<r;e++)if(!i[e](o))return false;return true}:o=>{for(let e=0;e<r;e++)if(i[e](o))return true;return false}}function Sn(n,t,s={}){return N(n,s).fn(t)}var j=class{constructor(t=1e3){this.cache=new Map,this._maxSize=t;}get(t,s={}){let i=JSON.stringify(t),r=this.cache.get(i);if(r)return this.cache.delete(i),this.cache.set(i,r),r;let o=N(t,s);if(this.cache.size>=this._maxSize){let e=this.cache.keys().next().value;e&&this.cache.delete(e);}return this.cache.set(i,o),o}has(t){return this.cache.has(JSON.stringify(t))}delete(t){return this.cache.delete(JSON.stringify(t))}clear(){this.cache.clear();}get size(){return this.cache.size}get maxSize(){return this._maxSize}set maxSize(t){for(this._maxSize=t;this.cache.size>this._maxSize;){let s=this.cache.keys().next().value;s&&this.cache.delete(s);}}},P=new j;function wn(n,t={}){return P.get(n,t)}function M(n,t="root",s={}){let i=[];return $(n,t,i,s),{valid:i.length===0,errors:i}}function $(n,t,s,i){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let e=0;e<n.length;e++)$(n[e],`${t}[${e}]`,s,i);return}if(y(n)){(!n.$||typeof n.$!="string")&&s.push(`${t}: invalid reference, $ must be non-empty string`);return}if(T(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||s.push(`${t}.$if: empty path in string shorthand`):$(n.$if,`${t}.$if`,s,i),$(n.then,`${t}.then`,s,i),n.else!==void 0&&$(n.else,`${t}.else`,s,i);return}if(C(n)){if(!Array.isArray(n.$pipe)){s.push(`${t}.$pipe: must be an array`);return}if(n.$pipe.length===0){s.push(`${t}.$pipe: must have at least one element`);return}for(let e=0;e<n.$pipe.length;e++)$(n.$pipe[e],`${t}.$pipe[${e}]`,s,i);return}if(b(n)){if(!n.$fn||typeof n.$fn!="string"){s.push(`${t}: invalid function, $fn must be non-empty string`);return}if(i.scope&&!(n.$fn in i.scope)&&s.push(`${t}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))s.push(`${t}.args: must be an array`);else for(let e=0;e<n.args.length;e++)$(n.args[e],`${t}.args[${e}]`,s,i);return}if(E(n)){x.has(n.op)||s.push(`${t}: invalid operator "${n.op}"`),$(n.left,`${t}.left`,s,i),n.right!==void 0&&$(n.right,`${t}.right`,s,i);return}if(h(n)){if(n.logic!=="AND"&&n.logic!=="OR"&&s.push(`${t}: invalid logic "${n.logic}", must be "AND" or "OR"`),!Array.isArray(n.conditions)){s.push(`${t}.conditions: must be an array`);return}for(let e=0;e<n.conditions.length;e++)$(n.conditions[e],`${t}.conditions[${e}]`,s,i);return}let r=n,o=Object.keys(r);for(let e=0;e<o.length;e++){let f=o[e];$(r[f],`${t}.${f}`,s,i);}}function kn(n,t={}){let s=M(n,"root",t);if(!s.valid)throw new Error(`Invalid expression: ${s.errors.join("; ")}`)}function xn(n,t={}){return M(n,"root",t).valid}var X={};sn(X,{$:()=>Y,$cond:()=>U,$fn:()=>H,$if:()=>Fn,$pipe:()=>Q,cond:()=>jn,fn:()=>On,pipe:()=>Nn,ref:()=>Rn});function Y(n){return {$:n}}var Rn=Y;function H(n,t){return t===void 0||t.length===0?{$fn:n}:{$fn:n,args:t}}var On=H;function Fn(n,t,s){return s===void 0?{$if:n,then:t}:{$if:n,then:t,else:s}}function Q(...n){return {$pipe:n}}var Nn=Q;function U(n,t,s){return s===void 0?{left:n,op:t}:{left:n,op:t,right:s}}var jn=U;var V="data",nn="scope",vn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function G(n,t={}){let{dataParam:s=V,scopeParam:i=nn,noPrefixes:r=false,useAccessor:o=false,lexicalPrefix:e}=t;return g(n,s,i,r,o,e)}function g(n,t,s,i,r,o){if(n===null)return omniAst.builders.literal(null);if(typeof n=="string")return omniAst.builders.literal(n);if(typeof n=="number")return omniAst.builders.literal(n);if(typeof n=="boolean")return omniAst.builders.literal(n);if(Array.isArray(n))return omniAst.builders.arrayExpression(n.map(e=>g(e,t,s,i,r,o)));if(y(n))return Gn(n.$,t,i,r,o);if(T(n))return Dn(n,t,s,i,r,o);if(C(n))return In(n.$pipe,t,s,i,r,o);if(b(n))return zn(n,t,s,i,r,o);if(E(n))return Mn(n,t,s,i,r,o);if(h(n))return Vn(n,t,s,i,r,o);if(typeof n=="object"){let f=Object.entries(n).map(([l,c])=>omniAst.builders.property(omniAst.builders.identifier(l),g(c,t,s,i,r,o)));return omniAst.builders.objectExpression(f)}return omniAst.builders.literal(null)}var _="accessor";function L(n,t){return t?n===t||n.startsWith(t+"."):false}function Gn(n,t,s,i,r){return i?L(n,r)?k(n,t,true):omniAst.builders.callExpression(omniAst.builders.identifier(_),[omniAst.builders.literal(n),omniAst.builders.identifier(t)]):n.includes("[*]")?Wn(n,t,s):k(n,t,s)}function k(n,t,s){let i=v(n);if(i.length===0)return s?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(t);let r;if(s){let o=i[0];r=omniAst.builders.identifier(o.value);for(let e=1;e<i.length;e++){let f=i[e];f.type==="key"?r=omniAst.builders.memberExpression(r,omniAst.builders.identifier(f.value),false,true):r=omniAst.builders.memberExpression(r,omniAst.builders.literal(f.value),true,true);}}else {r=omniAst.builders.identifier(t);for(let o of i)o.type==="key"?r=omniAst.builders.memberExpression(r,omniAst.builders.identifier(o.value),false,true):r=omniAst.builders.memberExpression(r,omniAst.builders.literal(o.value),true,true);}return r}function Wn(n,t,s){let i=n.indexOf("[*]"),r=n.slice(0,i),o=n.slice(i+3),e;if(r?e=k(r,t,s):e=s?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(t),!o||o==="")return e;if(o.includes("[*]"))return tn(e,o);let f="_i",l=o.startsWith(".")?o.slice(1):o,c=omniAst.builders.identifier(f);if(l){let a=v(l);for(let p of a)p.type==="key"?c=omniAst.builders.memberExpression(c,omniAst.builders.identifier(p.value),false,true):c=omniAst.builders.memberExpression(c,omniAst.builders.literal(p.value),true,true);}return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("map"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(f)],c)])}function tn(n,t){let s=t.indexOf("[*]"),i=t.slice(0,s),r=t.slice(s+3),o="_i",e=i.startsWith(".")?i.slice(1):i,f=omniAst.builders.identifier(o);if(e){let c=v(e);for(let a of c)a.type==="key"&&(f=omniAst.builders.memberExpression(f,omniAst.builders.identifier(a.value),false,true));}if(r.includes("[*]")){let c=tn(f,r);return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(o)],c)])}let l=r.startsWith(".")?r.slice(1):r;if(l){let c=v(l);for(let a of c)a.type==="key"&&(f=omniAst.builders.memberExpression(f,omniAst.builders.identifier(a.value),false,true));}return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(o)],f)])}function Dn(n,t,s,i,r,o){let e;if(typeof n.$if=="string"){let c=n.$if.startsWith("!"),a=c?n.$if.slice(1):n.$if,p;r?L(a,o)?p=k(a,t,true):p=omniAst.builders.callExpression(omniAst.builders.identifier(_),[omniAst.builders.literal(a),omniAst.builders.identifier(t)]):p=k(a,t,i),e=c?omniAst.builders.unaryExpression("!",p):p;}else e=g(n.$if,t,s,i,r,o);let f=g(n.then,t,s,i,r,o),l=n.else!==void 0?g(n.else,t,s,i,r,o):omniAst.builders.identifier("undefined");return omniAst.builders.conditionalExpression(e,f,l)}function zn(n,t,s,i,r,o){let e=i?omniAst.builders.identifier(n.$fn):omniAst.builders.memberExpression(omniAst.builders.identifier(s),omniAst.builders.identifier(n.$fn),false,false);if(n.args===void 0)return e;let f=n.args.map(l=>g(l,t,s,i,r,o));return omniAst.builders.callExpression(e,f)}function In(n,t,s,i,r,o){if(n.length===0)return omniAst.builders.identifier("undefined");if(n.length===1)return g(n[0],t,s,i,r,o);let e=g(n[0],t,s,i,r,o);for(let f=1;f<n.length;f++){let l=g(n[f],t,s,i,r,o);e=omniAst.builders.callExpression(l,[e]);}return e}function Z(n,t,s,i,r,o){if(y(n)){let e=n.$;return r?L(e,o)?k(e,t,true):omniAst.builders.callExpression(omniAst.builders.identifier(_),[omniAst.builders.literal(e),omniAst.builders.identifier(t)]):k(e,t,i)}return g(n,t,s,i,r,o)}function Mn(n,t,s,i,r,o){let e=Z(n.left,t,s,i,r,o),f=n.right!==void 0?Z(n.right,t,s,i,r,o):omniAst.builders.literal(null),l=vn[n.op];if(l)return omniAst.builders.binaryExpression(l,e,f);switch(n.op){case "in":return omniAst.builders.callExpression(omniAst.builders.memberExpression(f,omniAst.builders.identifier("includes")),[e]);case "notIn":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(f,omniAst.builders.identifier("includes")),[e]));case "contains":return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("includes"),false,true),[f]);case "notContains":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("includes"),false,true),[f]));case "exists":return omniAst.builders.binaryExpression("!=",e,omniAst.builders.literal(null));case "notExists":return omniAst.builders.binaryExpression("==",e,omniAst.builders.literal(null));case "matches":return omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[f]),omniAst.builders.identifier("test")),[e]);case "notMatches":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[f]),omniAst.builders.identifier("test")),[e]));case "startsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("startsWith"),false,true),[f]);case "endsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("endsWith"),false,true),[f]);default:return omniAst.builders.binaryExpression("===",e,f)}}function Vn(n,t,s,i,r,o){let{logic:e,conditions:f}=n,l=e==="AND"?"&&":"||";if(f.length===0)return omniAst.builders.literal(e==="AND");if(f.length===1)return g(f[0],t,s,i,r,o);let c=g(f[0],t,s,i,r,o);for(let a=1;a<f.length;a++){let p=g(f[a],t,s,i,r,o);c=omniAst.builders.logicalExpression(l,c,p);}return c}function v(n){let t=[],s=n.length,i=0,r="";for(;i<s;){let o=n[i];if(o===".")r&&(t.push({type:"key",value:r}),r=""),i++;else if(o==="["){r&&(t.push({type:"key",value:r}),r=""),i++;let e=i;for(;i<s&&n[i]!=="]";)i++;let f=n.slice(e,i);if(i++,f!=="*"){let l=parseInt(f,10);t.push({type:"index",value:isNaN(l)?f:l});}}else r+=o,i++;}return r&&t.push({type:"key",value:r}),t}function en(n,t=[V]){return omniAst.builders.arrowFunctionExpression(t.map(s=>omniAst.builders.identifier(s)),n)}function W(n){let t=new Set;return S(n,t),t}function S(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let i of n)S(i,t);return}if(y(n))return;if(T(n)){S(n.$if,t),S(n.then,t),n.else!==void 0&&S(n.else,t);return}if(C(n)){for(let i of n.$pipe)S(i,t);return}if(b(n)){if(t.add(n.$fn),n.args)for(let i of n.args)S(i,t);return}if(E(n)){n.left!==void 0&&typeof n.left=="object"&&S(n.left,t),n.right!==void 0&&typeof n.right=="object"&&S(n.right,t);return}if(h(n)){for(let i of n.conditions)S(i,t);return}let s=n;for(let i of Object.keys(s))S(s[i],t);}function D(n){let t=new Set;for(let s of n){let i=s.indexOf("."),r=s.indexOf("["),o=s.length;i!==-1&&(o=Math.min(o,i)),r!==-1&&(o=Math.min(o,r));let e=s.slice(0,o);e&&t.add(e);}return t}function Ln(n){return JSON.stringify(n)}function qn(n,t,s,i,r){let o=G(n,{noPrefixes:true,useAccessor:i,lexicalPrefix:r}),e=omniAst.generate(o),f="";i?r&&(f=`const{${r}}=data??{};`):t.size>0&&(f=`const{${[...t].join(",")}}=data??{};`);let l=i?new Set([...s,"accessor"]):s,c=l.size>0?`const{${[...l].join(",")}}=scope;`:"";return c?`(function(scope){${c}return function(data){${f}return ${e}}})`:`(function(){return function(data){${f}return ${e}}})`}function q(n,t={}){let{scope:s={},returnCode:i=false,useAccessor:r=false,lexicalPrefix:o}=t,e=w(n),f=D(e),l=W(n),c=Ln(n),a=qn(n,f,l,r,o);if(i)return {code:a,deps:e,hash:c,dataRoots:[...f],scopeFns:[...l]};let p;try{p=new Function(`return ${a}`)()(s);}catch(d){throw new Error(`AST compilation failed. If this is due to CSP, use the standard compile() function instead. Error: ${d instanceof Error?d.message:String(d)}`)}return {fn:p,deps:e,hash:c}}function on(n,t,s={}){let{fn:i}=q(n,s);return i(t)}function Jn(n,t){return z(n,t)}function z(n,t){if(n===null)return null;if(typeof n!="object")return n;if(Array.isArray(n))return n.map(o=>z(o,t));let s=n,i=Object.keys(s);for(let o of i)if(o in t){let e=t[o](s);if(typeof e=="object"&&e!==null&&o in e)throw new Error(`Transform "${o}" returned object with same key \u2014 infinite loop`);return z(e,t)}let r={};for(let o of i)r[o]=z(s[o],t);return r}var bt="2.0.0";exports.ExpressionCache=j;exports.VERSION=bt;exports.assertValid=kn;exports.builders=X;exports.cache=P;exports.cached=wn;exports.clearPathCache=dn;exports.compile=N;exports.compileAST=q;exports.compilePath=O;exports.dslToAST=G;exports.evaluate=Sn;exports.evaluateAST=on;exports.extractDataRoots=D;exports.extractDeps=w;exports.extractScopeFns=W;exports.get=pn;exports.getPathCacheSize=gn;exports.hasDeps=mn;exports.hasWildcard=B;exports.isCondition=E;exports.isConditionExpr=fn;exports.isConditionGroup=h;exports.isConditional=T;exports.isFn=b;exports.isLiteral=I;exports.isPipe=C;exports.isPure=yn;exports.isRef=y;exports.isValid=xn;exports.normalize=Jn;exports.normalizePath=F;exports.validate=M;exports.wrapInFunction=en;
|
package/dist/index.d.cts
CHANGED
|
@@ -26,49 +26,15 @@ interface ConditionalExpr {
|
|
|
26
26
|
then: Expression;
|
|
27
27
|
else?: Expression;
|
|
28
28
|
}
|
|
29
|
-
/**
|
|
30
|
-
* Callback function passed as argument to $fn (predicates, mappers, etc.)
|
|
31
|
-
* These are native JS functions, not DSL expressions.
|
|
32
|
-
* @example (item) => item.active
|
|
33
|
-
* @example (n) => n * 2
|
|
34
|
-
*/
|
|
35
|
-
type CallbackFn = (...args: any[]) => any;
|
|
36
|
-
/**
|
|
37
|
-
* Argument to a $fn expression: can be a DSL expression or a native callback
|
|
38
|
-
*/
|
|
39
|
-
type FnArg = Expression | CallbackFn;
|
|
40
29
|
/**
|
|
41
30
|
* Function call expression
|
|
42
31
|
* Calls a function from the provided scope with compiled arguments
|
|
43
32
|
* @example { "$fn": "add", "args": [{ "$": "a" }, { "$": "b" }] }
|
|
44
|
-
* @example { "$fn": "filter", "args": [
|
|
33
|
+
* @example { "$fn": "filter", "args": [{ "$fn": "isActive" }] }
|
|
45
34
|
*/
|
|
46
35
|
interface FnExpr {
|
|
47
36
|
$fn: string;
|
|
48
|
-
args?:
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Result of a transform function.
|
|
52
|
-
*
|
|
53
|
-
* Structurally similar to FnExpr but with relaxed args typing.
|
|
54
|
-
* Transforms can return domain-specific types in args (e.g., TestSpec, QueryParams)
|
|
55
|
-
* that will be passed to the scope function at runtime.
|
|
56
|
-
*
|
|
57
|
-
* Type safety for these args comes from the scope function implementation,
|
|
58
|
-
* not from the expression type system.
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```ts
|
|
62
|
-
* // Transform for $test
|
|
63
|
-
* const transform: TransformFn = (node) => ({
|
|
64
|
-
* $fn: "__test",
|
|
65
|
-
* args: [node.$test] // TestSpec, not FnArg
|
|
66
|
-
* });
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
interface TransformResult {
|
|
70
|
-
readonly $fn: string;
|
|
71
|
-
readonly args?: unknown[];
|
|
37
|
+
args?: Expression[];
|
|
72
38
|
}
|
|
73
39
|
/**
|
|
74
40
|
* Pipe expression (DSL syntax for composition with initial value)
|
|
@@ -81,8 +47,8 @@ interface PipeExpr {
|
|
|
81
47
|
/**
|
|
82
48
|
* Literal values (primitives, arrays, plain objects)
|
|
83
49
|
*/
|
|
84
|
-
type Literal = string | number | boolean | null |
|
|
85
|
-
[key: string]:
|
|
50
|
+
type Literal = string | number | boolean | null | Expression[] | {
|
|
51
|
+
[key: string]: Expression;
|
|
86
52
|
};
|
|
87
53
|
/**
|
|
88
54
|
* Condition expression - both sides accept any Expression
|
|
@@ -156,31 +122,6 @@ interface ValidationResult {
|
|
|
156
122
|
* @example { add, subtract, multiply, filter, map, sum }
|
|
157
123
|
*/
|
|
158
124
|
type Scope = Record<string, (...args: any[]) => any>;
|
|
159
|
-
/**
|
|
160
|
-
* Transform function for custom expression types.
|
|
161
|
-
*
|
|
162
|
-
* Receives the raw node (e.g., { $query: "name", params: {...} }) and returns:
|
|
163
|
-
* - Expression: for complex rewrites to standard expressions
|
|
164
|
-
* - TransformResult: for $fn calls with domain-specific args
|
|
165
|
-
*
|
|
166
|
-
* The returned value is compiled recursively. TransformResult args are
|
|
167
|
-
* compiled as literals and passed to the scope function at runtime.
|
|
168
|
-
*
|
|
169
|
-
* @example
|
|
170
|
-
* ```ts
|
|
171
|
-
* const transforms = {
|
|
172
|
-
* $query: (node) => ({
|
|
173
|
-
* $fn: "__query",
|
|
174
|
-
* args: [node.$query, node.params ?? {}]
|
|
175
|
-
* }),
|
|
176
|
-
* $test: (node) => ({
|
|
177
|
-
* $fn: "__test",
|
|
178
|
-
* args: [node.$test] // TestSpec passed as-is
|
|
179
|
-
* }),
|
|
180
|
-
* };
|
|
181
|
-
* ```
|
|
182
|
-
*/
|
|
183
|
-
type TransformFn = (node: Record<string, unknown>) => Expression | TransformResult;
|
|
184
125
|
/**
|
|
185
126
|
* Options for compilation
|
|
186
127
|
*/
|
|
@@ -196,13 +137,6 @@ interface CompileOptions<T = unknown> {
|
|
|
196
137
|
* compile(expr, { accessor: (path, ctx) => ctx.get(path) })
|
|
197
138
|
*/
|
|
198
139
|
accessor?: AccessorFn<T>;
|
|
199
|
-
/**
|
|
200
|
-
* Custom expression transforms.
|
|
201
|
-
* Key = marker (e.g. "$query"), value = transform function.
|
|
202
|
-
* The walker calls the transform before treating as literal.
|
|
203
|
-
* The returned Expression is compiled recursively.
|
|
204
|
-
*/
|
|
205
|
-
transforms?: Record<string, TransformFn>;
|
|
206
140
|
}
|
|
207
141
|
/**
|
|
208
142
|
* Check if value is a reference expression
|
|
@@ -216,12 +150,6 @@ declare const isConditional: (v: unknown) => v is ConditionalExpr;
|
|
|
216
150
|
* Check if value is a function call expression
|
|
217
151
|
*/
|
|
218
152
|
declare const isFn: (v: unknown) => v is FnExpr;
|
|
219
|
-
/**
|
|
220
|
-
* Check if value is a transform result.
|
|
221
|
-
* Note: TransformResult is structurally similar to FnExpr,
|
|
222
|
-
* so this guard is mainly for documentation/intent.
|
|
223
|
-
*/
|
|
224
|
-
declare const isTransformResult: (v: unknown) => v is TransformResult;
|
|
225
153
|
/**
|
|
226
154
|
* Check if value is a pipe expression
|
|
227
155
|
*/
|
|
@@ -353,7 +281,7 @@ declare function getPathCacheSize(): number;
|
|
|
353
281
|
* @example { "$": "user.age" } → ["user.age"]
|
|
354
282
|
* @example { "$if": "$isVip", "then": { "$": "price.vip" } } → ["$isVip", "price.vip"]
|
|
355
283
|
*/
|
|
356
|
-
declare function extractDeps(expr: Expression
|
|
284
|
+
declare function extractDeps(expr: Expression): string[];
|
|
357
285
|
/**
|
|
358
286
|
* Check if expression has dependencies
|
|
359
287
|
*/
|
|
@@ -501,7 +429,7 @@ declare const ref: typeof $;
|
|
|
501
429
|
* $fn("sum") // no args - returns function reference
|
|
502
430
|
* $fn("now", []) // empty args - calls function
|
|
503
431
|
*/
|
|
504
|
-
declare function $fn(name: string, args?:
|
|
432
|
+
declare function $fn(name: string, args?: Expression[]): FnExpr;
|
|
505
433
|
/**
|
|
506
434
|
* Alias for $fn (function builder)
|
|
507
435
|
*/
|
|
@@ -608,11 +536,6 @@ interface TransformOptions {
|
|
|
608
536
|
* - `lexicalPrefix: "params"` → `params?.foo` instead of `accessor("params.foo", data)`
|
|
609
537
|
*/
|
|
610
538
|
lexicalPrefix?: string;
|
|
611
|
-
/**
|
|
612
|
-
* Custom expression transforms.
|
|
613
|
-
* Key = marker (e.g. "$query"), value = transform function.
|
|
614
|
-
*/
|
|
615
|
-
transforms?: Record<string, TransformFn>;
|
|
616
539
|
}
|
|
617
540
|
/**
|
|
618
541
|
* Transform DSL expression to AST node
|
|
@@ -649,7 +572,6 @@ declare function wrapInFunction(bodyAst: ASTNode, params?: string[]): ASTNode;
|
|
|
649
572
|
* Extract all function names used from scope in an expression
|
|
650
573
|
*
|
|
651
574
|
* @param expr - DSL expression to analyze
|
|
652
|
-
* @param transforms - Optional custom transforms (to resolve custom nodes before collecting)
|
|
653
575
|
* @returns Set of function names used
|
|
654
576
|
*
|
|
655
577
|
* @example
|
|
@@ -667,7 +589,7 @@ declare function wrapInFunction(bodyAst: ASTNode, params?: string[]): ASTNode;
|
|
|
667
589
|
* // Set { "filter", "sum" }
|
|
668
590
|
* ```
|
|
669
591
|
*/
|
|
670
|
-
declare function extractScopeFns(expr: Expression
|
|
592
|
+
declare function extractScopeFns(expr: Expression): Set<string>;
|
|
671
593
|
/**
|
|
672
594
|
* Extract root-level data dependencies from paths
|
|
673
595
|
*
|
|
@@ -709,11 +631,6 @@ interface CompileASTOptions {
|
|
|
709
631
|
* - `lexicalPrefix: "params"` → `params?.foo` instead of `accessor("params.foo", data)`
|
|
710
632
|
*/
|
|
711
633
|
lexicalPrefix?: string;
|
|
712
|
-
/**
|
|
713
|
-
* Custom expression transforms.
|
|
714
|
-
* Key = marker (e.g. "$query"), value = transform function.
|
|
715
|
-
*/
|
|
716
|
-
transforms?: Record<string, TransformFn>;
|
|
717
634
|
}
|
|
718
635
|
/** Result when returnCode is true */
|
|
719
636
|
interface CompileASTCodeResult {
|
|
@@ -763,6 +680,72 @@ declare function compileAST<T = unknown, R = unknown>(expr: Expression, options?
|
|
|
763
680
|
*/
|
|
764
681
|
declare function evaluateAST<T = unknown, R = unknown>(expr: Expression, data: T, options?: CompileASTOptions): R;
|
|
765
682
|
|
|
683
|
+
/**
|
|
684
|
+
* @statedelta-libs/expressions - Normalize
|
|
685
|
+
*
|
|
686
|
+
* External normalization helper for custom expression types.
|
|
687
|
+
* Converts custom DSL nodes ($query, $mapper, etc.) to standard Expression
|
|
688
|
+
* BEFORE compilation. Keeps the core compiler pure.
|
|
689
|
+
*
|
|
690
|
+
* @example
|
|
691
|
+
* ```ts
|
|
692
|
+
* const transforms = {
|
|
693
|
+
* $query: (node) => ({ $fn: "__query", args: [node.$query, node.params ?? {}] })
|
|
694
|
+
* };
|
|
695
|
+
*
|
|
696
|
+
* const pure = normalize(
|
|
697
|
+
* { $query: "isAttacked", params: { row: { $: "kingRow" } } },
|
|
698
|
+
* transforms
|
|
699
|
+
* );
|
|
700
|
+
* // → { $fn: "__query", args: ["isAttacked", { row: { $: "kingRow" } }] }
|
|
701
|
+
*
|
|
702
|
+
* compile(pure, { scope });
|
|
703
|
+
* ```
|
|
704
|
+
*/
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Transform function for custom expression types.
|
|
708
|
+
* Receives the raw node and returns a standard Expression.
|
|
709
|
+
*
|
|
710
|
+
* @example
|
|
711
|
+
* ```ts
|
|
712
|
+
* const transforms: Transforms = {
|
|
713
|
+
* $query: (node) => ({
|
|
714
|
+
* $fn: "__query",
|
|
715
|
+
* args: [node.$query, node.params ?? {}]
|
|
716
|
+
* }),
|
|
717
|
+
* };
|
|
718
|
+
* ```
|
|
719
|
+
*/
|
|
720
|
+
type TransformFn = (node: Record<string, unknown>) => Expression;
|
|
721
|
+
/**
|
|
722
|
+
* Map of transform functions keyed by marker (e.g. "$query", "$mapper")
|
|
723
|
+
*/
|
|
724
|
+
type Transforms = Record<string, TransformFn>;
|
|
725
|
+
/**
|
|
726
|
+
* Normalize an expression by applying transforms recursively.
|
|
727
|
+
* Converts custom DSL nodes to standard Expression types.
|
|
728
|
+
*
|
|
729
|
+
* @param expr - Expression (possibly with custom nodes)
|
|
730
|
+
* @param transforms - Map of transform functions
|
|
731
|
+
* @returns Pure Expression with all custom nodes converted
|
|
732
|
+
*
|
|
733
|
+
* @example
|
|
734
|
+
* ```ts
|
|
735
|
+
* const transforms = {
|
|
736
|
+
* $query: (node) => ({ $fn: "__query", args: [node.$query, node.params ?? {}] })
|
|
737
|
+
* };
|
|
738
|
+
*
|
|
739
|
+
* normalize({ $query: "check", params: { x: 1 } }, transforms);
|
|
740
|
+
* // → { $fn: "__query", args: ["check", { x: 1 }] }
|
|
741
|
+
*
|
|
742
|
+
* // Nested expressions in params are also normalized
|
|
743
|
+
* normalize({ $query: "check", params: { row: { $: "myRow" } } }, transforms);
|
|
744
|
+
* // → { $fn: "__query", args: ["check", { row: { $: "myRow" } }] }
|
|
745
|
+
* ```
|
|
746
|
+
*/
|
|
747
|
+
declare function normalize(expr: unknown, transforms: Transforms): Expression;
|
|
748
|
+
|
|
766
749
|
/**
|
|
767
750
|
* @statedelta-libs/expressions
|
|
768
751
|
*
|
|
@@ -796,6 +779,6 @@ declare function evaluateAST<T = unknown, R = unknown>(expr: Expression, data: T
|
|
|
796
779
|
* ); // 3
|
|
797
780
|
* ```
|
|
798
781
|
*/
|
|
799
|
-
declare const VERSION = "
|
|
782
|
+
declare const VERSION = "2.0.0";
|
|
800
783
|
|
|
801
|
-
export { type AccessorFn, type
|
|
784
|
+
export { type AccessorFn, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type Expression, ExpressionCache, type FnExpr, type Literal, type PathGetter, type PipeExpr, type RefExpr, type Scope, type TransformFn, type TransformOptions, type Transforms, VERSION, type ValidateOptions, type ValidationResult, assertValid, builders, cache, cached, clearPathCache, compile, compileAST, compilePath, dslToAST, evaluate, evaluateAST, extractDataRoots, extractDeps, extractScopeFns, get, getPathCacheSize, hasDeps, hasWildcard, isCondition, isConditionExpr, isConditionGroup, isConditional, isFn, isLiteral, isPipe, isPure, isRef, isValid, normalize, normalizePath, validate, wrapInFunction };
|
package/dist/index.d.ts
CHANGED
|
@@ -26,49 +26,15 @@ interface ConditionalExpr {
|
|
|
26
26
|
then: Expression;
|
|
27
27
|
else?: Expression;
|
|
28
28
|
}
|
|
29
|
-
/**
|
|
30
|
-
* Callback function passed as argument to $fn (predicates, mappers, etc.)
|
|
31
|
-
* These are native JS functions, not DSL expressions.
|
|
32
|
-
* @example (item) => item.active
|
|
33
|
-
* @example (n) => n * 2
|
|
34
|
-
*/
|
|
35
|
-
type CallbackFn = (...args: any[]) => any;
|
|
36
|
-
/**
|
|
37
|
-
* Argument to a $fn expression: can be a DSL expression or a native callback
|
|
38
|
-
*/
|
|
39
|
-
type FnArg = Expression | CallbackFn;
|
|
40
29
|
/**
|
|
41
30
|
* Function call expression
|
|
42
31
|
* Calls a function from the provided scope with compiled arguments
|
|
43
32
|
* @example { "$fn": "add", "args": [{ "$": "a" }, { "$": "b" }] }
|
|
44
|
-
* @example { "$fn": "filter", "args": [
|
|
33
|
+
* @example { "$fn": "filter", "args": [{ "$fn": "isActive" }] }
|
|
45
34
|
*/
|
|
46
35
|
interface FnExpr {
|
|
47
36
|
$fn: string;
|
|
48
|
-
args?:
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Result of a transform function.
|
|
52
|
-
*
|
|
53
|
-
* Structurally similar to FnExpr but with relaxed args typing.
|
|
54
|
-
* Transforms can return domain-specific types in args (e.g., TestSpec, QueryParams)
|
|
55
|
-
* that will be passed to the scope function at runtime.
|
|
56
|
-
*
|
|
57
|
-
* Type safety for these args comes from the scope function implementation,
|
|
58
|
-
* not from the expression type system.
|
|
59
|
-
*
|
|
60
|
-
* @example
|
|
61
|
-
* ```ts
|
|
62
|
-
* // Transform for $test
|
|
63
|
-
* const transform: TransformFn = (node) => ({
|
|
64
|
-
* $fn: "__test",
|
|
65
|
-
* args: [node.$test] // TestSpec, not FnArg
|
|
66
|
-
* });
|
|
67
|
-
* ```
|
|
68
|
-
*/
|
|
69
|
-
interface TransformResult {
|
|
70
|
-
readonly $fn: string;
|
|
71
|
-
readonly args?: unknown[];
|
|
37
|
+
args?: Expression[];
|
|
72
38
|
}
|
|
73
39
|
/**
|
|
74
40
|
* Pipe expression (DSL syntax for composition with initial value)
|
|
@@ -81,8 +47,8 @@ interface PipeExpr {
|
|
|
81
47
|
/**
|
|
82
48
|
* Literal values (primitives, arrays, plain objects)
|
|
83
49
|
*/
|
|
84
|
-
type Literal = string | number | boolean | null |
|
|
85
|
-
[key: string]:
|
|
50
|
+
type Literal = string | number | boolean | null | Expression[] | {
|
|
51
|
+
[key: string]: Expression;
|
|
86
52
|
};
|
|
87
53
|
/**
|
|
88
54
|
* Condition expression - both sides accept any Expression
|
|
@@ -156,31 +122,6 @@ interface ValidationResult {
|
|
|
156
122
|
* @example { add, subtract, multiply, filter, map, sum }
|
|
157
123
|
*/
|
|
158
124
|
type Scope = Record<string, (...args: any[]) => any>;
|
|
159
|
-
/**
|
|
160
|
-
* Transform function for custom expression types.
|
|
161
|
-
*
|
|
162
|
-
* Receives the raw node (e.g., { $query: "name", params: {...} }) and returns:
|
|
163
|
-
* - Expression: for complex rewrites to standard expressions
|
|
164
|
-
* - TransformResult: for $fn calls with domain-specific args
|
|
165
|
-
*
|
|
166
|
-
* The returned value is compiled recursively. TransformResult args are
|
|
167
|
-
* compiled as literals and passed to the scope function at runtime.
|
|
168
|
-
*
|
|
169
|
-
* @example
|
|
170
|
-
* ```ts
|
|
171
|
-
* const transforms = {
|
|
172
|
-
* $query: (node) => ({
|
|
173
|
-
* $fn: "__query",
|
|
174
|
-
* args: [node.$query, node.params ?? {}]
|
|
175
|
-
* }),
|
|
176
|
-
* $test: (node) => ({
|
|
177
|
-
* $fn: "__test",
|
|
178
|
-
* args: [node.$test] // TestSpec passed as-is
|
|
179
|
-
* }),
|
|
180
|
-
* };
|
|
181
|
-
* ```
|
|
182
|
-
*/
|
|
183
|
-
type TransformFn = (node: Record<string, unknown>) => Expression | TransformResult;
|
|
184
125
|
/**
|
|
185
126
|
* Options for compilation
|
|
186
127
|
*/
|
|
@@ -196,13 +137,6 @@ interface CompileOptions<T = unknown> {
|
|
|
196
137
|
* compile(expr, { accessor: (path, ctx) => ctx.get(path) })
|
|
197
138
|
*/
|
|
198
139
|
accessor?: AccessorFn<T>;
|
|
199
|
-
/**
|
|
200
|
-
* Custom expression transforms.
|
|
201
|
-
* Key = marker (e.g. "$query"), value = transform function.
|
|
202
|
-
* The walker calls the transform before treating as literal.
|
|
203
|
-
* The returned Expression is compiled recursively.
|
|
204
|
-
*/
|
|
205
|
-
transforms?: Record<string, TransformFn>;
|
|
206
140
|
}
|
|
207
141
|
/**
|
|
208
142
|
* Check if value is a reference expression
|
|
@@ -216,12 +150,6 @@ declare const isConditional: (v: unknown) => v is ConditionalExpr;
|
|
|
216
150
|
* Check if value is a function call expression
|
|
217
151
|
*/
|
|
218
152
|
declare const isFn: (v: unknown) => v is FnExpr;
|
|
219
|
-
/**
|
|
220
|
-
* Check if value is a transform result.
|
|
221
|
-
* Note: TransformResult is structurally similar to FnExpr,
|
|
222
|
-
* so this guard is mainly for documentation/intent.
|
|
223
|
-
*/
|
|
224
|
-
declare const isTransformResult: (v: unknown) => v is TransformResult;
|
|
225
153
|
/**
|
|
226
154
|
* Check if value is a pipe expression
|
|
227
155
|
*/
|
|
@@ -353,7 +281,7 @@ declare function getPathCacheSize(): number;
|
|
|
353
281
|
* @example { "$": "user.age" } → ["user.age"]
|
|
354
282
|
* @example { "$if": "$isVip", "then": { "$": "price.vip" } } → ["$isVip", "price.vip"]
|
|
355
283
|
*/
|
|
356
|
-
declare function extractDeps(expr: Expression
|
|
284
|
+
declare function extractDeps(expr: Expression): string[];
|
|
357
285
|
/**
|
|
358
286
|
* Check if expression has dependencies
|
|
359
287
|
*/
|
|
@@ -501,7 +429,7 @@ declare const ref: typeof $;
|
|
|
501
429
|
* $fn("sum") // no args - returns function reference
|
|
502
430
|
* $fn("now", []) // empty args - calls function
|
|
503
431
|
*/
|
|
504
|
-
declare function $fn(name: string, args?:
|
|
432
|
+
declare function $fn(name: string, args?: Expression[]): FnExpr;
|
|
505
433
|
/**
|
|
506
434
|
* Alias for $fn (function builder)
|
|
507
435
|
*/
|
|
@@ -608,11 +536,6 @@ interface TransformOptions {
|
|
|
608
536
|
* - `lexicalPrefix: "params"` → `params?.foo` instead of `accessor("params.foo", data)`
|
|
609
537
|
*/
|
|
610
538
|
lexicalPrefix?: string;
|
|
611
|
-
/**
|
|
612
|
-
* Custom expression transforms.
|
|
613
|
-
* Key = marker (e.g. "$query"), value = transform function.
|
|
614
|
-
*/
|
|
615
|
-
transforms?: Record<string, TransformFn>;
|
|
616
539
|
}
|
|
617
540
|
/**
|
|
618
541
|
* Transform DSL expression to AST node
|
|
@@ -649,7 +572,6 @@ declare function wrapInFunction(bodyAst: ASTNode, params?: string[]): ASTNode;
|
|
|
649
572
|
* Extract all function names used from scope in an expression
|
|
650
573
|
*
|
|
651
574
|
* @param expr - DSL expression to analyze
|
|
652
|
-
* @param transforms - Optional custom transforms (to resolve custom nodes before collecting)
|
|
653
575
|
* @returns Set of function names used
|
|
654
576
|
*
|
|
655
577
|
* @example
|
|
@@ -667,7 +589,7 @@ declare function wrapInFunction(bodyAst: ASTNode, params?: string[]): ASTNode;
|
|
|
667
589
|
* // Set { "filter", "sum" }
|
|
668
590
|
* ```
|
|
669
591
|
*/
|
|
670
|
-
declare function extractScopeFns(expr: Expression
|
|
592
|
+
declare function extractScopeFns(expr: Expression): Set<string>;
|
|
671
593
|
/**
|
|
672
594
|
* Extract root-level data dependencies from paths
|
|
673
595
|
*
|
|
@@ -709,11 +631,6 @@ interface CompileASTOptions {
|
|
|
709
631
|
* - `lexicalPrefix: "params"` → `params?.foo` instead of `accessor("params.foo", data)`
|
|
710
632
|
*/
|
|
711
633
|
lexicalPrefix?: string;
|
|
712
|
-
/**
|
|
713
|
-
* Custom expression transforms.
|
|
714
|
-
* Key = marker (e.g. "$query"), value = transform function.
|
|
715
|
-
*/
|
|
716
|
-
transforms?: Record<string, TransformFn>;
|
|
717
634
|
}
|
|
718
635
|
/** Result when returnCode is true */
|
|
719
636
|
interface CompileASTCodeResult {
|
|
@@ -763,6 +680,72 @@ declare function compileAST<T = unknown, R = unknown>(expr: Expression, options?
|
|
|
763
680
|
*/
|
|
764
681
|
declare function evaluateAST<T = unknown, R = unknown>(expr: Expression, data: T, options?: CompileASTOptions): R;
|
|
765
682
|
|
|
683
|
+
/**
|
|
684
|
+
* @statedelta-libs/expressions - Normalize
|
|
685
|
+
*
|
|
686
|
+
* External normalization helper for custom expression types.
|
|
687
|
+
* Converts custom DSL nodes ($query, $mapper, etc.) to standard Expression
|
|
688
|
+
* BEFORE compilation. Keeps the core compiler pure.
|
|
689
|
+
*
|
|
690
|
+
* @example
|
|
691
|
+
* ```ts
|
|
692
|
+
* const transforms = {
|
|
693
|
+
* $query: (node) => ({ $fn: "__query", args: [node.$query, node.params ?? {}] })
|
|
694
|
+
* };
|
|
695
|
+
*
|
|
696
|
+
* const pure = normalize(
|
|
697
|
+
* { $query: "isAttacked", params: { row: { $: "kingRow" } } },
|
|
698
|
+
* transforms
|
|
699
|
+
* );
|
|
700
|
+
* // → { $fn: "__query", args: ["isAttacked", { row: { $: "kingRow" } }] }
|
|
701
|
+
*
|
|
702
|
+
* compile(pure, { scope });
|
|
703
|
+
* ```
|
|
704
|
+
*/
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Transform function for custom expression types.
|
|
708
|
+
* Receives the raw node and returns a standard Expression.
|
|
709
|
+
*
|
|
710
|
+
* @example
|
|
711
|
+
* ```ts
|
|
712
|
+
* const transforms: Transforms = {
|
|
713
|
+
* $query: (node) => ({
|
|
714
|
+
* $fn: "__query",
|
|
715
|
+
* args: [node.$query, node.params ?? {}]
|
|
716
|
+
* }),
|
|
717
|
+
* };
|
|
718
|
+
* ```
|
|
719
|
+
*/
|
|
720
|
+
type TransformFn = (node: Record<string, unknown>) => Expression;
|
|
721
|
+
/**
|
|
722
|
+
* Map of transform functions keyed by marker (e.g. "$query", "$mapper")
|
|
723
|
+
*/
|
|
724
|
+
type Transforms = Record<string, TransformFn>;
|
|
725
|
+
/**
|
|
726
|
+
* Normalize an expression by applying transforms recursively.
|
|
727
|
+
* Converts custom DSL nodes to standard Expression types.
|
|
728
|
+
*
|
|
729
|
+
* @param expr - Expression (possibly with custom nodes)
|
|
730
|
+
* @param transforms - Map of transform functions
|
|
731
|
+
* @returns Pure Expression with all custom nodes converted
|
|
732
|
+
*
|
|
733
|
+
* @example
|
|
734
|
+
* ```ts
|
|
735
|
+
* const transforms = {
|
|
736
|
+
* $query: (node) => ({ $fn: "__query", args: [node.$query, node.params ?? {}] })
|
|
737
|
+
* };
|
|
738
|
+
*
|
|
739
|
+
* normalize({ $query: "check", params: { x: 1 } }, transforms);
|
|
740
|
+
* // → { $fn: "__query", args: ["check", { x: 1 }] }
|
|
741
|
+
*
|
|
742
|
+
* // Nested expressions in params are also normalized
|
|
743
|
+
* normalize({ $query: "check", params: { row: { $: "myRow" } } }, transforms);
|
|
744
|
+
* // → { $fn: "__query", args: ["check", { row: { $: "myRow" } }] }
|
|
745
|
+
* ```
|
|
746
|
+
*/
|
|
747
|
+
declare function normalize(expr: unknown, transforms: Transforms): Expression;
|
|
748
|
+
|
|
766
749
|
/**
|
|
767
750
|
* @statedelta-libs/expressions
|
|
768
751
|
*
|
|
@@ -796,6 +779,6 @@ declare function evaluateAST<T = unknown, R = unknown>(expr: Expression, data: T
|
|
|
796
779
|
* ); // 3
|
|
797
780
|
* ```
|
|
798
781
|
*/
|
|
799
|
-
declare const VERSION = "
|
|
782
|
+
declare const VERSION = "2.0.0";
|
|
800
783
|
|
|
801
|
-
export { type AccessorFn, type
|
|
784
|
+
export { type AccessorFn, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type Expression, ExpressionCache, type FnExpr, type Literal, type PathGetter, type PipeExpr, type RefExpr, type Scope, type TransformFn, type TransformOptions, type Transforms, VERSION, type ValidateOptions, type ValidationResult, assertValid, builders, cache, cached, clearPathCache, compile, compileAST, compilePath, dslToAST, evaluate, evaluateAST, extractDataRoots, extractDeps, extractScopeFns, get, getPathCacheSize, hasDeps, hasWildcard, isCondition, isConditionExpr, isConditionGroup, isConditional, isFn, isLiteral, isPipe, isPure, isRef, isValid, normalize, normalizePath, validate, wrapInFunction };
|