@statedelta-libs/expressions 2.0.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,9 +10,11 @@
10
10
  - **DSL Puro** - 100% JSON-serializável, sem callbacks inline
11
11
  - **Compilação** - Compila uma vez, executa milhões de vezes
12
12
  - **Alta performance** - ~25-30M ops/s após compilação
13
- - **Scope externo** - Funções vêm via scope, não hardcoded
13
+ - **Scope externo** - Funções puras vêm via scope, não hardcoded
14
+ - **Context externo** - HOCs de continuidade via context (`tryCatch`, `transaction`, etc.)
14
15
  - **Accessor customizado** - Suporte a `ctx.get(path)` para objetos especiais
15
16
  - **$pipe** - Composição com valor inicial (sintaxe DSL)
17
+ - **$cb** - Callback expressions para HOCs de continuidade
16
18
  - **Path syntax** - Suporte a wildcards (`items[*].price`)
17
19
  - **Dependency extraction** - Para dirty tracking/reatividade
18
20
  - **Conditions nativo** - Condicionais integradas com expressions nos lados
@@ -297,6 +299,76 @@ Condicionais compiladas internamente. Ambos os lados aceitam qualquer expressão
297
299
 
298
300
  **Operadores:** `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `notIn`, `contains`, `notContains`, `exists`, `notExists`, `matches`, `notMatches`, `startsWith`, `endsWith`
299
301
 
302
+ ### Callback ($cb)
303
+
304
+ HOC de continuidade - executa body dentro de um context function.
305
+
306
+ ```typescript
307
+ // Básico - tryCatch
308
+ { $cb: "tryCatch", body: { $fn: "query" } }
309
+
310
+ // Com parâmetros
311
+ { $cb: "transaction", body: { $fn: "save" }, params: { isolation: "serializable" } }
312
+
313
+ // Aninhado
314
+ {
315
+ $cb: "tryCatch",
316
+ body: {
317
+ $cb: "transaction",
318
+ body: { $fn: "save" }
319
+ }
320
+ }
321
+ ```
322
+
323
+ ## Context
324
+
325
+ O context define HOCs disponíveis para `$cb`. Diferente de scope (funções puras), context functions controlam a execução do body:
326
+
327
+ ```typescript
328
+ import type { Context, ContextFn } from '@statedelta-libs/expressions';
329
+
330
+ const tryCatch: ContextFn = (cb, data, get, params) => {
331
+ try {
332
+ return cb(data, get);
333
+ } catch {
334
+ return params?.fallback ?? null;
335
+ }
336
+ };
337
+
338
+ const transaction: ContextFn = (cb, data, get, params) => {
339
+ const tx = db.beginTransaction(params);
340
+ try {
341
+ const result = cb({ ...data, tx }, get);
342
+ tx.commit();
343
+ return result;
344
+ } catch (e) {
345
+ tx.rollback();
346
+ throw e;
347
+ }
348
+ };
349
+
350
+ // Context function pode ignorar o cb e retornar outro valor
351
+ const cached: ContextFn = (cb, data, get, params) => {
352
+ if (cache.has(params?.key)) {
353
+ return cache.get(params.key); // Não executa cb
354
+ }
355
+ return cb(data, get);
356
+ };
357
+
358
+ const context: Context = { tryCatch, transaction, cached };
359
+
360
+ compile(expression, { scope, context });
361
+ ```
362
+
363
+ **Parâmetros do ContextFn:**
364
+
365
+ | Parâmetro | Tipo | Descrição |
366
+ |-----------|------|-----------|
367
+ | `cb` | `(data, get) => R` | Body compilado como callback |
368
+ | `data` | `T` | Dados do runtime |
369
+ | `get` | `(path) => unknown` | Resolver de paths |
370
+ | `params` | `unknown` | Parâmetros do `$cb.params` |
371
+
300
372
  ## Scope
301
373
 
302
374
  O scope define quais funções estão disponíveis para `$fn`:
@@ -399,7 +471,7 @@ Funções declarativas para construir expressões:
399
471
  ```typescript
400
472
  import { builders } from '@statedelta-libs/expressions';
401
473
 
402
- const { $, $fn, $if, $pipe, $cond } = builders;
474
+ const { $, $fn, $if, $pipe, $cond, $cb } = builders;
403
475
 
404
476
  // Path reference
405
477
  $("player.hp") // { $: "player.hp" }
@@ -420,6 +492,10 @@ $pipe(
420
492
 
421
493
  // Condition
422
494
  $cond($("age"), "gte", 18) // { left: ..., op: "gte", right: 18 }
495
+
496
+ // Callback (context)
497
+ $cb("tryCatch", $fn("query")) // { $cb: "tryCatch", body: {...} }
498
+ $cb("transaction", $fn("save"), { isolation: "serializable" })
423
499
  ```
424
500
 
425
501
  ## TypeScript
@@ -432,11 +508,15 @@ import type {
432
508
  ConditionalExpr,
433
509
  FnExpr,
434
510
  PipeExpr,
511
+ CbExpr,
435
512
  Condition,
436
513
  ConditionGroup,
437
514
  ConditionExpr,
438
515
  ConditionOp,
439
516
  Scope,
517
+ Context,
518
+ ContextFn,
519
+ PathGetterFn,
440
520
  CompileOptions,
441
521
  AccessorFn,
442
522
  TransformFn,
@@ -449,6 +529,7 @@ import {
449
529
  isConditional,
450
530
  isFn,
451
531
  isPipe,
532
+ isCb,
452
533
  isCondition,
453
534
  isLiteral,
454
535
  } from '@statedelta-libs/expressions';
@@ -505,6 +586,28 @@ Funções só são acessíveis se existirem no `scope` fornecido pelo desenvolve
505
586
 
506
587
  4. **Novos tipos**: `Transforms` (alias para `Record<string, TransformFn>`)
507
588
 
589
+ ### v1.2 → v2.0
590
+
591
+ 1. **Novo tipo `$cb`**: HOC de continuidade para wrapping contextual:
592
+ ```typescript
593
+ // tryCatch, transaction, cached, etc.
594
+ { $cb: "tryCatch", body: { $fn: "query" }, params: { fallback: [] } }
595
+ ```
596
+
597
+ 2. **Novo `context` em CompileOptions**: Separado de `scope` para HOCs:
598
+ ```typescript
599
+ compile(expr, { scope, context });
600
+ compileAST(expr, { scope, context });
601
+ ```
602
+
603
+ 3. **Novos tipos**: `CbExpr`, `Context`, `ContextFn`, `PathGetterFn`
604
+
605
+ 4. **Novo type guard**: `isCb()`
606
+
607
+ 5. **Novo builder**: `$cb(name, body, params?)`
608
+
609
+ 6. **Novo extractor**: `extractContextFns()`
610
+
508
611
  ## Licença
509
612
 
510
613
  MIT © Anderson D. Rosa
package/dist/index.cjs CHANGED
@@ -1 +1 @@
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;
1
+ 'use strict';var omniAst=require('omni-ast');var gn=Object.defineProperty;var mn=(n,t)=>{for(var o in t)gn(n,o,{get:t[o],enumerable:true});};var E=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,S=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,w=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),x=n=>n!==null&&typeof n=="object"&&"$cb"in n&&typeof n.$cb=="string"&&"body"in n,v=new Set(["eq","neq","gt","gte","lt","lte","in","notIn","contains","notContains","exists","notExists","matches","notMatches","startsWith","endsWith"]),h=n=>n!==null&&typeof n=="object"&&"left"in n&&"op"in n&&v.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),b=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,yn=n=>h(n)||b(n),B=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 o=n,r="left"in o&&"op"in o&&v.has(o.op);return !("$"in o)&&!("$if"in o)&&!("$fn"in o)&&!("$pipe"in o)&&!("$cb"in o)&&!r&&!("logic"in o)}return false};var G=new Map;function Q(n){let t=[],o=n.length,r=0,i="";for(;r<o;){let s=n[r];if(s===".")i&&(t.push({type:"key",value:i}),i=""),r++;else if(s==="["){i&&(t.push({type:"key",value:i}),i=""),r++;let e=r;for(;r<o&&n[r]!=="]";)r++;let f=n.slice(e,r);if(r++,f==="*")t.push({type:"wildcard",value:"*"});else {let u=parseInt(f,10);t.push({type:"index",value:isNaN(u)?f:u});}}else i+=s,r++;}return i&&t.push({type:"key",value:i}),t}function U(n){return n.includes("[*]")}function j(n){let t=G.get(n);return t||(t=U(n)?hn(n):En(n),G.set(n,t),t)}function En(n){if(!n.includes(".")&&!n.includes("["))return i=>i?.[n];let t=Q(n),o=t.length;if(o===2){let[i,s]=t,e=i.value,f=s.value;return u=>u?.[e]?.[f]}if(o===3){let[i,s,e]=t,f=i.value,u=s.value,a=e.value;return l=>l?.[f]?.[u]?.[a]}let r=t.map(i=>i.value);return i=>{let s=i;for(let e=0;e<o&&s!=null;e++)s=s[r[e]];return s}}function hn(n){let t=Q(n),o=[];for(let r=0;r<t.length;r++)t[r].type==="wildcard"&&o.push(r);return o.length===1?bn(t,o[0]):Cn(t,o)}function bn(n,t){let o=n.slice(0,t).map(e=>e.value),r=n.slice(t+1).map(e=>e.value),i=o.length,s=r.length;if(s===0){if(i===1){let e=o[0];return f=>f?.[e]}return e=>{let f=e;for(let u=0;u<i&&f!=null;u++)f=f[o[u]];return f}}if(s===1){let e=r[0];if(i===1){let f=o[0];return u=>{let a=u?.[f];if(Array.isArray(a))return a.map(l=>l?.[e])}}return f=>{let u=f;for(let a=0;a<i&&u!=null;a++)u=u[o[a]];if(Array.isArray(u))return u.map(a=>a?.[e])}}return e=>{let f=e;for(let u=0;u<i&&f!=null;u++)f=f[o[u]];if(Array.isArray(f))return f.map(u=>{let a=u;for(let l=0;l<s&&a!=null;l++)a=a[r[l]];return a})}}function Cn(n,t){let o=[],r=0;for(let s=0;s<t.length;s++){let e=t[s],f=s===t.length-1,u=n.slice(r,e).map(a=>a.value);u.length>0&&o.push({type:"access",keys:u}),o.push({type:f?"map":"flatMap",keys:[]}),r=e+1;}let i=n.slice(r).map(s=>s.value);return s=>{let e=s;for(let f of o){if(e==null)return;if(f.type==="access")for(let u of f.keys){if(e==null)return;e=e[u];}else if(f.type==="flatMap"){if(!Array.isArray(e))return;e=e.flatMap(u=>{let a=u;return Array.isArray(a)?a:[a]});}else if(f.type==="map"){if(!Array.isArray(e))return;i.length>0&&(e=e.map(u=>{let a=u;for(let l of i){if(a==null)return;a=a[l];}return a}));}}return e}}function Tn(n,t){return j(t)(n)}function W(n){let t=n.indexOf("[*]");return t===-1?n:n.slice(0,t)}function $n(){G.clear();}function An(){return G.size}function R(n){let t=new Set;return C(n,t),Array.from(t)}function C(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let i=0;i<n.length;i++)C(n[i],t);return}if(E(n)){t.add(W(n.$));return}if(S(n)){if(typeof n.$if=="string"){let i=n.$if.startsWith("!")?n.$if.slice(1):n.$if;t.add(W(i));}else C(n.$if,t);C(n.then,t),n.else!==void 0&&C(n.else,t);return}if(k(n)){for(let i=0;i<n.$pipe.length;i++)C(n.$pipe[i],t);return}if(w(n)){if(n.args)for(let i=0;i<n.args.length;i++)C(n.args[i],t);return}if(x(n)){C(n.body,t),n.params!==void 0&&C(n.params,t);return}if(h(n)){C(n.left,t),n.right!==void 0&&C(n.right,t);return}if(b(n)){for(let i=0;i<n.conditions.length;i++)C(n.conditions[i],t);return}let o=n,r=Object.keys(o);for(let i=0;i<r.length;i++)C(o[r[i]],t);}function Sn(n){return R(n).length>0}function wn(n){return R(n).length===0}function kn(n){return JSON.stringify(n)}function z(n,t={}){let o=t.scope??{},r=t.accessor,i=t.context??{},s=y(n,o,r,i),e=R(n),f=kn(n);return {fn:s,deps:e,hash:f}}function y(n,t,o,r){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let i=n.map(s=>y(s,t,o,r));return s=>i.map(e=>e(s))}if(E(n))return xn(n,o);if(S(n))return Fn(n,t,o,r);if(k(n))return Rn(n,t,o,r);if(w(n))return On(n,t,o,r);if(x(n))return Nn(n,t,o,r);if(h(n))return jn(n,t,o,r);if(b(n))return vn(n,t,o,r);if(B(n)){let i=n,s=Object.keys(i),e=s.map(f=>y(i[f],t,o,r));return f=>{let u={};for(let a=0;a<s.length;a++)u[s[a]]=e[a](f);return u}}return ()=>n}function Z(n,t){return t?o=>t(n,o):j(n)}function xn(n,t){return Z(n.$,t)}function Fn(n,t,o,r){let i;if(typeof n.$if=="string"){let f=n.$if.startsWith("!")?n.$if.slice(1):n.$if,u=Z(f,o);i=n.$if.startsWith("!")?l=>!u(l):l=>!!u(l);}else {let f=y(n.$if,t,o,r);i=u=>!!f(u);}let s=y(n.then,t,o,r),e=n.else!==void 0?y(n.else,t,o,r):()=>{};return f=>i(f)?s(f):e(f)}function Rn(n,t,o,r){let i=n.$pipe;if(i.length===0)return ()=>{};if(i.length===1)return y(i[0],t,o,r);let s=y(i[0],t,o,r),e=i.slice(1).map(u=>y(u,t,o,r)),f=e.length;if(f===1){let[u]=e;return a=>{let l=s(a),p=u(a);return typeof p=="function"?p(l):p}}if(f===2){let[u,a]=e;return l=>{let p=s(l),d=u(l);return p=typeof d=="function"?d(p):d,d=a(l),typeof d=="function"?d(p):d}}if(f===3){let[u,a,l]=e;return p=>{let d=s(p),g=u(p);return d=typeof g=="function"?g(d):g,g=a(p),d=typeof g=="function"?g(d):g,g=l(p),typeof g=="function"?g(d):g}}return u=>{let a=s(u);for(let l=0;l<f;l++){let p=e[l](u);a=typeof p=="function"?p(a):p;}return a}}function On(n,t,o,r){let i=n.$fn,s=n.args;if(s===void 0)return ()=>{let u=t[i];if(!u)throw new Error(`Function not found in scope: ${i}`);return u};let e=s.map(u=>y(u,t,o,r)),f=e.length;if(f===0)return ()=>{let u=t[i];if(!u)throw new Error(`Function not found in scope: ${i}`);return u()};if(f===1){let[u]=e;return a=>{let l=t[i];if(!l)throw new Error(`Function not found in scope: ${i}`);return l(u(a))}}if(f===2){let[u,a]=e;return l=>{let p=t[i];if(!p)throw new Error(`Function not found in scope: ${i}`);return p(u(l),a(l))}}if(f===3){let[u,a,l]=e;return p=>{let d=t[i];if(!d)throw new Error(`Function not found in scope: ${i}`);return d(u(p),a(p),l(p))}}return u=>{let a=t[i];if(!a)throw new Error(`Function not found in scope: ${i}`);return a(...e.map(l=>l(u)))}}function Nn(n,t,o,r){let i=n.$cb,s=y(n.body,t,o,r),e=n.params?y(n.params,t,o,r):void 0,f=u=>o?a=>o(a,u):a=>j(a)(u);return u=>{let a=r?.[i];if(!a)throw new Error(`Context function not found: ${i}`);let l=(g,F)=>s(g),p=f(u),d=e?e(u):void 0;return a(l,u,p,d)}}function jn(n,t,o,r){let i=y(n.left,t,o,r),s=n.right!==void 0?y(n.right,t,o,r):()=>{};switch(n.op){case "eq":return e=>i(e)===s(e);case "neq":return e=>i(e)!==s(e);case "gt":return e=>i(e)>s(e);case "gte":return e=>i(e)>=s(e);case "lt":return e=>i(e)<s(e);case "lte":return e=>i(e)<=s(e);case "in":return e=>{let f=s(e);return Array.isArray(f)&&f.includes(i(e))};case "notIn":return e=>{let f=s(e);return !Array.isArray(f)||!f.includes(i(e))};case "contains":return e=>{let f=i(e);return Array.isArray(f)&&f.includes(s(e))};case "notContains":return e=>{let f=i(e);return !Array.isArray(f)||!f.includes(s(e))};case "exists":return e=>i(e)!==void 0;case "notExists":return e=>i(e)===void 0;case "matches":return e=>{let f=i(e),u=s(e);return typeof f!="string"||typeof u!="string"?false:new RegExp(u).test(f)};case "notMatches":return e=>{let f=i(e),u=s(e);return typeof f!="string"||typeof u!="string"?true:!new RegExp(u).test(f)};case "startsWith":return e=>{let f=i(e),u=s(e);return typeof f=="string"&&typeof u=="string"&&f.startsWith(u)};case "endsWith":return e=>{let f=i(e),u=s(e);return typeof f=="string"&&typeof u=="string"&&f.endsWith(u)}}}function vn(n,t,o,r){let i=n.conditions.map(e=>y(e,t,o,r)),s=i.length;if(s===1)return e=>!!i[0](e);if(s===2){let[e,f]=i;return n.logic==="AND"?u=>!!e(u)&&!!f(u):u=>!!e(u)||!!f(u)}if(s===3){let[e,f,u]=i;return n.logic==="AND"?a=>!!e(a)&&!!f(a)&&!!u(a):a=>!!e(a)||!!f(a)||!!u(a)}return n.logic==="AND"?e=>{for(let f=0;f<s;f++)if(!i[f](e))return false;return true}:e=>{for(let f=0;f<s;f++)if(i[f](e))return true;return false}}function Gn(n,t,o={}){return z(n,o).fn(t)}var D=class{constructor(t=1e3){this.cache=new Map,this._maxSize=t;}get(t,o={}){let r=JSON.stringify(t),i=this.cache.get(r);if(i)return this.cache.delete(r),this.cache.set(r,i),i;let s=z(t,o);if(this.cache.size>=this._maxSize){let e=this.cache.keys().next().value;e&&this.cache.delete(e);}return this.cache.set(r,s),s}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 o=this.cache.keys().next().value;o&&this.cache.delete(o);}}},P=new D;function Wn(n,t={}){return P.get(n,t)}function J(n,t="root",o={}){let r=[];return T(n,t,r,o),{valid:r.length===0,errors:r}}function T(n,t,o,r){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let e=0;e<n.length;e++)T(n[e],`${t}[${e}]`,o,r);return}if(E(n)){(!n.$||typeof n.$!="string")&&o.push(`${t}: invalid reference, $ must be non-empty string`);return}if(S(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||o.push(`${t}.$if: empty path in string shorthand`):T(n.$if,`${t}.$if`,o,r),T(n.then,`${t}.then`,o,r),n.else!==void 0&&T(n.else,`${t}.else`,o,r);return}if(k(n)){if(!Array.isArray(n.$pipe)){o.push(`${t}.$pipe: must be an array`);return}if(n.$pipe.length===0){o.push(`${t}.$pipe: must have at least one element`);return}for(let e=0;e<n.$pipe.length;e++)T(n.$pipe[e],`${t}.$pipe[${e}]`,o,r);return}if(w(n)){if(!n.$fn||typeof n.$fn!="string"){o.push(`${t}: invalid function, $fn must be non-empty string`);return}if(r.scope&&!(n.$fn in r.scope)&&o.push(`${t}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))o.push(`${t}.args: must be an array`);else for(let e=0;e<n.args.length;e++)T(n.args[e],`${t}.args[${e}]`,o,r);return}if(x(n)){if(!n.$cb||typeof n.$cb!="string"){o.push(`${t}: invalid callback, $cb must be non-empty string`);return}r.context&&!(n.$cb in r.context)&&o.push(`${t}: context function "${n.$cb}" not found`),T(n.body,`${t}.body`,o,r),n.params!==void 0&&T(n.params,`${t}.params`,o,r);return}if(h(n)){v.has(n.op)||o.push(`${t}: invalid operator "${n.op}"`),T(n.left,`${t}.left`,o,r),n.right!==void 0&&T(n.right,`${t}.right`,o,r);return}if(b(n)){if(n.logic!=="AND"&&n.logic!=="OR"&&o.push(`${t}: invalid logic "${n.logic}", must be "AND" or "OR"`),!Array.isArray(n.conditions)){o.push(`${t}.conditions: must be an array`);return}for(let e=0;e<n.conditions.length;e++)T(n.conditions[e],`${t}.conditions[${e}]`,o,r);return}let i=n,s=Object.keys(i);for(let e=0;e<s.length;e++){let f=s[e];T(i[f],`${t}.${f}`,o,r);}}function zn(n,t={}){let o=J(n,"root",t);if(!o.valid)throw new Error(`Invalid expression: ${o.errors.join("; ")}`)}function Dn(n,t={}){return J(n,"root",t).valid}var sn={};mn(sn,{$:()=>nn,$cb:()=>rn,$cond:()=>on,$fn:()=>tn,$if:()=>_n,$pipe:()=>en,cb:()=>qn,cond:()=>Ln,fn:()=>In,pipe:()=>Vn,ref:()=>Mn});function nn(n){return {$:n}}var Mn=nn;function tn(n,t){return t===void 0||t.length===0?{$fn:n}:{$fn:n,args:t}}var In=tn;function _n(n,t,o){return o===void 0?{$if:n,then:t}:{$if:n,then:t,else:o}}function en(...n){return {$pipe:n}}var Vn=en;function on(n,t,o){return o===void 0?{left:n,op:t}:{left:n,op:t,right:o}}var Ln=on;function rn(n,t,o){return o===void 0?{$cb:n,body:t}:{$cb:n,body:t,params:o}}var qn=rn;var K="data",un="scope",Bn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function I(n,t={}){let{dataParam:o=K,scopeParam:r=un,noPrefixes:i=false,useAccessor:s=false,lexicalPrefix:e}=t;return m(n,o,r,i,s,e)}function m(n,t,o,r,i,s){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=>m(e,t,o,r,i,s)));if(E(n))return Jn(n.$,t,r,i,s);if(S(n))return Xn(n,t,o,r,i,s);if(k(n))return Un(n.$pipe,t,o,r,i,s);if(w(n))return Yn(n,t,o,r,i,s);if(x(n))return Qn(n,t,o,r,i,s);if(h(n))return Zn(n,t,o,r,i,s);if(b(n))return Pn(n,t,o,r,i,s);if(typeof n=="object"){let f=Object.entries(n).map(([u,a])=>omniAst.builders.property(omniAst.builders.identifier(u),m(a,t,o,r,i,s)));return omniAst.builders.objectExpression(f)}return omniAst.builders.literal(null)}var X="accessor";function Y(n,t){return t?n===t||n.startsWith(t+"."):false}function Jn(n,t,o,r,i){return r?Y(n,i)?O(n,t,true):omniAst.builders.callExpression(omniAst.builders.identifier(X),[omniAst.builders.literal(n),omniAst.builders.identifier(t)]):n.includes("[*]")?Kn(n,t,o):O(n,t,o)}function O(n,t,o){let r=M(n);if(r.length===0)return o?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(t);let i;if(o){let s=r[0];i=omniAst.builders.identifier(s.value);for(let e=1;e<r.length;e++){let f=r[e];f.type==="key"?i=omniAst.builders.memberExpression(i,omniAst.builders.identifier(f.value),false,true):i=omniAst.builders.memberExpression(i,omniAst.builders.literal(f.value),true,true);}}else {i=omniAst.builders.identifier(t);for(let s of r)s.type==="key"?i=omniAst.builders.memberExpression(i,omniAst.builders.identifier(s.value),false,true):i=omniAst.builders.memberExpression(i,omniAst.builders.literal(s.value),true,true);}return i}function Kn(n,t,o){let r=n.indexOf("[*]"),i=n.slice(0,r),s=n.slice(r+3),e;if(i?e=O(i,t,o):e=o?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(t),!s||s==="")return e;if(s.includes("[*]"))return cn(e,s);let f="_i",u=s.startsWith(".")?s.slice(1):s,a=omniAst.builders.identifier(f);if(u){let l=M(u);for(let p of l)p.type==="key"?a=omniAst.builders.memberExpression(a,omniAst.builders.identifier(p.value),false,true):a=omniAst.builders.memberExpression(a,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)],a)])}function cn(n,t){let o=t.indexOf("[*]"),r=t.slice(0,o),i=t.slice(o+3),s="_i",e=r.startsWith(".")?r.slice(1):r,f=omniAst.builders.identifier(s);if(e){let a=M(e);for(let l of a)l.type==="key"&&(f=omniAst.builders.memberExpression(f,omniAst.builders.identifier(l.value),false,true));}if(i.includes("[*]")){let a=cn(f,i);return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(s)],a)])}let u=i.startsWith(".")?i.slice(1):i;if(u){let a=M(u);for(let l of a)l.type==="key"&&(f=omniAst.builders.memberExpression(f,omniAst.builders.identifier(l.value),false,true));}return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(s)],f)])}function Xn(n,t,o,r,i,s){let e;if(typeof n.$if=="string"){let a=n.$if.startsWith("!"),l=a?n.$if.slice(1):n.$if,p;i?Y(l,s)?p=O(l,t,true):p=omniAst.builders.callExpression(omniAst.builders.identifier(X),[omniAst.builders.literal(l),omniAst.builders.identifier(t)]):p=O(l,t,r),e=a?omniAst.builders.unaryExpression("!",p):p;}else e=m(n.$if,t,o,r,i,s);let f=m(n.then,t,o,r,i,s),u=n.else!==void 0?m(n.else,t,o,r,i,s):omniAst.builders.identifier("undefined");return omniAst.builders.conditionalExpression(e,f,u)}function Yn(n,t,o,r,i,s){let e=r?omniAst.builders.identifier(n.$fn):omniAst.builders.memberExpression(omniAst.builders.identifier(o),omniAst.builders.identifier(n.$fn),false,false);if(n.args===void 0)return e;let f=n.args.map(u=>m(u,t,o,r,i,s));return omniAst.builders.callExpression(e,f)}var Hn="context";function Qn(n,t,o,r,i,s){let e=r?omniAst.builders.identifier(n.$cb):omniAst.builders.memberExpression(omniAst.builders.identifier(Hn),omniAst.builders.identifier(n.$cb),false,false),f=m(n.body,t,o,r,i,s),a=[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(t),omniAst.builders.identifier("get")],f),omniAst.builders.identifier(t),omniAst.builders.identifier("get")];if(n.params!==void 0){let l=m(n.params,t,o,r,i,s);a.push(l);}return omniAst.builders.callExpression(e,a)}function Un(n,t,o,r,i,s){if(n.length===0)return omniAst.builders.identifier("undefined");if(n.length===1)return m(n[0],t,o,r,i,s);let e=m(n[0],t,o,r,i,s);for(let f=1;f<n.length;f++){let u=m(n[f],t,o,r,i,s);e=omniAst.builders.callExpression(u,[e]);}return e}function fn(n,t,o,r,i,s){if(E(n)){let e=n.$;return i?Y(e,s)?O(e,t,true):omniAst.builders.callExpression(omniAst.builders.identifier(X),[omniAst.builders.literal(e),omniAst.builders.identifier(t)]):O(e,t,r)}return m(n,t,o,r,i,s)}function Zn(n,t,o,r,i,s){let e=fn(n.left,t,o,r,i,s),f=n.right!==void 0?fn(n.right,t,o,r,i,s):omniAst.builders.literal(null),u=Bn[n.op];if(u)return omniAst.builders.binaryExpression(u,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 Pn(n,t,o,r,i,s){let{logic:e,conditions:f}=n,u=e==="AND"?"&&":"||";if(f.length===0)return omniAst.builders.literal(e==="AND");if(f.length===1)return m(f[0],t,o,r,i,s);let a=m(f[0],t,o,r,i,s);for(let l=1;l<f.length;l++){let p=m(f[l],t,o,r,i,s);a=omniAst.builders.logicalExpression(u,a,p);}return a}function M(n){let t=[],o=n.length,r=0,i="";for(;r<o;){let s=n[r];if(s===".")i&&(t.push({type:"key",value:i}),i=""),r++;else if(s==="["){i&&(t.push({type:"key",value:i}),i=""),r++;let e=r;for(;r<o&&n[r]!=="]";)r++;let f=n.slice(e,r);if(r++,f!=="*"){let u=parseInt(f,10);t.push({type:"index",value:isNaN(u)?f:u});}}else i+=s,r++;}return i&&t.push({type:"key",value:i}),t}function an(n,t=[K]){return omniAst.builders.arrowFunctionExpression(t.map(o=>omniAst.builders.identifier(o)),n)}function _(n){let t=new Set;return $(n,t),t}function $(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r of n)$(r,t);return}if(E(n))return;if(S(n)){$(n.$if,t),$(n.then,t),n.else!==void 0&&$(n.else,t);return}if(k(n)){for(let r of n.$pipe)$(r,t);return}if(w(n)){if(t.add(n.$fn),n.args)for(let r of n.args)$(r,t);return}if(x(n)){$(n.body,t),n.params!==void 0&&$(n.params,t);return}if(h(n)){n.left!==void 0&&typeof n.left=="object"&&$(n.left,t),n.right!==void 0&&typeof n.right=="object"&&$(n.right,t);return}if(b(n)){for(let r of n.conditions)$(r,t);return}let o=n;for(let r of Object.keys(o))$(o[r],t);}function V(n){let t=new Set;return A(n,t),t}function A(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r of n)A(r,t);return}if(E(n))return;if(S(n)){A(n.$if,t),A(n.then,t),n.else!==void 0&&A(n.else,t);return}if(k(n)){for(let r of n.$pipe)A(r,t);return}if(w(n)){if(n.args)for(let r of n.args)A(r,t);return}if(x(n)){t.add(n.$cb),A(n.body,t),n.params!==void 0&&A(n.params,t);return}if(h(n)){n.left!==void 0&&typeof n.left=="object"&&A(n.left,t),n.right!==void 0&&typeof n.right=="object"&&A(n.right,t);return}if(b(n)){for(let r of n.conditions)A(r,t);return}let o=n;for(let r of Object.keys(o))A(o[r],t);}function L(n){let t=new Set;for(let o of n){let r=o.indexOf("."),i=o.indexOf("["),s=o.length;r!==-1&&(s=Math.min(s,r)),i!==-1&&(s=Math.min(s,i));let e=o.slice(0,s);e&&t.add(e);}return t}function tt(n){return JSON.stringify(n)}function et(n,t,o,r,i,s){let e=I(n,{noPrefixes:true,useAccessor:i,lexicalPrefix:s}),f=omniAst.generate(e),u="";i?s&&(u=`const{${s}}=data??{};`):t.size>0&&(u=`const{${[...t].join(",")}}=data??{};`);let a=i?new Set([...o,"accessor"]):o,l=a.size>0?`const{${[...a].join(",")}}=scope;`:"",p=r.size>0?`const{${[...r].join(",")}}=context;`:"",d=r.size>0,g="";d&&(i?g="const get=(path)=>accessor(path,data);":g="const get=(path)=>path.split('.').reduce((o,k)=>o?.[k],data);");let F=a.size>0,N;if(F||d){let pn=d?"scope,context":"scope",dn=`${u}${g}return ${f}`;N=`(function(${pn}){${l}${p}return function(data){${dn}}})`;}else N=`(function(){return function(data){${u}return ${f}}})`;return N}function H(n,t={}){let{scope:o={},context:r={},returnCode:i=false,useAccessor:s=false,lexicalPrefix:e}=t,f=R(n),u=L(f),a=_(n),l=V(n),p=tt(n),d=et(n,u,a,l,s,e);if(i)return {code:d,deps:f,hash:p,dataRoots:[...u],scopeFns:[...a],contextFns:[...l]};let g;try{let F=l.size>0,N=new Function(`return ${d}`)();g=F?N(o,r):N(o);}catch(F){throw new Error(`AST compilation failed. If this is due to CSP, use the standard compile() function instead. Error: ${F instanceof Error?F.message:String(F)}`)}return {fn:g,deps:f,hash:p}}function ln(n,t,o={}){let{fn:r}=H(n,o);return r(t)}function it(n,t){return q(n,t)}function q(n,t){if(n===null)return null;if(typeof n!="object")return n;if(Array.isArray(n))return n.map(s=>q(s,t));let o=n,r=Object.keys(o);for(let s of r)if(s in t){let e=t[s](o);if(typeof e=="object"&&e!==null&&s in e)throw new Error(`Transform "${s}" returned object with same key \u2014 infinite loop`);return q(e,t)}let i={};for(let s of r)i[s]=q(o[s],t);return i}var vt="2.0.0";exports.ExpressionCache=D;exports.VERSION=vt;exports.assertValid=zn;exports.builders=sn;exports.cache=P;exports.cached=Wn;exports.clearPathCache=$n;exports.compile=z;exports.compileAST=H;exports.compilePath=j;exports.dslToAST=I;exports.evaluate=Gn;exports.evaluateAST=ln;exports.extractContextFns=V;exports.extractDataRoots=L;exports.extractDeps=R;exports.extractScopeFns=_;exports.get=Tn;exports.getPathCacheSize=An;exports.hasDeps=Sn;exports.hasWildcard=U;exports.isCb=x;exports.isCondition=h;exports.isConditionExpr=yn;exports.isConditionGroup=b;exports.isConditional=S;exports.isFn=w;exports.isLiteral=B;exports.isPipe=k;exports.isPure=wn;exports.isRef=E;exports.isValid=Dn;exports.normalize=it;exports.normalizePath=W;exports.validate=J;exports.wrapInFunction=an;
package/dist/index.d.cts CHANGED
@@ -44,6 +44,17 @@ interface FnExpr {
44
44
  interface PipeExpr {
45
45
  $pipe: Expression[];
46
46
  }
47
+ /**
48
+ * Callback expression - HOC de continuidade
49
+ * Executa body dentro de um context function (tryCatch, transaction, etc.)
50
+ * @example { $cb: "tryCatch", body: { $fn: "query" } }
51
+ * @example { $cb: "transaction", params: { isolation: "serializable" }, body: { $fn: "query" } }
52
+ */
53
+ interface CbExpr {
54
+ $cb: string;
55
+ body: Expression;
56
+ params?: Expression;
57
+ }
47
58
  /**
48
59
  * Literal values (primitives, arrays, plain objects)
49
60
  */
@@ -75,7 +86,7 @@ type ConditionExpr = Condition | ConditionGroup;
75
86
  /**
76
87
  * Union of all expression types
77
88
  */
78
- type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | ConditionExpr;
89
+ type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | CbExpr | ConditionExpr;
79
90
  /**
80
91
  * Compiled expression function
81
92
  */
@@ -122,6 +133,50 @@ interface ValidationResult {
122
133
  * @example { add, subtract, multiply, filter, map, sum }
123
134
  */
124
135
  type Scope = Record<string, (...args: any[]) => any>;
136
+ /**
137
+ * Path getter function for context callbacks
138
+ */
139
+ type PathGetterFn = (path: string) => unknown;
140
+ /**
141
+ * Context function - HOC que controla execução do body.
142
+ * Recebe o body como callback e decide quando/se executá-lo.
143
+ *
144
+ * @param cb - Body compilado como callback (recebe data e get)
145
+ * @param data - Dados do runtime
146
+ * @param get - Resolver de paths (accessor)
147
+ * @param params - Parâmetros extras para o context (opcional)
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * const tryCatch: ContextFn = (cb, data, get, params) => {
152
+ * try {
153
+ * return cb(data, get);
154
+ * } catch (e) {
155
+ * return params?.fallback ?? null;
156
+ * }
157
+ * };
158
+ *
159
+ * const transaction: ContextFn = (cb, data, get, params) => {
160
+ * const tx = db.beginTransaction(params);
161
+ * try {
162
+ * const result = cb({ ...data, tx }, get);
163
+ * tx.commit();
164
+ * return result;
165
+ * } catch (e) {
166
+ * tx.rollback();
167
+ * throw e;
168
+ * }
169
+ * };
170
+ * ```
171
+ */
172
+ type ContextFn<T = any, R = any> = (cb: (data: T, get: PathGetterFn) => R, data: T, get: PathGetterFn, params?: unknown) => R;
173
+ /**
174
+ * Context registry - HOC functions available to $cb expressions.
175
+ * Separate from scope because context functions have different signature.
176
+ *
177
+ * @example { tryCatch, transaction, withRetry }
178
+ */
179
+ type Context = Record<string, ContextFn>;
125
180
  /**
126
181
  * Options for compilation
127
182
  */
@@ -137,6 +192,18 @@ interface CompileOptions<T = unknown> {
137
192
  * compile(expr, { accessor: (path, ctx) => ctx.get(path) })
138
193
  */
139
194
  accessor?: AccessorFn<T>;
195
+ /**
196
+ * Context functions available to $cb expressions.
197
+ * HOC functions that control body execution (tryCatch, transaction, etc.).
198
+ *
199
+ * @example
200
+ * compile(expr, {
201
+ * context: {
202
+ * tryCatch: (cb, data, get) => { try { return cb(data, get); } catch { return null; } }
203
+ * }
204
+ * })
205
+ */
206
+ context?: Context;
140
207
  }
141
208
  /**
142
209
  * Check if value is a reference expression
@@ -154,6 +221,10 @@ declare const isFn: (v: unknown) => v is FnExpr;
154
221
  * Check if value is a pipe expression
155
222
  */
156
223
  declare const isPipe: (v: unknown) => v is PipeExpr;
224
+ /**
225
+ * Check if value is a callback expression
226
+ */
227
+ declare const isCb: (v: unknown) => v is CbExpr;
157
228
  /**
158
229
  * Check if value is a condition expression
159
230
  *
@@ -359,6 +430,8 @@ declare function cached<T = unknown, R = unknown>(expr: Expression, options?: Co
359
430
  interface ValidateOptions {
360
431
  /** Scope to validate function names against (optional) */
361
432
  scope?: Scope;
433
+ /** Context to validate $cb function names against (optional) */
434
+ context?: Context;
362
435
  }
363
436
  /**
364
437
  * Validate expression structure
@@ -481,18 +554,40 @@ declare function $cond(left: Expression, op: ConditionOp, right?: Expression): C
481
554
  * Alias for $cond (condition builder)
482
555
  */
483
556
  declare const cond: typeof $cond;
557
+ /**
558
+ * Create a callback expression (HOC de continuidade).
559
+ *
560
+ * @param name - Context function name (from context)
561
+ * @param body - Expression to execute inside the context
562
+ * @param params - Optional parameters for the context function
563
+ * @returns CbExpr
564
+ *
565
+ * @example
566
+ * $cb("tryCatch", $fn("query"))
567
+ * // { $cb: "tryCatch", body: { $fn: "query" } }
568
+ *
569
+ * $cb("transaction", $fn("saveUser"), { isolation: "serializable" })
570
+ * // { $cb: "transaction", body: {...}, params: {...} }
571
+ */
572
+ declare function $cb(name: string, body: Expression, params?: Expression): CbExpr;
573
+ /**
574
+ * Alias for $cb (callback builder)
575
+ */
576
+ declare const cb: typeof $cb;
484
577
 
485
578
  declare const builders_$: typeof $;
579
+ declare const builders_$cb: typeof $cb;
486
580
  declare const builders_$cond: typeof $cond;
487
581
  declare const builders_$fn: typeof $fn;
488
582
  declare const builders_$if: typeof $if;
489
583
  declare const builders_$pipe: typeof $pipe;
584
+ declare const builders_cb: typeof cb;
490
585
  declare const builders_cond: typeof cond;
491
586
  declare const builders_fn: typeof fn;
492
587
  declare const builders_pipe: typeof pipe;
493
588
  declare const builders_ref: typeof ref;
494
589
  declare namespace builders {
495
- export { builders_$ as $, builders_$cond as $cond, builders_$fn as $fn, builders_$if as $if, builders_$pipe as $pipe, builders_cond as cond, builders_fn as fn, builders_pipe as pipe, builders_ref as ref };
590
+ export { builders_$ as $, builders_$cb as $cb, builders_$cond as $cond, builders_$fn as $fn, builders_$if as $if, builders_$pipe as $pipe, builders_cb as cb, builders_cond as cond, builders_fn as fn, builders_pipe as pipe, builders_ref as ref };
496
591
  }
497
592
 
498
593
  /**
@@ -590,6 +685,19 @@ declare function wrapInFunction(bodyAst: ASTNode, params?: string[]): ASTNode;
590
685
  * ```
591
686
  */
592
687
  declare function extractScopeFns(expr: Expression): Set<string>;
688
+ /**
689
+ * Extract all context function names used in an expression
690
+ *
691
+ * @param expr - DSL expression to analyze
692
+ * @returns Set of context function names used
693
+ *
694
+ * @example
695
+ * ```ts
696
+ * extractContextFns({ $cb: "tryCatch", body: { $fn: "query" } })
697
+ * // Set { "tryCatch" }
698
+ * ```
699
+ */
700
+ declare function extractContextFns(expr: Expression): Set<string>;
593
701
  /**
594
702
  * Extract root-level data dependencies from paths
595
703
  *
@@ -618,6 +726,8 @@ declare function extractDataRoots(deps: string[]): Set<string>;
618
726
  interface CompileASTOptions {
619
727
  /** Scope with functions available to the expression */
620
728
  scope?: Scope;
729
+ /** Context with HOC functions available to $cb expressions */
730
+ context?: Context;
621
731
  /** Return generated code instead of function (for debugging) */
622
732
  returnCode?: boolean;
623
733
  /**
@@ -639,6 +749,7 @@ interface CompileASTCodeResult {
639
749
  hash: string;
640
750
  dataRoots: string[];
641
751
  scopeFns: string[];
752
+ contextFns: string[];
642
753
  }
643
754
  /**
644
755
  * Compile DSL expression to optimized function using AST generation
@@ -781,4 +892,4 @@ declare function normalize(expr: unknown, transforms: Transforms): Expression;
781
892
  */
782
893
  declare const VERSION = "2.0.0";
783
894
 
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 };
895
+ export { type AccessorFn, type CbExpr, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type Context, type ContextFn, type Expression, ExpressionCache, type FnExpr, type Literal, type PathGetter, type PathGetterFn, 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, extractContextFns, extractDataRoots, extractDeps, extractScopeFns, get, getPathCacheSize, hasDeps, hasWildcard, isCb, isCondition, isConditionExpr, isConditionGroup, isConditional, isFn, isLiteral, isPipe, isPure, isRef, isValid, normalize, normalizePath, validate, wrapInFunction };
package/dist/index.d.ts CHANGED
@@ -44,6 +44,17 @@ interface FnExpr {
44
44
  interface PipeExpr {
45
45
  $pipe: Expression[];
46
46
  }
47
+ /**
48
+ * Callback expression - HOC de continuidade
49
+ * Executa body dentro de um context function (tryCatch, transaction, etc.)
50
+ * @example { $cb: "tryCatch", body: { $fn: "query" } }
51
+ * @example { $cb: "transaction", params: { isolation: "serializable" }, body: { $fn: "query" } }
52
+ */
53
+ interface CbExpr {
54
+ $cb: string;
55
+ body: Expression;
56
+ params?: Expression;
57
+ }
47
58
  /**
48
59
  * Literal values (primitives, arrays, plain objects)
49
60
  */
@@ -75,7 +86,7 @@ type ConditionExpr = Condition | ConditionGroup;
75
86
  /**
76
87
  * Union of all expression types
77
88
  */
78
- type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | ConditionExpr;
89
+ type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | CbExpr | ConditionExpr;
79
90
  /**
80
91
  * Compiled expression function
81
92
  */
@@ -122,6 +133,50 @@ interface ValidationResult {
122
133
  * @example { add, subtract, multiply, filter, map, sum }
123
134
  */
124
135
  type Scope = Record<string, (...args: any[]) => any>;
136
+ /**
137
+ * Path getter function for context callbacks
138
+ */
139
+ type PathGetterFn = (path: string) => unknown;
140
+ /**
141
+ * Context function - HOC que controla execução do body.
142
+ * Recebe o body como callback e decide quando/se executá-lo.
143
+ *
144
+ * @param cb - Body compilado como callback (recebe data e get)
145
+ * @param data - Dados do runtime
146
+ * @param get - Resolver de paths (accessor)
147
+ * @param params - Parâmetros extras para o context (opcional)
148
+ *
149
+ * @example
150
+ * ```ts
151
+ * const tryCatch: ContextFn = (cb, data, get, params) => {
152
+ * try {
153
+ * return cb(data, get);
154
+ * } catch (e) {
155
+ * return params?.fallback ?? null;
156
+ * }
157
+ * };
158
+ *
159
+ * const transaction: ContextFn = (cb, data, get, params) => {
160
+ * const tx = db.beginTransaction(params);
161
+ * try {
162
+ * const result = cb({ ...data, tx }, get);
163
+ * tx.commit();
164
+ * return result;
165
+ * } catch (e) {
166
+ * tx.rollback();
167
+ * throw e;
168
+ * }
169
+ * };
170
+ * ```
171
+ */
172
+ type ContextFn<T = any, R = any> = (cb: (data: T, get: PathGetterFn) => R, data: T, get: PathGetterFn, params?: unknown) => R;
173
+ /**
174
+ * Context registry - HOC functions available to $cb expressions.
175
+ * Separate from scope because context functions have different signature.
176
+ *
177
+ * @example { tryCatch, transaction, withRetry }
178
+ */
179
+ type Context = Record<string, ContextFn>;
125
180
  /**
126
181
  * Options for compilation
127
182
  */
@@ -137,6 +192,18 @@ interface CompileOptions<T = unknown> {
137
192
  * compile(expr, { accessor: (path, ctx) => ctx.get(path) })
138
193
  */
139
194
  accessor?: AccessorFn<T>;
195
+ /**
196
+ * Context functions available to $cb expressions.
197
+ * HOC functions that control body execution (tryCatch, transaction, etc.).
198
+ *
199
+ * @example
200
+ * compile(expr, {
201
+ * context: {
202
+ * tryCatch: (cb, data, get) => { try { return cb(data, get); } catch { return null; } }
203
+ * }
204
+ * })
205
+ */
206
+ context?: Context;
140
207
  }
141
208
  /**
142
209
  * Check if value is a reference expression
@@ -154,6 +221,10 @@ declare const isFn: (v: unknown) => v is FnExpr;
154
221
  * Check if value is a pipe expression
155
222
  */
156
223
  declare const isPipe: (v: unknown) => v is PipeExpr;
224
+ /**
225
+ * Check if value is a callback expression
226
+ */
227
+ declare const isCb: (v: unknown) => v is CbExpr;
157
228
  /**
158
229
  * Check if value is a condition expression
159
230
  *
@@ -359,6 +430,8 @@ declare function cached<T = unknown, R = unknown>(expr: Expression, options?: Co
359
430
  interface ValidateOptions {
360
431
  /** Scope to validate function names against (optional) */
361
432
  scope?: Scope;
433
+ /** Context to validate $cb function names against (optional) */
434
+ context?: Context;
362
435
  }
363
436
  /**
364
437
  * Validate expression structure
@@ -481,18 +554,40 @@ declare function $cond(left: Expression, op: ConditionOp, right?: Expression): C
481
554
  * Alias for $cond (condition builder)
482
555
  */
483
556
  declare const cond: typeof $cond;
557
+ /**
558
+ * Create a callback expression (HOC de continuidade).
559
+ *
560
+ * @param name - Context function name (from context)
561
+ * @param body - Expression to execute inside the context
562
+ * @param params - Optional parameters for the context function
563
+ * @returns CbExpr
564
+ *
565
+ * @example
566
+ * $cb("tryCatch", $fn("query"))
567
+ * // { $cb: "tryCatch", body: { $fn: "query" } }
568
+ *
569
+ * $cb("transaction", $fn("saveUser"), { isolation: "serializable" })
570
+ * // { $cb: "transaction", body: {...}, params: {...} }
571
+ */
572
+ declare function $cb(name: string, body: Expression, params?: Expression): CbExpr;
573
+ /**
574
+ * Alias for $cb (callback builder)
575
+ */
576
+ declare const cb: typeof $cb;
484
577
 
485
578
  declare const builders_$: typeof $;
579
+ declare const builders_$cb: typeof $cb;
486
580
  declare const builders_$cond: typeof $cond;
487
581
  declare const builders_$fn: typeof $fn;
488
582
  declare const builders_$if: typeof $if;
489
583
  declare const builders_$pipe: typeof $pipe;
584
+ declare const builders_cb: typeof cb;
490
585
  declare const builders_cond: typeof cond;
491
586
  declare const builders_fn: typeof fn;
492
587
  declare const builders_pipe: typeof pipe;
493
588
  declare const builders_ref: typeof ref;
494
589
  declare namespace builders {
495
- export { builders_$ as $, builders_$cond as $cond, builders_$fn as $fn, builders_$if as $if, builders_$pipe as $pipe, builders_cond as cond, builders_fn as fn, builders_pipe as pipe, builders_ref as ref };
590
+ export { builders_$ as $, builders_$cb as $cb, builders_$cond as $cond, builders_$fn as $fn, builders_$if as $if, builders_$pipe as $pipe, builders_cb as cb, builders_cond as cond, builders_fn as fn, builders_pipe as pipe, builders_ref as ref };
496
591
  }
497
592
 
498
593
  /**
@@ -590,6 +685,19 @@ declare function wrapInFunction(bodyAst: ASTNode, params?: string[]): ASTNode;
590
685
  * ```
591
686
  */
592
687
  declare function extractScopeFns(expr: Expression): Set<string>;
688
+ /**
689
+ * Extract all context function names used in an expression
690
+ *
691
+ * @param expr - DSL expression to analyze
692
+ * @returns Set of context function names used
693
+ *
694
+ * @example
695
+ * ```ts
696
+ * extractContextFns({ $cb: "tryCatch", body: { $fn: "query" } })
697
+ * // Set { "tryCatch" }
698
+ * ```
699
+ */
700
+ declare function extractContextFns(expr: Expression): Set<string>;
593
701
  /**
594
702
  * Extract root-level data dependencies from paths
595
703
  *
@@ -618,6 +726,8 @@ declare function extractDataRoots(deps: string[]): Set<string>;
618
726
  interface CompileASTOptions {
619
727
  /** Scope with functions available to the expression */
620
728
  scope?: Scope;
729
+ /** Context with HOC functions available to $cb expressions */
730
+ context?: Context;
621
731
  /** Return generated code instead of function (for debugging) */
622
732
  returnCode?: boolean;
623
733
  /**
@@ -639,6 +749,7 @@ interface CompileASTCodeResult {
639
749
  hash: string;
640
750
  dataRoots: string[];
641
751
  scopeFns: string[];
752
+ contextFns: string[];
642
753
  }
643
754
  /**
644
755
  * Compile DSL expression to optimized function using AST generation
@@ -781,4 +892,4 @@ declare function normalize(expr: unknown, transforms: Transforms): Expression;
781
892
  */
782
893
  declare const VERSION = "2.0.0";
783
894
 
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 };
895
+ export { type AccessorFn, type CbExpr, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type Context, type ContextFn, type Expression, ExpressionCache, type FnExpr, type Literal, type PathGetter, type PathGetterFn, 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, extractContextFns, extractDataRoots, extractDeps, extractScopeFns, get, getPathCacheSize, hasDeps, hasWildcard, isCb, isCondition, isConditionExpr, isConditionGroup, isConditional, isFn, isLiteral, isPipe, isPure, isRef, isValid, normalize, normalizePath, validate, wrapInFunction };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import {builders,generate}from'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 builders.literal(null);if(typeof n=="string")return builders.literal(n);if(typeof n=="number")return builders.literal(n);if(typeof n=="boolean")return builders.literal(n);if(Array.isArray(n))return 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])=>builders.property(builders.identifier(l),g(c,t,s,i,r,o)));return builders.objectExpression(f)}return 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):builders.callExpression(builders.identifier(_),[builders.literal(n),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?builders.identifier("undefined"):builders.identifier(t);let r;if(s){let o=i[0];r=builders.identifier(o.value);for(let e=1;e<i.length;e++){let f=i[e];f.type==="key"?r=builders.memberExpression(r,builders.identifier(f.value),false,true):r=builders.memberExpression(r,builders.literal(f.value),true,true);}}else {r=builders.identifier(t);for(let o of i)o.type==="key"?r=builders.memberExpression(r,builders.identifier(o.value),false,true):r=builders.memberExpression(r,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?builders.identifier("undefined"):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=builders.identifier(f);if(l){let a=v(l);for(let p of a)p.type==="key"?c=builders.memberExpression(c,builders.identifier(p.value),false,true):c=builders.memberExpression(c,builders.literal(p.value),true,true);}return builders.callExpression(builders.memberExpression(e,builders.identifier("map"),false,true),[builders.arrowFunctionExpression([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=builders.identifier(o);if(e){let c=v(e);for(let a of c)a.type==="key"&&(f=builders.memberExpression(f,builders.identifier(a.value),false,true));}if(r.includes("[*]")){let c=tn(f,r);return builders.callExpression(builders.memberExpression(n,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([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=builders.memberExpression(f,builders.identifier(a.value),false,true));}return builders.callExpression(builders.memberExpression(n,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([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=builders.callExpression(builders.identifier(_),[builders.literal(a),builders.identifier(t)]):p=k(a,t,i),e=c?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):builders.identifier("undefined");return builders.conditionalExpression(e,f,l)}function zn(n,t,s,i,r,o){let e=i?builders.identifier(n.$fn):builders.memberExpression(builders.identifier(s),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 builders.callExpression(e,f)}function In(n,t,s,i,r,o){if(n.length===0)return 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=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):builders.callExpression(builders.identifier(_),[builders.literal(e),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):builders.literal(null),l=vn[n.op];if(l)return builders.binaryExpression(l,e,f);switch(n.op){case "in":return builders.callExpression(builders.memberExpression(f,builders.identifier("includes")),[e]);case "notIn":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(f,builders.identifier("includes")),[e]));case "contains":return builders.callExpression(builders.memberExpression(e,builders.identifier("includes"),false,true),[f]);case "notContains":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(e,builders.identifier("includes"),false,true),[f]));case "exists":return builders.binaryExpression("!=",e,builders.literal(null));case "notExists":return builders.binaryExpression("==",e,builders.literal(null));case "matches":return builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[f]),builders.identifier("test")),[e]);case "notMatches":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[f]),builders.identifier("test")),[e]));case "startsWith":return builders.callExpression(builders.memberExpression(e,builders.identifier("startsWith"),false,true),[f]);case "endsWith":return builders.callExpression(builders.memberExpression(e,builders.identifier("endsWith"),false,true),[f]);default:return 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 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=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 builders.arrowFunctionExpression(t.map(s=>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=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";export{j as ExpressionCache,bt as VERSION,kn as assertValid,X as builders,P as cache,wn as cached,dn as clearPathCache,N as compile,q as compileAST,O as compilePath,G as dslToAST,Sn as evaluate,on as evaluateAST,D as extractDataRoots,w as extractDeps,W as extractScopeFns,pn as get,gn as getPathCacheSize,mn as hasDeps,B as hasWildcard,E as isCondition,fn as isConditionExpr,h as isConditionGroup,T as isConditional,b as isFn,I as isLiteral,C as isPipe,yn as isPure,y as isRef,xn as isValid,Jn as normalize,F as normalizePath,M as validate,en as wrapInFunction};
1
+ import {builders,generate}from'omni-ast';var gn=Object.defineProperty;var mn=(n,t)=>{for(var o in t)gn(n,o,{get:t[o],enumerable:true});};var E=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,S=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,w=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),x=n=>n!==null&&typeof n=="object"&&"$cb"in n&&typeof n.$cb=="string"&&"body"in n,v=new Set(["eq","neq","gt","gte","lt","lte","in","notIn","contains","notContains","exists","notExists","matches","notMatches","startsWith","endsWith"]),h=n=>n!==null&&typeof n=="object"&&"left"in n&&"op"in n&&v.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),b=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,yn=n=>h(n)||b(n),B=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 o=n,r="left"in o&&"op"in o&&v.has(o.op);return !("$"in o)&&!("$if"in o)&&!("$fn"in o)&&!("$pipe"in o)&&!("$cb"in o)&&!r&&!("logic"in o)}return false};var G=new Map;function Q(n){let t=[],o=n.length,r=0,i="";for(;r<o;){let s=n[r];if(s===".")i&&(t.push({type:"key",value:i}),i=""),r++;else if(s==="["){i&&(t.push({type:"key",value:i}),i=""),r++;let e=r;for(;r<o&&n[r]!=="]";)r++;let f=n.slice(e,r);if(r++,f==="*")t.push({type:"wildcard",value:"*"});else {let u=parseInt(f,10);t.push({type:"index",value:isNaN(u)?f:u});}}else i+=s,r++;}return i&&t.push({type:"key",value:i}),t}function U(n){return n.includes("[*]")}function j(n){let t=G.get(n);return t||(t=U(n)?hn(n):En(n),G.set(n,t),t)}function En(n){if(!n.includes(".")&&!n.includes("["))return i=>i?.[n];let t=Q(n),o=t.length;if(o===2){let[i,s]=t,e=i.value,f=s.value;return u=>u?.[e]?.[f]}if(o===3){let[i,s,e]=t,f=i.value,u=s.value,a=e.value;return l=>l?.[f]?.[u]?.[a]}let r=t.map(i=>i.value);return i=>{let s=i;for(let e=0;e<o&&s!=null;e++)s=s[r[e]];return s}}function hn(n){let t=Q(n),o=[];for(let r=0;r<t.length;r++)t[r].type==="wildcard"&&o.push(r);return o.length===1?bn(t,o[0]):Cn(t,o)}function bn(n,t){let o=n.slice(0,t).map(e=>e.value),r=n.slice(t+1).map(e=>e.value),i=o.length,s=r.length;if(s===0){if(i===1){let e=o[0];return f=>f?.[e]}return e=>{let f=e;for(let u=0;u<i&&f!=null;u++)f=f[o[u]];return f}}if(s===1){let e=r[0];if(i===1){let f=o[0];return u=>{let a=u?.[f];if(Array.isArray(a))return a.map(l=>l?.[e])}}return f=>{let u=f;for(let a=0;a<i&&u!=null;a++)u=u[o[a]];if(Array.isArray(u))return u.map(a=>a?.[e])}}return e=>{let f=e;for(let u=0;u<i&&f!=null;u++)f=f[o[u]];if(Array.isArray(f))return f.map(u=>{let a=u;for(let l=0;l<s&&a!=null;l++)a=a[r[l]];return a})}}function Cn(n,t){let o=[],r=0;for(let s=0;s<t.length;s++){let e=t[s],f=s===t.length-1,u=n.slice(r,e).map(a=>a.value);u.length>0&&o.push({type:"access",keys:u}),o.push({type:f?"map":"flatMap",keys:[]}),r=e+1;}let i=n.slice(r).map(s=>s.value);return s=>{let e=s;for(let f of o){if(e==null)return;if(f.type==="access")for(let u of f.keys){if(e==null)return;e=e[u];}else if(f.type==="flatMap"){if(!Array.isArray(e))return;e=e.flatMap(u=>{let a=u;return Array.isArray(a)?a:[a]});}else if(f.type==="map"){if(!Array.isArray(e))return;i.length>0&&(e=e.map(u=>{let a=u;for(let l of i){if(a==null)return;a=a[l];}return a}));}}return e}}function Tn(n,t){return j(t)(n)}function W(n){let t=n.indexOf("[*]");return t===-1?n:n.slice(0,t)}function $n(){G.clear();}function An(){return G.size}function R(n){let t=new Set;return C(n,t),Array.from(t)}function C(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let i=0;i<n.length;i++)C(n[i],t);return}if(E(n)){t.add(W(n.$));return}if(S(n)){if(typeof n.$if=="string"){let i=n.$if.startsWith("!")?n.$if.slice(1):n.$if;t.add(W(i));}else C(n.$if,t);C(n.then,t),n.else!==void 0&&C(n.else,t);return}if(k(n)){for(let i=0;i<n.$pipe.length;i++)C(n.$pipe[i],t);return}if(w(n)){if(n.args)for(let i=0;i<n.args.length;i++)C(n.args[i],t);return}if(x(n)){C(n.body,t),n.params!==void 0&&C(n.params,t);return}if(h(n)){C(n.left,t),n.right!==void 0&&C(n.right,t);return}if(b(n)){for(let i=0;i<n.conditions.length;i++)C(n.conditions[i],t);return}let o=n,r=Object.keys(o);for(let i=0;i<r.length;i++)C(o[r[i]],t);}function Sn(n){return R(n).length>0}function wn(n){return R(n).length===0}function kn(n){return JSON.stringify(n)}function z(n,t={}){let o=t.scope??{},r=t.accessor,i=t.context??{},s=y(n,o,r,i),e=R(n),f=kn(n);return {fn:s,deps:e,hash:f}}function y(n,t,o,r){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let i=n.map(s=>y(s,t,o,r));return s=>i.map(e=>e(s))}if(E(n))return xn(n,o);if(S(n))return Fn(n,t,o,r);if(k(n))return Rn(n,t,o,r);if(w(n))return On(n,t,o,r);if(x(n))return Nn(n,t,o,r);if(h(n))return jn(n,t,o,r);if(b(n))return vn(n,t,o,r);if(B(n)){let i=n,s=Object.keys(i),e=s.map(f=>y(i[f],t,o,r));return f=>{let u={};for(let a=0;a<s.length;a++)u[s[a]]=e[a](f);return u}}return ()=>n}function Z(n,t){return t?o=>t(n,o):j(n)}function xn(n,t){return Z(n.$,t)}function Fn(n,t,o,r){let i;if(typeof n.$if=="string"){let f=n.$if.startsWith("!")?n.$if.slice(1):n.$if,u=Z(f,o);i=n.$if.startsWith("!")?l=>!u(l):l=>!!u(l);}else {let f=y(n.$if,t,o,r);i=u=>!!f(u);}let s=y(n.then,t,o,r),e=n.else!==void 0?y(n.else,t,o,r):()=>{};return f=>i(f)?s(f):e(f)}function Rn(n,t,o,r){let i=n.$pipe;if(i.length===0)return ()=>{};if(i.length===1)return y(i[0],t,o,r);let s=y(i[0],t,o,r),e=i.slice(1).map(u=>y(u,t,o,r)),f=e.length;if(f===1){let[u]=e;return a=>{let l=s(a),p=u(a);return typeof p=="function"?p(l):p}}if(f===2){let[u,a]=e;return l=>{let p=s(l),d=u(l);return p=typeof d=="function"?d(p):d,d=a(l),typeof d=="function"?d(p):d}}if(f===3){let[u,a,l]=e;return p=>{let d=s(p),g=u(p);return d=typeof g=="function"?g(d):g,g=a(p),d=typeof g=="function"?g(d):g,g=l(p),typeof g=="function"?g(d):g}}return u=>{let a=s(u);for(let l=0;l<f;l++){let p=e[l](u);a=typeof p=="function"?p(a):p;}return a}}function On(n,t,o,r){let i=n.$fn,s=n.args;if(s===void 0)return ()=>{let u=t[i];if(!u)throw new Error(`Function not found in scope: ${i}`);return u};let e=s.map(u=>y(u,t,o,r)),f=e.length;if(f===0)return ()=>{let u=t[i];if(!u)throw new Error(`Function not found in scope: ${i}`);return u()};if(f===1){let[u]=e;return a=>{let l=t[i];if(!l)throw new Error(`Function not found in scope: ${i}`);return l(u(a))}}if(f===2){let[u,a]=e;return l=>{let p=t[i];if(!p)throw new Error(`Function not found in scope: ${i}`);return p(u(l),a(l))}}if(f===3){let[u,a,l]=e;return p=>{let d=t[i];if(!d)throw new Error(`Function not found in scope: ${i}`);return d(u(p),a(p),l(p))}}return u=>{let a=t[i];if(!a)throw new Error(`Function not found in scope: ${i}`);return a(...e.map(l=>l(u)))}}function Nn(n,t,o,r){let i=n.$cb,s=y(n.body,t,o,r),e=n.params?y(n.params,t,o,r):void 0,f=u=>o?a=>o(a,u):a=>j(a)(u);return u=>{let a=r?.[i];if(!a)throw new Error(`Context function not found: ${i}`);let l=(g,F)=>s(g),p=f(u),d=e?e(u):void 0;return a(l,u,p,d)}}function jn(n,t,o,r){let i=y(n.left,t,o,r),s=n.right!==void 0?y(n.right,t,o,r):()=>{};switch(n.op){case "eq":return e=>i(e)===s(e);case "neq":return e=>i(e)!==s(e);case "gt":return e=>i(e)>s(e);case "gte":return e=>i(e)>=s(e);case "lt":return e=>i(e)<s(e);case "lte":return e=>i(e)<=s(e);case "in":return e=>{let f=s(e);return Array.isArray(f)&&f.includes(i(e))};case "notIn":return e=>{let f=s(e);return !Array.isArray(f)||!f.includes(i(e))};case "contains":return e=>{let f=i(e);return Array.isArray(f)&&f.includes(s(e))};case "notContains":return e=>{let f=i(e);return !Array.isArray(f)||!f.includes(s(e))};case "exists":return e=>i(e)!==void 0;case "notExists":return e=>i(e)===void 0;case "matches":return e=>{let f=i(e),u=s(e);return typeof f!="string"||typeof u!="string"?false:new RegExp(u).test(f)};case "notMatches":return e=>{let f=i(e),u=s(e);return typeof f!="string"||typeof u!="string"?true:!new RegExp(u).test(f)};case "startsWith":return e=>{let f=i(e),u=s(e);return typeof f=="string"&&typeof u=="string"&&f.startsWith(u)};case "endsWith":return e=>{let f=i(e),u=s(e);return typeof f=="string"&&typeof u=="string"&&f.endsWith(u)}}}function vn(n,t,o,r){let i=n.conditions.map(e=>y(e,t,o,r)),s=i.length;if(s===1)return e=>!!i[0](e);if(s===2){let[e,f]=i;return n.logic==="AND"?u=>!!e(u)&&!!f(u):u=>!!e(u)||!!f(u)}if(s===3){let[e,f,u]=i;return n.logic==="AND"?a=>!!e(a)&&!!f(a)&&!!u(a):a=>!!e(a)||!!f(a)||!!u(a)}return n.logic==="AND"?e=>{for(let f=0;f<s;f++)if(!i[f](e))return false;return true}:e=>{for(let f=0;f<s;f++)if(i[f](e))return true;return false}}function Gn(n,t,o={}){return z(n,o).fn(t)}var D=class{constructor(t=1e3){this.cache=new Map,this._maxSize=t;}get(t,o={}){let r=JSON.stringify(t),i=this.cache.get(r);if(i)return this.cache.delete(r),this.cache.set(r,i),i;let s=z(t,o);if(this.cache.size>=this._maxSize){let e=this.cache.keys().next().value;e&&this.cache.delete(e);}return this.cache.set(r,s),s}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 o=this.cache.keys().next().value;o&&this.cache.delete(o);}}},P=new D;function Wn(n,t={}){return P.get(n,t)}function J(n,t="root",o={}){let r=[];return T(n,t,r,o),{valid:r.length===0,errors:r}}function T(n,t,o,r){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let e=0;e<n.length;e++)T(n[e],`${t}[${e}]`,o,r);return}if(E(n)){(!n.$||typeof n.$!="string")&&o.push(`${t}: invalid reference, $ must be non-empty string`);return}if(S(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||o.push(`${t}.$if: empty path in string shorthand`):T(n.$if,`${t}.$if`,o,r),T(n.then,`${t}.then`,o,r),n.else!==void 0&&T(n.else,`${t}.else`,o,r);return}if(k(n)){if(!Array.isArray(n.$pipe)){o.push(`${t}.$pipe: must be an array`);return}if(n.$pipe.length===0){o.push(`${t}.$pipe: must have at least one element`);return}for(let e=0;e<n.$pipe.length;e++)T(n.$pipe[e],`${t}.$pipe[${e}]`,o,r);return}if(w(n)){if(!n.$fn||typeof n.$fn!="string"){o.push(`${t}: invalid function, $fn must be non-empty string`);return}if(r.scope&&!(n.$fn in r.scope)&&o.push(`${t}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))o.push(`${t}.args: must be an array`);else for(let e=0;e<n.args.length;e++)T(n.args[e],`${t}.args[${e}]`,o,r);return}if(x(n)){if(!n.$cb||typeof n.$cb!="string"){o.push(`${t}: invalid callback, $cb must be non-empty string`);return}r.context&&!(n.$cb in r.context)&&o.push(`${t}: context function "${n.$cb}" not found`),T(n.body,`${t}.body`,o,r),n.params!==void 0&&T(n.params,`${t}.params`,o,r);return}if(h(n)){v.has(n.op)||o.push(`${t}: invalid operator "${n.op}"`),T(n.left,`${t}.left`,o,r),n.right!==void 0&&T(n.right,`${t}.right`,o,r);return}if(b(n)){if(n.logic!=="AND"&&n.logic!=="OR"&&o.push(`${t}: invalid logic "${n.logic}", must be "AND" or "OR"`),!Array.isArray(n.conditions)){o.push(`${t}.conditions: must be an array`);return}for(let e=0;e<n.conditions.length;e++)T(n.conditions[e],`${t}.conditions[${e}]`,o,r);return}let i=n,s=Object.keys(i);for(let e=0;e<s.length;e++){let f=s[e];T(i[f],`${t}.${f}`,o,r);}}function zn(n,t={}){let o=J(n,"root",t);if(!o.valid)throw new Error(`Invalid expression: ${o.errors.join("; ")}`)}function Dn(n,t={}){return J(n,"root",t).valid}var sn={};mn(sn,{$:()=>nn,$cb:()=>rn,$cond:()=>on,$fn:()=>tn,$if:()=>_n,$pipe:()=>en,cb:()=>qn,cond:()=>Ln,fn:()=>In,pipe:()=>Vn,ref:()=>Mn});function nn(n){return {$:n}}var Mn=nn;function tn(n,t){return t===void 0||t.length===0?{$fn:n}:{$fn:n,args:t}}var In=tn;function _n(n,t,o){return o===void 0?{$if:n,then:t}:{$if:n,then:t,else:o}}function en(...n){return {$pipe:n}}var Vn=en;function on(n,t,o){return o===void 0?{left:n,op:t}:{left:n,op:t,right:o}}var Ln=on;function rn(n,t,o){return o===void 0?{$cb:n,body:t}:{$cb:n,body:t,params:o}}var qn=rn;var K="data",un="scope",Bn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function I(n,t={}){let{dataParam:o=K,scopeParam:r=un,noPrefixes:i=false,useAccessor:s=false,lexicalPrefix:e}=t;return m(n,o,r,i,s,e)}function m(n,t,o,r,i,s){if(n===null)return builders.literal(null);if(typeof n=="string")return builders.literal(n);if(typeof n=="number")return builders.literal(n);if(typeof n=="boolean")return builders.literal(n);if(Array.isArray(n))return builders.arrayExpression(n.map(e=>m(e,t,o,r,i,s)));if(E(n))return Jn(n.$,t,r,i,s);if(S(n))return Xn(n,t,o,r,i,s);if(k(n))return Un(n.$pipe,t,o,r,i,s);if(w(n))return Yn(n,t,o,r,i,s);if(x(n))return Qn(n,t,o,r,i,s);if(h(n))return Zn(n,t,o,r,i,s);if(b(n))return Pn(n,t,o,r,i,s);if(typeof n=="object"){let f=Object.entries(n).map(([u,a])=>builders.property(builders.identifier(u),m(a,t,o,r,i,s)));return builders.objectExpression(f)}return builders.literal(null)}var X="accessor";function Y(n,t){return t?n===t||n.startsWith(t+"."):false}function Jn(n,t,o,r,i){return r?Y(n,i)?O(n,t,true):builders.callExpression(builders.identifier(X),[builders.literal(n),builders.identifier(t)]):n.includes("[*]")?Kn(n,t,o):O(n,t,o)}function O(n,t,o){let r=M(n);if(r.length===0)return o?builders.identifier("undefined"):builders.identifier(t);let i;if(o){let s=r[0];i=builders.identifier(s.value);for(let e=1;e<r.length;e++){let f=r[e];f.type==="key"?i=builders.memberExpression(i,builders.identifier(f.value),false,true):i=builders.memberExpression(i,builders.literal(f.value),true,true);}}else {i=builders.identifier(t);for(let s of r)s.type==="key"?i=builders.memberExpression(i,builders.identifier(s.value),false,true):i=builders.memberExpression(i,builders.literal(s.value),true,true);}return i}function Kn(n,t,o){let r=n.indexOf("[*]"),i=n.slice(0,r),s=n.slice(r+3),e;if(i?e=O(i,t,o):e=o?builders.identifier("undefined"):builders.identifier(t),!s||s==="")return e;if(s.includes("[*]"))return cn(e,s);let f="_i",u=s.startsWith(".")?s.slice(1):s,a=builders.identifier(f);if(u){let l=M(u);for(let p of l)p.type==="key"?a=builders.memberExpression(a,builders.identifier(p.value),false,true):a=builders.memberExpression(a,builders.literal(p.value),true,true);}return builders.callExpression(builders.memberExpression(e,builders.identifier("map"),false,true),[builders.arrowFunctionExpression([builders.identifier(f)],a)])}function cn(n,t){let o=t.indexOf("[*]"),r=t.slice(0,o),i=t.slice(o+3),s="_i",e=r.startsWith(".")?r.slice(1):r,f=builders.identifier(s);if(e){let a=M(e);for(let l of a)l.type==="key"&&(f=builders.memberExpression(f,builders.identifier(l.value),false,true));}if(i.includes("[*]")){let a=cn(f,i);return builders.callExpression(builders.memberExpression(n,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([builders.identifier(s)],a)])}let u=i.startsWith(".")?i.slice(1):i;if(u){let a=M(u);for(let l of a)l.type==="key"&&(f=builders.memberExpression(f,builders.identifier(l.value),false,true));}return builders.callExpression(builders.memberExpression(n,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([builders.identifier(s)],f)])}function Xn(n,t,o,r,i,s){let e;if(typeof n.$if=="string"){let a=n.$if.startsWith("!"),l=a?n.$if.slice(1):n.$if,p;i?Y(l,s)?p=O(l,t,true):p=builders.callExpression(builders.identifier(X),[builders.literal(l),builders.identifier(t)]):p=O(l,t,r),e=a?builders.unaryExpression("!",p):p;}else e=m(n.$if,t,o,r,i,s);let f=m(n.then,t,o,r,i,s),u=n.else!==void 0?m(n.else,t,o,r,i,s):builders.identifier("undefined");return builders.conditionalExpression(e,f,u)}function Yn(n,t,o,r,i,s){let e=r?builders.identifier(n.$fn):builders.memberExpression(builders.identifier(o),builders.identifier(n.$fn),false,false);if(n.args===void 0)return e;let f=n.args.map(u=>m(u,t,o,r,i,s));return builders.callExpression(e,f)}var Hn="context";function Qn(n,t,o,r,i,s){let e=r?builders.identifier(n.$cb):builders.memberExpression(builders.identifier(Hn),builders.identifier(n.$cb),false,false),f=m(n.body,t,o,r,i,s),a=[builders.arrowFunctionExpression([builders.identifier(t),builders.identifier("get")],f),builders.identifier(t),builders.identifier("get")];if(n.params!==void 0){let l=m(n.params,t,o,r,i,s);a.push(l);}return builders.callExpression(e,a)}function Un(n,t,o,r,i,s){if(n.length===0)return builders.identifier("undefined");if(n.length===1)return m(n[0],t,o,r,i,s);let e=m(n[0],t,o,r,i,s);for(let f=1;f<n.length;f++){let u=m(n[f],t,o,r,i,s);e=builders.callExpression(u,[e]);}return e}function fn(n,t,o,r,i,s){if(E(n)){let e=n.$;return i?Y(e,s)?O(e,t,true):builders.callExpression(builders.identifier(X),[builders.literal(e),builders.identifier(t)]):O(e,t,r)}return m(n,t,o,r,i,s)}function Zn(n,t,o,r,i,s){let e=fn(n.left,t,o,r,i,s),f=n.right!==void 0?fn(n.right,t,o,r,i,s):builders.literal(null),u=Bn[n.op];if(u)return builders.binaryExpression(u,e,f);switch(n.op){case "in":return builders.callExpression(builders.memberExpression(f,builders.identifier("includes")),[e]);case "notIn":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(f,builders.identifier("includes")),[e]));case "contains":return builders.callExpression(builders.memberExpression(e,builders.identifier("includes"),false,true),[f]);case "notContains":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(e,builders.identifier("includes"),false,true),[f]));case "exists":return builders.binaryExpression("!=",e,builders.literal(null));case "notExists":return builders.binaryExpression("==",e,builders.literal(null));case "matches":return builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[f]),builders.identifier("test")),[e]);case "notMatches":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[f]),builders.identifier("test")),[e]));case "startsWith":return builders.callExpression(builders.memberExpression(e,builders.identifier("startsWith"),false,true),[f]);case "endsWith":return builders.callExpression(builders.memberExpression(e,builders.identifier("endsWith"),false,true),[f]);default:return builders.binaryExpression("===",e,f)}}function Pn(n,t,o,r,i,s){let{logic:e,conditions:f}=n,u=e==="AND"?"&&":"||";if(f.length===0)return builders.literal(e==="AND");if(f.length===1)return m(f[0],t,o,r,i,s);let a=m(f[0],t,o,r,i,s);for(let l=1;l<f.length;l++){let p=m(f[l],t,o,r,i,s);a=builders.logicalExpression(u,a,p);}return a}function M(n){let t=[],o=n.length,r=0,i="";for(;r<o;){let s=n[r];if(s===".")i&&(t.push({type:"key",value:i}),i=""),r++;else if(s==="["){i&&(t.push({type:"key",value:i}),i=""),r++;let e=r;for(;r<o&&n[r]!=="]";)r++;let f=n.slice(e,r);if(r++,f!=="*"){let u=parseInt(f,10);t.push({type:"index",value:isNaN(u)?f:u});}}else i+=s,r++;}return i&&t.push({type:"key",value:i}),t}function an(n,t=[K]){return builders.arrowFunctionExpression(t.map(o=>builders.identifier(o)),n)}function _(n){let t=new Set;return $(n,t),t}function $(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r of n)$(r,t);return}if(E(n))return;if(S(n)){$(n.$if,t),$(n.then,t),n.else!==void 0&&$(n.else,t);return}if(k(n)){for(let r of n.$pipe)$(r,t);return}if(w(n)){if(t.add(n.$fn),n.args)for(let r of n.args)$(r,t);return}if(x(n)){$(n.body,t),n.params!==void 0&&$(n.params,t);return}if(h(n)){n.left!==void 0&&typeof n.left=="object"&&$(n.left,t),n.right!==void 0&&typeof n.right=="object"&&$(n.right,t);return}if(b(n)){for(let r of n.conditions)$(r,t);return}let o=n;for(let r of Object.keys(o))$(o[r],t);}function V(n){let t=new Set;return A(n,t),t}function A(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r of n)A(r,t);return}if(E(n))return;if(S(n)){A(n.$if,t),A(n.then,t),n.else!==void 0&&A(n.else,t);return}if(k(n)){for(let r of n.$pipe)A(r,t);return}if(w(n)){if(n.args)for(let r of n.args)A(r,t);return}if(x(n)){t.add(n.$cb),A(n.body,t),n.params!==void 0&&A(n.params,t);return}if(h(n)){n.left!==void 0&&typeof n.left=="object"&&A(n.left,t),n.right!==void 0&&typeof n.right=="object"&&A(n.right,t);return}if(b(n)){for(let r of n.conditions)A(r,t);return}let o=n;for(let r of Object.keys(o))A(o[r],t);}function L(n){let t=new Set;for(let o of n){let r=o.indexOf("."),i=o.indexOf("["),s=o.length;r!==-1&&(s=Math.min(s,r)),i!==-1&&(s=Math.min(s,i));let e=o.slice(0,s);e&&t.add(e);}return t}function tt(n){return JSON.stringify(n)}function et(n,t,o,r,i,s){let e=I(n,{noPrefixes:true,useAccessor:i,lexicalPrefix:s}),f=generate(e),u="";i?s&&(u=`const{${s}}=data??{};`):t.size>0&&(u=`const{${[...t].join(",")}}=data??{};`);let a=i?new Set([...o,"accessor"]):o,l=a.size>0?`const{${[...a].join(",")}}=scope;`:"",p=r.size>0?`const{${[...r].join(",")}}=context;`:"",d=r.size>0,g="";d&&(i?g="const get=(path)=>accessor(path,data);":g="const get=(path)=>path.split('.').reduce((o,k)=>o?.[k],data);");let F=a.size>0,N;if(F||d){let pn=d?"scope,context":"scope",dn=`${u}${g}return ${f}`;N=`(function(${pn}){${l}${p}return function(data){${dn}}})`;}else N=`(function(){return function(data){${u}return ${f}}})`;return N}function H(n,t={}){let{scope:o={},context:r={},returnCode:i=false,useAccessor:s=false,lexicalPrefix:e}=t,f=R(n),u=L(f),a=_(n),l=V(n),p=tt(n),d=et(n,u,a,l,s,e);if(i)return {code:d,deps:f,hash:p,dataRoots:[...u],scopeFns:[...a],contextFns:[...l]};let g;try{let F=l.size>0,N=new Function(`return ${d}`)();g=F?N(o,r):N(o);}catch(F){throw new Error(`AST compilation failed. If this is due to CSP, use the standard compile() function instead. Error: ${F instanceof Error?F.message:String(F)}`)}return {fn:g,deps:f,hash:p}}function ln(n,t,o={}){let{fn:r}=H(n,o);return r(t)}function it(n,t){return q(n,t)}function q(n,t){if(n===null)return null;if(typeof n!="object")return n;if(Array.isArray(n))return n.map(s=>q(s,t));let o=n,r=Object.keys(o);for(let s of r)if(s in t){let e=t[s](o);if(typeof e=="object"&&e!==null&&s in e)throw new Error(`Transform "${s}" returned object with same key \u2014 infinite loop`);return q(e,t)}let i={};for(let s of r)i[s]=q(o[s],t);return i}var vt="2.0.0";export{D as ExpressionCache,vt as VERSION,zn as assertValid,sn as builders,P as cache,Wn as cached,$n as clearPathCache,z as compile,H as compileAST,j as compilePath,I as dslToAST,Gn as evaluate,ln as evaluateAST,V as extractContextFns,L as extractDataRoots,R as extractDeps,_ as extractScopeFns,Tn as get,An as getPathCacheSize,Sn as hasDeps,U as hasWildcard,x as isCb,h as isCondition,yn as isConditionExpr,b as isConditionGroup,S as isConditional,w as isFn,B as isLiteral,k as isPipe,wn as isPure,E as isRef,Dn as isValid,it as normalize,W as normalizePath,J as validate,an as wrapInFunction};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statedelta-libs/expressions",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "JSON DSL compiler for optimized functions - StateDelta expression engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",