@statedelta-libs/expressions 0.2.1 → 1.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
@@ -14,7 +14,7 @@
14
14
  - **$pipe** - Composição com valor inicial (sintaxe DSL)
15
15
  - **Path syntax** - Suporte a wildcards (`items[*].price`)
16
16
  - **Dependency extraction** - Para dirty tracking/reatividade
17
- - **Integração** - Usa `@statedelta-libs/conditions` para condicionais
17
+ - **Conditions nativo** - Condicionais integradas com expressions nos lados
18
18
  - **Type-safe** - TypeScript nativo com inferência
19
19
 
20
20
  ## Instalação
@@ -93,6 +93,75 @@ fn(data); // Executa (mais rápido que compile())
93
93
  | Hot path crítico | `compileAST()` | V8 JIT otimiza melhor |
94
94
  | Expressões complexas | `compileAST()` | Ganho maior em nested calls |
95
95
 
96
+ #### useAccessor (compileAST)
97
+
98
+ Para contextos inteligentes (ex: `TickContext`), use `useAccessor: true` para gerar `accessor(path, data)` ao invés de acesso direto:
99
+
100
+ ```typescript
101
+ const ctx = new TickContext();
102
+
103
+ const { fn } = compileAST(
104
+ { $fn: "add", args: [{ $: "hp" }, { $: "mp" }] },
105
+ {
106
+ scope: {
107
+ add,
108
+ accessor: (path) => ctx.get(path) // closure que captura ctx
109
+ },
110
+ useAccessor: true
111
+ }
112
+ );
113
+
114
+ fn(); // usa ctx.get("hp") + ctx.get("mp")
115
+ ```
116
+
117
+ Código gerado:
118
+ ```js
119
+ (function(scope){
120
+ const{add,accessor}=scope;
121
+ return function(data){
122
+ return add(accessor("hp",data),accessor("mp",data))
123
+ }
124
+ })
125
+ ```
126
+
127
+ #### lexicalPrefix (compileAST)
128
+
129
+ Para máxima performance em paths específicos, use `lexicalPrefix` para acesso direto via destructuring:
130
+
131
+ ```typescript
132
+ const ctx = new TickContext();
133
+
134
+ const { fn } = compileAST(
135
+ { $fn: "add", args: [{ $: "hp" }, { $: "params.damage" }] },
136
+ {
137
+ scope: {
138
+ add,
139
+ accessor: (path) => ctx.get(path)
140
+ },
141
+ useAccessor: true,
142
+ lexicalPrefix: "params" // params.* vai direto, resto via accessor
143
+ }
144
+ );
145
+
146
+ fn({ params: { damage: 25 } }); // ctx.get("hp") + params.damage
147
+ ```
148
+
149
+ Código gerado:
150
+ ```js
151
+ (function(scope){
152
+ const{add,accessor}=scope;
153
+ return function(data){
154
+ const{params}=data??{}; // destructuring direto (rápido!)
155
+ return add(accessor("hp",data),params?.damage)
156
+ }
157
+ })
158
+ ```
159
+
160
+ | Path | Com lexicalPrefix | Sem lexicalPrefix |
161
+ |------|-------------------|-------------------|
162
+ | `params.damage` | `params?.damage` (direto) | `accessor("params.damage", data)` |
163
+ | `hp` | `accessor("hp", data)` | `accessor("hp", data)` |
164
+
96
165
  ### evaluate() / evaluateAST()
97
166
 
98
167
  Compila e executa em um passo.
@@ -122,6 +191,33 @@ const deps = extractDeps({
122
191
  // ["$isVip", "price.vip", "price.regular"]
123
192
  ```
124
193
 
194
+ ## JSON Aninhado (Walk Automático)
195
+
196
+ O compilador **percorre automaticamente** todo o JSON e resolve expressões onde quer que estejam:
197
+
198
+ ```typescript
199
+ const { fn } = compile({
200
+ name: "John",
201
+ damage: { $: "params.damage" },
202
+ active: { $if: "hp.current", then: true, else: false },
203
+ nested: {
204
+ deep: {
205
+ value: { $fn: "add", args: [{ $: "a" }, { $: "b" }] }
206
+ }
207
+ }
208
+ }, { scope });
209
+
210
+ fn({ params: { damage: 25 }, hp: { current: 100 }, a: 1, b: 2 });
211
+ // {
212
+ // name: "John",
213
+ // damage: 25,
214
+ // active: true,
215
+ // nested: { deep: { value: 3 } }
216
+ // }
217
+ ```
218
+
219
+ Não precisa de walker manual - o `compile()` e `compileAST()` já fazem isso internamente.
220
+
125
221
  ## Tipos de Expressão
126
222
 
127
223
  ### Literal
@@ -146,7 +242,7 @@ true
146
242
 
147
243
  ```typescript
148
244
  {
149
- $if: { path: "age", op: "gte", value: 18 },
245
+ $if: { left: { $: "age" }, op: "gte", right: 18 },
150
246
  then: "adult",
151
247
  else: "minor"
152
248
  }
@@ -189,14 +285,36 @@ Chama função do scope com argumentos compilados.
189
285
  // → scope.getTimestamp()
190
286
  ```
191
287
 
192
- ### Condition (delegado)
288
+ ### Condition
289
+
290
+ Condicionais compiladas internamente. Ambos os lados aceitam qualquer expressão:
193
291
 
194
292
  ```typescript
195
- // Detectado automaticamente e delegado para @statedelta-libs/conditions
196
- { path: "user.age", op: "gte", value: 18 }
293
+ // Ref vs literal (básico)
294
+ { left: { $: "user.age" }, op: "gte", right: 18 }
295
+
296
+ // Ref vs Ref
297
+ { left: { $: "price" }, op: "lte", right: { $: "budget" } }
298
+
299
+ // $fn nos lados
300
+ { left: { $fn: "add", args: [{ $: "a" }, { $: "b" }] }, op: "gt", right: 100 }
301
+
302
+ // $pipe no lado
303
+ { left: { $pipe: [{ $: "name" }, { $fn: "upper" }] }, op: "eq", right: "ADMIN" }
304
+
305
+ // Condition group
306
+ {
307
+ logic: "AND",
308
+ conditions: [
309
+ { left: { $: "active" }, op: "eq", right: true },
310
+ { left: { $fn: "len", args: [{ $: "items" }] }, op: "gte", right: 3 }
311
+ ]
312
+ }
197
313
  ```
198
314
 
199
- > **Nota:** Apenas objetos com operadores de condition válidos (`eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `notIn`, `contains`, `notContains`, `exists`, `notExists`, `matches`, `notMatches`, `startsWith`, `endsWith`) são detectados como conditions. Objetos com `op: "set"` ou outros operadores não são conditions e são tratados como literals.
315
+ **Operadores:** `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `notIn`, `contains`, `notContains`, `exists`, `notExists`, `matches`, `notMatches`, `startsWith`, `endsWith`
316
+
317
+ > **Nota:** Objetos com `op: "set"` ou outros operadores não-condition são tratados como literals.
200
318
 
201
319
  ## Scope
202
320
 
@@ -254,7 +372,7 @@ O accessor é propagado para:
254
372
  - Shorthand de `$if` (`{ $if: "path", ... }`)
255
373
  - Argumentos de `$fn`
256
374
  - Steps de `$pipe`
257
- - Conditions (delegadas para `@statedelta-libs/conditions`)
375
+ - Conditions (compiladas internamente)
258
376
 
259
377
  **Performance:** Igual ao acesso direto (~25-30M ops/s).
260
378
 
@@ -347,16 +465,16 @@ O compilador detecta automaticamente o tipo de expressão baseado na estrutura d
347
465
  | Conditional | `{ $if, then }` presentes | `{ $if: cond, then: x, else: y }` |
348
466
  | Function | `{ $fn }` presente | `{ $fn: "add", args: [...] }` |
349
467
  | Pipe | `{ $pipe }` presente | `{ $pipe: [...] }` |
350
- | Condition | `{ path, op }` com operador válido | `{ path: "age", op: "gte", value: 18 }` |
468
+ | Condition | `{ left, op }` com operador válido | `{ left: { $: "age" }, op: "gte", right: 18 }` |
351
469
  | Literal | Nenhum dos acima | `{ foo: "bar" }`, `42`, `"hello"` |
352
470
 
353
471
  ### Distinção entre Conditions e Effect Objects
354
472
 
355
- Objetos com `path` e `op` só são tratados como conditions se `op` for um operador válido:
473
+ Objetos com `left` e `op` só são tratados como conditions se `op` for um operador válido:
356
474
 
357
475
  ```typescript
358
476
  // ✓ Condition (op: "eq" é operador válido)
359
- { path: "user.age", op: "eq", value: 18 }
477
+ { left: { $: "user.age" }, op: "eq", right: 18 }
360
478
 
361
479
  // ✓ Literal object (op: "set" NÃO é operador de condition)
362
480
  { resource: "state", op: "set", path: "currentPlayer", value: "X" }
@@ -371,7 +489,7 @@ Funções declarativas para construir expressões. Disponíveis via namespace `b
371
489
  ```typescript
372
490
  import { builders, compile } from '@statedelta-libs/expressions';
373
491
 
374
- const { $, $fn, $if, $pipe } = builders;
492
+ const { $, $fn, $if, $pipe, $cond } = builders;
375
493
  ```
376
494
 
377
495
  ### `$` / `ref` - Path Reference
@@ -423,13 +541,33 @@ $pipe(
423
541
  )
424
542
  ```
425
543
 
544
+ ### `$cond` / `cond` - Condition
545
+
546
+ ```typescript
547
+ // Básico
548
+ $cond($("age"), "gte", 18)
549
+ // { left: { $: "age" }, op: "gte", right: 18 }
550
+
551
+ // Exists (sem right)
552
+ $cond($("email"), "exists")
553
+
554
+ // Ref vs Ref
555
+ $cond($("price"), "lte", $("budget"))
556
+
557
+ // Com $fn nos lados
558
+ $cond($fn("add", [$("a"), $("b")]), "gt", 100)
559
+
560
+ // Com $pipe
561
+ $cond($pipe($("name"), $fn("upper")), "eq", "ADMIN")
562
+ ```
563
+
426
564
  ### Exemplo Completo
427
565
 
428
566
  ```typescript
429
567
  import { builders, compile } from '@statedelta-libs/expressions';
430
568
  import { filter, map, sum } from '@statedelta-libs/operators';
431
569
 
432
- const { $, $fn, $if, $pipe } = builders;
570
+ const { $, $fn, $if, $pipe, $cond } = builders;
433
571
 
434
572
  const scope = { filter, map, sum };
435
573
 
@@ -459,6 +597,7 @@ fn({
459
597
  | `$` | `ref` |
460
598
  | `$fn` | `fn` |
461
599
  | `$pipe` | `pipe` |
600
+ | `$cond` | `cond` |
462
601
 
463
602
  ## TypeScript
464
603
 
@@ -470,6 +609,10 @@ import type {
470
609
  ConditionalExpr,
471
610
  FnExpr,
472
611
  PipeExpr,
612
+ Condition,
613
+ ConditionGroup,
614
+ ConditionExpr,
615
+ ConditionOp,
473
616
  Scope,
474
617
  CompileOptions,
475
618
  AccessorFn,
@@ -512,6 +655,19 @@ import {
512
655
 
513
656
  4. **Novo**: `$pipe` como sintaxe DSL para composição
514
657
 
658
+ ### v1.0 → v1.1
659
+
660
+ 1. **Conditions internas**: `@statedelta-libs/conditions` não é mais dependência. Conditions são compiladas internamente.
661
+
662
+ 2. **Expressions nos lados**: `left`/`right` de conditions agora aceitam qualquer `Expression` (`$fn`, `$pipe`, `$if`, etc), não apenas `Ref | literal`.
663
+
664
+ 3. **Novo builder**: `$cond(left, op, right?)` para construir conditions com expressions:
665
+ ```typescript
666
+ $cond($fn("add", [$("a"), $("b")]), "gt", 100)
667
+ ```
668
+
669
+ 4. **Novos tipos**: `ConditionOp`, `Condition`, `ConditionGroup`, `ConditionExpr` exportados diretamente do expressions.
670
+
515
671
  ## Licença
516
672
 
517
673
  MIT © Anderson D. Rosa
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- 'use strict';var conditions=require('@statedelta-libs/conditions'),omniAst=require('omni-ast');var on=Object.defineProperty;var rn=(n,e)=>{for(var i in e)on(n,i,{get:e[i],enumerable:true});};var g=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,h=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,T=n=>n!==null&&typeof n=="object"&&"$fn"in n&&typeof n.$fn=="string",b=n=>n!==null&&typeof n=="object"&&"$pipe"in n&&Array.isArray(n.$pipe),_=new Set(["eq","neq","gt","gte","lt","lte","in","notIn","contains","notContains","exists","notExists","matches","notMatches","startsWith","endsWith"]),y=n=>n!==null&&typeof n=="object"&&"path"in n&&"op"in n&&_.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),E=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,sn=n=>y(n)||E(n),D=n=>{if(n===null)return true;let e=typeof n;if(e==="string"||e==="number"||e==="boolean"||Array.isArray(n))return true;if(e==="object"&&n!==null){let i=n,t="path"in i&&"op"in i&&_.has(i.op);return !("$"in i)&&!("$if"in i)&&!("$fn"in i)&&!("$pipe"in i)&&!t&&!("logic"in i)}return false};var x=new Map;function q(n){let e=[],i=n.length,t=0,r="";for(;t<i;){let f=n[t];if(f===".")r&&(e.push({type:"key",value:r}),r=""),t++;else if(f==="["){r&&(e.push({type:"key",value:r}),r=""),t++;let o=t;for(;t<i&&n[t]!=="]";)t++;let s=n.slice(o,t);if(t++,s==="*")e.push({type:"wildcard",value:"*"});else {let u=parseInt(s,10);e.push({type:"index",value:isNaN(u)?s:u});}}else r+=f,t++;}return r&&e.push({type:"key",value:r}),e}function J(n){return n.includes("[*]")}function O(n){let e=x.get(n);return e||(e=J(n)?fn(n):ln(n),x.set(n,e),e)}function ln(n){if(!n.includes(".")&&!n.includes("["))return r=>r?.[n];let e=q(n),i=e.length;if(i===2){let[r,f]=e,o=r.value,s=f.value;return u=>u?.[o]?.[s]}if(i===3){let[r,f,o]=e,s=r.value,u=f.value,a=o.value;return c=>c?.[s]?.[u]?.[a]}let t=e.map(r=>r.value);return r=>{let f=r;for(let o=0;o<i&&f!=null;o++)f=f[t[o]];return f}}function fn(n){let e=q(n),i=[];for(let t=0;t<e.length;t++)e[t].type==="wildcard"&&i.push(t);return i.length===1?un(e,i[0]):an(e,i)}function un(n,e){let i=n.slice(0,e).map(o=>o.value),t=n.slice(e+1).map(o=>o.value),r=i.length,f=t.length;if(f===0){if(r===1){let o=i[0];return s=>s?.[o]}return o=>{let s=o;for(let u=0;u<r&&s!=null;u++)s=s[i[u]];return s}}if(f===1){let o=t[0];if(r===1){let s=i[0];return u=>{let a=u?.[s];if(Array.isArray(a))return a.map(c=>c?.[o])}}return s=>{let u=s;for(let a=0;a<r&&u!=null;a++)u=u[i[a]];if(Array.isArray(u))return u.map(a=>a?.[o])}}return o=>{let s=o;for(let u=0;u<r&&s!=null;u++)s=s[i[u]];if(Array.isArray(s))return s.map(u=>{let a=u;for(let c=0;c<f&&a!=null;c++)a=a[t[c]];return a})}}function an(n,e){let i=[],t=0;for(let f=0;f<e.length;f++){let o=e[f],s=f===e.length-1,u=n.slice(t,o).map(a=>a.value);u.length>0&&i.push({type:"access",keys:u}),i.push({type:s?"map":"flatMap",keys:[]}),t=o+1;}let r=n.slice(t).map(f=>f.value);return f=>{let o=f;for(let s of i){if(o==null)return;if(s.type==="access")for(let u of s.keys){if(o==null)return;o=o[u];}else if(s.type==="flatMap"){if(!Array.isArray(o))return;o=o.flatMap(u=>{let a=u;return Array.isArray(a)?a:[a]});}else if(s.type==="map"){if(!Array.isArray(o))return;r.length>0&&(o=o.map(u=>{let a=u;for(let c of r){if(a==null)return;a=a[c];}return a}));}}return o}}function cn(n,e){return O(e)(n)}function R(n){let e=n.indexOf("[*]");return e===-1?n:n.slice(0,e)}function pn(){x.clear();}function dn(){return x.size}function w(n){let e=new Set;return S(n,e),Array.from(e)}function S(n,e){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r=0;r<n.length;r++)S(n[r],e);return}if(g(n)){e.add(R(n.$));return}if(h(n)){if(typeof n.$if=="string"){let r=n.$if.startsWith("!")?n.$if.slice(1):n.$if;e.add(R(r));}else S(n.$if,e);S(n.then,e),n.else!==void 0&&S(n.else,e);return}if(b(n)){for(let r=0;r<n.$pipe.length;r++)S(n.$pipe[r],e);return}if(T(n)){if(n.args)for(let r=0;r<n.args.length;r++)S(n.args[r],e);return}if(y(n)){e.add(R(n.path)),n.value!==void 0&&conditions.isRef(n.value)&&e.add(R(n.value.$));return}if(E(n)){for(let r=0;r<n.conditions.length;r++)S(n.conditions[r],e);return}let i=n,t=Object.keys(i);for(let r=0;r<t.length;r++)S(i[t[r]],e);}function gn(n){return w(n).length>0}function yn(n){return w(n).length===0}function En(n){return JSON.stringify(n)}function F(n,e={}){let i=e.scope??{},t=e.accessor,r=C(n,i,t),f=w(n),o=En(n);return {fn:r,deps:f,hash:o}}function C(n,e,i){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let t=n.map(r=>C(r,e,i));return r=>t.map(f=>f(r))}if(g(n))return hn(n,i);if(h(n))return Tn(n,e,i);if(b(n))return bn(n,e,i);if(T(n))return Cn(n,e,i);if(y(n))return conditions.compile(n,i?{accessor:i}:void 0);if(E(n))return conditions.compile(n,i?{accessor:i}:void 0);if(D(n)){let t=n,r=Object.keys(t),f=r.map(o=>C(t[o],e,i));return o=>{let s={};for(let u=0;u<r.length;u++)s[r[u]]=f[u](o);return s}}return ()=>n}function K(n,e){return e?i=>e(n,i):O(n)}function hn(n,e){return K(n.$,e)}function Tn(n,e,i){let t;if(typeof n.$if=="string"){let o=n.$if.startsWith("!")?n.$if.slice(1):n.$if,s=K(o,i);t=n.$if.startsWith("!")?a=>!s(a):a=>!!s(a);}else {let o=C(n.$if,e,i);t=s=>!!o(s);}let r=C(n.then,e,i),f=n.else!==void 0?C(n.else,e,i):()=>{};return o=>t(o)?r(o):f(o)}function bn(n,e,i){let t=n.$pipe;if(t.length===0)return ()=>{};if(t.length===1)return C(t[0],e,i);let r=C(t[0],e,i),f=t.slice(1).map(s=>C(s,e,i)),o=f.length;if(o===1){let[s]=f;return u=>{let a=r(u),c=s(u);return typeof c=="function"?c(a):c}}if(o===2){let[s,u]=f;return a=>{let c=r(a),p=s(a);return c=typeof p=="function"?p(c):p,p=u(a),typeof p=="function"?p(c):p}}if(o===3){let[s,u,a]=f;return c=>{let p=r(c),d=s(c);return p=typeof d=="function"?d(p):d,d=u(c),p=typeof d=="function"?d(p):d,d=a(c),typeof d=="function"?d(p):d}}return s=>{let u=r(s);for(let a=0;a<o;a++){let c=f[a](s);u=typeof c=="function"?c(u):c;}return u}}function Cn(n,e,i){let t=n.$fn,r=n.args;if(r===void 0)return ()=>{let s=e[t];if(!s)throw new Error(`Function not found in scope: ${t}`);return s};let f=r.map(s=>C(s,e,i)),o=f.length;if(o===0)return s=>{let u=e[t];if(!u)throw new Error(`Function not found in scope: ${t}`);return u()};if(o===1){let[s]=f;return u=>{let a=e[t];if(!a)throw new Error(`Function not found in scope: ${t}`);return a(s(u))}}if(o===2){let[s,u]=f;return a=>{let c=e[t];if(!c)throw new Error(`Function not found in scope: ${t}`);return c(s(a),u(a))}}if(o===3){let[s,u,a]=f;return c=>{let p=e[t];if(!p)throw new Error(`Function not found in scope: ${t}`);return p(s(c),u(c),a(c))}}return s=>{let u=e[t];if(!u)throw new Error(`Function not found in scope: ${t}`);return u(...f.map(a=>a(s)))}}function $n(n,e,i={}){return F(n,i).fn(e)}var v=class{constructor(e=1e3){this.cache=new Map,this._maxSize=e;}get(e,i={}){let t=JSON.stringify(e),r=this.cache.get(t);if(r)return this.cache.delete(t),this.cache.set(t,r),r;let f=F(e,i);if(this.cache.size>=this._maxSize){let o=this.cache.keys().next().value;o&&this.cache.delete(o);}return this.cache.set(t,f),f}has(e){return this.cache.has(JSON.stringify(e))}delete(e){return this.cache.delete(JSON.stringify(e))}clear(){this.cache.clear();}get size(){return this.cache.size}get maxSize(){return this._maxSize}set maxSize(e){for(this._maxSize=e;this.cache.size>this._maxSize;){let i=this.cache.keys().next().value;i&&this.cache.delete(i);}}},Y=new v;function Sn(n,e={}){return Y.get(n,e)}function I(n,e="root",i={}){let t=[];return k(n,e,t,i),{valid:t.length===0,errors:t}}function k(n,e,i,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let o=0;o<n.length;o++)k(n[o],`${e}[${o}]`,i,t);return}if(g(n)){(!n.$||typeof n.$!="string")&&i.push(`${e}: invalid reference, $ must be non-empty string`);return}if(h(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||i.push(`${e}.$if: empty path in string shorthand`):k(n.$if,`${e}.$if`,i,t),k(n.then,`${e}.then`,i,t),n.else!==void 0&&k(n.else,`${e}.else`,i,t);return}if(b(n)){if(!Array.isArray(n.$pipe)){i.push(`${e}.$pipe: must be an array`);return}if(n.$pipe.length===0){i.push(`${e}.$pipe: must have at least one element`);return}for(let o=0;o<n.$pipe.length;o++)k(n.$pipe[o],`${e}.$pipe[${o}]`,i,t);return}if(T(n)){if(!n.$fn||typeof n.$fn!="string"){i.push(`${e}: invalid function, $fn must be non-empty string`);return}if(t.scope&&!(n.$fn in t.scope)&&i.push(`${e}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))i.push(`${e}.args: must be an array`);else for(let o=0;o<n.args.length;o++)k(n.args[o],`${e}.args[${o}]`,i,t);return}if(y(n)){let o=conditions.validate(n,e);o.valid||i.push(...o.errors);return}if(E(n)){let o=conditions.validate(n,e);o.valid||i.push(...o.errors);return}let r=n,f=Object.keys(r);for(let o=0;o<f.length;o++){let s=f[o];k(r[s],`${e}.${s}`,i,t);}}function An(n,e={}){let i=I(n,"root",e);if(!i.valid)throw new Error(`Invalid expression: ${i.errors.join("; ")}`)}function kn(n,e={}){return I(n,"root",e).valid}var Z={};rn(Z,{$:()=>Q,$fn:()=>U,$if:()=>xn,$pipe:()=>X,fn:()=>Rn,pipe:()=>On,ref:()=>wn});function Q(n){return {$:n}}var wn=Q;function U(n,e){return e===void 0||e.length===0?{$fn:n}:{$fn:n,args:e}}var Rn=U;function xn(n,e,i){return i===void 0?{$if:n,then:e}:{$if:n,then:e,else:i}}function X(...n){return {$pipe:n}}var On=X;var L="data",P="scope",Fn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function W(n,e={}){let{dataParam:i=L,scopeParam:t=P,noPrefixes:r=false,useAccessor:f=false,lexicalPrefix:o}=e;return m(n,i,t,r,f,o)}function m(n,e,i,t,r,f){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(o=>m(o,e,i,t,r,f)));if(g(n))return vn(n.$,e,t,r,f);if(h(n))return jn(n,e,i,t,r,f);if(b(n))return Wn(n.$pipe,e,i,t,r,f);if(T(n))return Gn(n,e,i,t,r,f);if(y(n))return zn(n,e,i,t,r,f);if(E(n))return Mn(n,e,i,t,r,f);if(typeof n=="object"){let s=Object.entries(n).map(([u,a])=>omniAst.builders.property(omniAst.builders.identifier(u),m(a,e,i,t,r,f)));return omniAst.builders.objectExpression(s)}return omniAst.builders.literal(null)}var N="accessor";function j(n,e){return e?n===e||n.startsWith(e+"."):false}function vn(n,e,i,t,r){return t?j(n,r)?A(n,e,true):omniAst.builders.callExpression(omniAst.builders.identifier(N),[omniAst.builders.literal(n),omniAst.builders.identifier(e)]):n.includes("[*]")?Nn(n,e,i):A(n,e,i)}function A(n,e,i){let t=G(n);if(t.length===0)return i?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(e);let r;if(i){let f=t[0];r=omniAst.builders.identifier(f.value);for(let o=1;o<t.length;o++){let s=t[o];s.type==="key"?r=omniAst.builders.memberExpression(r,omniAst.builders.identifier(s.value),false,true):r=omniAst.builders.memberExpression(r,omniAst.builders.literal(s.value),true,true);}}else {r=omniAst.builders.identifier(e);for(let f of t)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);}return r}function Nn(n,e,i){let t=n.indexOf("[*]"),r=n.slice(0,t),f=n.slice(t+3),o;if(r?o=A(r,e,i):o=i?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(e),!f||f==="")return o;if(f.includes("[*]"))return nn(o,f);let s="_i",u=f.startsWith(".")?f.slice(1):f,a=omniAst.builders.identifier(s);if(u){let c=G(u);for(let p of c)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(o,omniAst.builders.identifier("map"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(s)],a)])}function nn(n,e){let i=e.indexOf("[*]"),t=e.slice(0,i),r=e.slice(i+3),f="_i",o=t.startsWith(".")?t.slice(1):t,s=omniAst.builders.identifier(f);if(o){let a=G(o);for(let c of a)c.type==="key"&&(s=omniAst.builders.memberExpression(s,omniAst.builders.identifier(c.value),false,true));}if(r.includes("[*]")){let a=nn(s,r);return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(f)],a)])}let u=r.startsWith(".")?r.slice(1):r;if(u){let a=G(u);for(let c of a)c.type==="key"&&(s=omniAst.builders.memberExpression(s,omniAst.builders.identifier(c.value),false,true));}return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(f)],s)])}function jn(n,e,i,t,r,f){let o;if(typeof n.$if=="string"){let a=n.$if.startsWith("!"),c=a?n.$if.slice(1):n.$if,p;r?j(c,f)?p=A(c,e,true):p=omniAst.builders.callExpression(omniAst.builders.identifier(N),[omniAst.builders.literal(c),omniAst.builders.identifier(e)]):p=A(c,e,t),o=a?omniAst.builders.unaryExpression("!",p):p;}else o=m(n.$if,e,i,t,r,f);let s=m(n.then,e,i,t,r,f),u=n.else!==void 0?m(n.else,e,i,t,r,f):omniAst.builders.identifier("undefined");return omniAst.builders.conditionalExpression(o,s,u)}function Gn(n,e,i,t,r,f){let o=t?omniAst.builders.identifier(n.$fn):omniAst.builders.memberExpression(omniAst.builders.identifier(i),omniAst.builders.identifier(n.$fn),false,false);if(n.args===void 0)return o;let s=n.args.map(u=>m(u,e,i,t,r,f));return omniAst.builders.callExpression(o,s)}function Wn(n,e,i,t,r,f){if(n.length===0)return omniAst.builders.identifier("undefined");if(n.length===1)return m(n[0],e,i,t,r,f);let o=m(n[0],e,i,t,r,f);for(let s=1;s<n.length;s++){let u=m(n[s],e,i,t,r,f);o=omniAst.builders.callExpression(u,[o]);}return o}function zn(n,e,i,t,r,f){let o;r?j(n.path,f)?o=A(n.path,e,true):o=omniAst.builders.callExpression(omniAst.builders.identifier(N),[omniAst.builders.literal(n.path),omniAst.builders.identifier(e)]):o=A(n.path,e,t);let s=n.value!==void 0?g(n.value)?r?j(n.value.$,f)?A(n.value.$,e,true):omniAst.builders.callExpression(omniAst.builders.identifier(N),[omniAst.builders.literal(n.value.$),omniAst.builders.identifier(e)]):A(n.value.$,e,t):m(n.value,e,i,t,r,f):omniAst.builders.literal(null),u=Fn[n.op];if(u)return omniAst.builders.binaryExpression(u,o,s);switch(n.op){case "in":return omniAst.builders.callExpression(omniAst.builders.memberExpression(s,omniAst.builders.identifier("includes")),[o]);case "notIn":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(s,omniAst.builders.identifier("includes")),[o]));case "contains":return omniAst.builders.callExpression(omniAst.builders.memberExpression(o,omniAst.builders.identifier("includes"),false,true),[s]);case "notContains":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(o,omniAst.builders.identifier("includes"),false,true),[s]));case "exists":return omniAst.builders.binaryExpression("!=",o,omniAst.builders.literal(null));case "notExists":return omniAst.builders.binaryExpression("==",o,omniAst.builders.literal(null));case "matches":return omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[s]),omniAst.builders.identifier("test")),[o]);case "notMatches":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[s]),omniAst.builders.identifier("test")),[o]));case "startsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(o,omniAst.builders.identifier("startsWith"),false,true),[s]);case "endsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(o,omniAst.builders.identifier("endsWith"),false,true),[s]);default:return omniAst.builders.binaryExpression("===",o,s)}}function Mn(n,e,i,t,r,f){let{logic:o,conditions:s}=n,u=o==="AND"?"&&":"||";if(s.length===0)return omniAst.builders.literal(o==="AND");if(s.length===1)return m(s[0],e,i,t,r,f);let a=m(s[0],e,i,t,r,f);for(let c=1;c<s.length;c++){let p=m(s[c],e,i,t,r,f);a=omniAst.builders.logicalExpression(u,a,p);}return a}function G(n){let e=[],i=n.length,t=0,r="";for(;t<i;){let f=n[t];if(f===".")r&&(e.push({type:"key",value:r}),r=""),t++;else if(f==="["){r&&(e.push({type:"key",value:r}),r=""),t++;let o=t;for(;t<i&&n[t]!=="]";)t++;let s=n.slice(o,t);if(t++,s!=="*"){let u=parseInt(s,10);e.push({type:"index",value:isNaN(u)?s:u});}}else r+=f,t++;}return r&&e.push({type:"key",value:r}),e}function en(n,e=[L]){return omniAst.builders.arrowFunctionExpression(e.map(i=>omniAst.builders.identifier(i)),n)}function z(n){let e=new Set;return $(n,e),e}function $(n,e){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let t of n)$(t,e);return}if(g(n))return;if(h(n)){$(n.$if,e),$(n.then,e),n.else!==void 0&&$(n.else,e);return}if(b(n)){for(let t of n.$pipe)$(t,e);return}if(T(n)){if(e.add(n.$fn),n.args)for(let t of n.args)$(t,e);return}if(y(n)){n.value!==void 0&&typeof n.value=="object"&&$(n.value,e);return}if(E(n)){for(let t of n.conditions)$(t,e);return}let i=n;for(let t of Object.keys(i))$(i[t],e);}function M(n){let e=new Set;for(let i of n){let t=i.indexOf("."),r=i.indexOf("["),f=i.length;t!==-1&&(f=Math.min(f,t)),r!==-1&&(f=Math.min(f,r));let o=i.slice(0,f);o&&e.add(o);}return e}function In(n){return JSON.stringify(n)}function Ln(n,e,i,t,r){let f=W(n,{noPrefixes:true,useAccessor:t,lexicalPrefix:r}),o=omniAst.generate(f),s="";t?r&&(s=`const{${r}}=data??{};`):e.size>0&&(s=`const{${[...e].join(",")}}=data??{};`);let u=t?new Set([...i,"accessor"]):i,a=u.size>0?`const{${[...u].join(",")}}=scope;`:"";return a?`(function(scope){${a}return function(data){${s}return ${o}}})`:`(function(){return function(data){${s}return ${o}}})`}function V(n,e={}){let{scope:i={},returnCode:t=false,useAccessor:r=false,lexicalPrefix:f}=e,o=w(n),s=M(o),u=z(n),a=In(n),c=Ln(n,s,u,r,f);if(t)return {code:c,deps:o,hash:a,dataRoots:[...s],scopeFns:[...u]};let p;try{p=new Function(`return ${c}`)()(i);}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:o,hash:a}}function tn(n,e,i={}){let{fn:t}=V(n,i);return t(e)}var he="0.1.1";exports.ExpressionCache=v;exports.VERSION=he;exports.assertValid=An;exports.builders=Z;exports.cache=Y;exports.cached=Sn;exports.clearPathCache=pn;exports.compile=F;exports.compileAST=V;exports.compilePath=O;exports.dslToAST=W;exports.evaluate=$n;exports.evaluateAST=tn;exports.extractDataRoots=M;exports.extractDeps=w;exports.extractScopeFns=z;exports.get=cn;exports.getPathCacheSize=dn;exports.hasDeps=gn;exports.hasWildcard=J;exports.isCondition=y;exports.isConditionExpr=sn;exports.isConditionGroup=E;exports.isConditional=h;exports.isFn=T;exports.isLiteral=D;exports.isPipe=b;exports.isPure=yn;exports.isRef=g;exports.isValid=kn;exports.normalizePath=R;exports.validate=I;exports.wrapInFunction=en;
1
+ 'use strict';var omniAst=require('omni-ast');var on=Object.defineProperty;var rn=(n,t)=>{for(var s in t)on(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"]),h=n=>n!==null&&typeof n=="object"&&"left"in n&&"op"in n&&x.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),E=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,sn=n=>h(n)||E(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,e="left"in s&&"op"in s&&x.has(s.op);return !("$"in s)&&!("$if"in s)&&!("$fn"in s)&&!("$pipe"in s)&&!e&&!("logic"in s)}return false};var R=new Map;function q(n){let t=[],s=n.length,e=0,r="";for(;e<s;){let o=n[e];if(o===".")r&&(t.push({type:"key",value:r}),r=""),e++;else if(o==="["){r&&(t.push({type:"key",value:r}),r=""),e++;let i=e;for(;e<s&&n[e]!=="]";)e++;let f=n.slice(i,e);if(e++,f==="*")t.push({type:"wildcard",value:"*"});else {let l=parseInt(f,10);t.push({type:"index",value:isNaN(l)?f:l});}}else r+=o,e++;}return r&&t.push({type:"key",value:r}),t}function J(n){return n.includes("[*]")}function O(n){let t=R.get(n);return t||(t=J(n)?un(n):fn(n),R.set(n,t),t)}function fn(n){if(!n.includes(".")&&!n.includes("["))return r=>r?.[n];let t=q(n),s=t.length;if(s===2){let[r,o]=t,i=r.value,f=o.value;return l=>l?.[i]?.[f]}if(s===3){let[r,o,i]=t,f=r.value,l=o.value,c=i.value;return a=>a?.[f]?.[l]?.[c]}let e=t.map(r=>r.value);return r=>{let o=r;for(let i=0;i<s&&o!=null;i++)o=o[e[i]];return o}}function un(n){let t=q(n),s=[];for(let e=0;e<t.length;e++)t[e].type==="wildcard"&&s.push(e);return s.length===1?ln(t,s[0]):cn(t,s)}function ln(n,t){let s=n.slice(0,t).map(i=>i.value),e=n.slice(t+1).map(i=>i.value),r=s.length,o=e.length;if(o===0){if(r===1){let i=s[0];return f=>f?.[i]}return i=>{let f=i;for(let l=0;l<r&&f!=null;l++)f=f[s[l]];return f}}if(o===1){let i=e[0];if(r===1){let f=s[0];return l=>{let c=l?.[f];if(Array.isArray(c))return c.map(a=>a?.[i])}}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?.[i])}}return i=>{let f=i;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[e[a]];return c})}}function cn(n,t){let s=[],e=0;for(let o=0;o<t.length;o++){let i=t[o],f=o===t.length-1,l=n.slice(e,i).map(c=>c.value);l.length>0&&s.push({type:"access",keys:l}),s.push({type:f?"map":"flatMap",keys:[]}),e=i+1;}let r=n.slice(e).map(o=>o.value);return o=>{let i=o;for(let f of s){if(i==null)return;if(f.type==="access")for(let l of f.keys){if(i==null)return;i=i[l];}else if(f.type==="flatMap"){if(!Array.isArray(i))return;i=i.flatMap(l=>{let c=l;return Array.isArray(c)?c:[c]});}else if(f.type==="map"){if(!Array.isArray(i))return;r.length>0&&(i=i.map(l=>{let c=l;for(let a of r){if(c==null)return;c=c[a];}return c}));}}return i}}function an(n,t){return O(t)(n)}function F(n){let t=n.indexOf("[*]");return t===-1?n:n.slice(0,t)}function pn(){R.clear();}function dn(){return R.size}function k(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++){let o=n.args[r];typeof o!="function"&&A(o,t);}return}if(h(n)){A(n.left,t),n.right!==void 0&&A(n.right,t);return}if(E(n)){for(let r=0;r<n.conditions.length;r++)A(n.conditions[r],t);return}let s=n,e=Object.keys(s);for(let r=0;r<e.length;r++)A(s[e[r]],t);}function gn(n){return k(n).length>0}function mn(n){return k(n).length===0}function yn(n){return JSON.stringify(n)}function N(n,t={}){let s=t.scope??{},e=t.accessor,r=m(n,s,e),o=k(n),i=yn(n);return {fn:r,deps:o,hash:i}}function m(n,t,s){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let e=n.map(r=>m(r,t,s));return r=>e.map(o=>o(r))}if(y(n))return hn(n,s);if(T(n))return En(n,t,s);if(C(n))return Tn(n,t,s);if(b(n))return bn(n,t,s);if(h(n))return Cn(n,t,s);if(E(n))return An(n,t,s);if(I(n)){let e=n,r=Object.keys(e),o=r.map(i=>m(e[i],t,s));return i=>{let f={};for(let l=0;l<r.length;l++)f[r[l]]=o[l](i);return f}}return ()=>n}function B(n,t){return t?s=>t(n,s):O(n)}function hn(n,t){return B(n.$,t)}function En(n,t,s){let e;if(typeof n.$if=="string"){let i=n.$if.startsWith("!")?n.$if.slice(1):n.$if,f=B(i,s);e=n.$if.startsWith("!")?c=>!f(c):c=>!!f(c);}else {let i=m(n.$if,t,s);e=f=>!!i(f);}let r=m(n.then,t,s),o=n.else!==void 0?m(n.else,t,s):()=>{};return i=>e(i)?r(i):o(i)}function Tn(n,t,s){let e=n.$pipe;if(e.length===0)return ()=>{};if(e.length===1)return m(e[0],t,s);let r=m(e[0],t,s),o=e.slice(1).map(f=>m(f,t,s)),i=o.length;if(i===1){let[f]=o;return l=>{let c=r(l),a=f(l);return typeof a=="function"?a(c):a}}if(i===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(i===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<i;c++){let a=o[c](f);l=typeof a=="function"?a(l):a;}return l}}function bn(n,t,s){let e=n.$fn,r=n.args;if(r===void 0)return ()=>{let f=t[e];if(!f)throw new Error(`Function not found in scope: ${e}`);return f};let o=r.map(f=>typeof f=="function"?()=>f:m(f,t,s)),i=o.length;if(i===0)return f=>{let l=t[e];if(!l)throw new Error(`Function not found in scope: ${e}`);return l()};if(i===1){let[f]=o;return l=>{let c=t[e];if(!c)throw new Error(`Function not found in scope: ${e}`);return c(f(l))}}if(i===2){let[f,l]=o;return c=>{let a=t[e];if(!a)throw new Error(`Function not found in scope: ${e}`);return a(f(c),l(c))}}if(i===3){let[f,l,c]=o;return a=>{let p=t[e];if(!p)throw new Error(`Function not found in scope: ${e}`);return p(f(a),l(a),c(a))}}return f=>{let l=t[e];if(!l)throw new Error(`Function not found in scope: ${e}`);return l(...o.map(c=>c(f)))}}function Cn(n,t,s){let e=m(n.left,t,s),r=n.right!==void 0?m(n.right,t,s):()=>{};switch(n.op){case "eq":return o=>e(o)===r(o);case "neq":return o=>e(o)!==r(o);case "gt":return o=>e(o)>r(o);case "gte":return o=>e(o)>=r(o);case "lt":return o=>e(o)<r(o);case "lte":return o=>e(o)<=r(o);case "in":return o=>{let i=r(o);return Array.isArray(i)&&i.includes(e(o))};case "notIn":return o=>{let i=r(o);return !Array.isArray(i)||!i.includes(e(o))};case "contains":return o=>{let i=e(o);return Array.isArray(i)&&i.includes(r(o))};case "notContains":return o=>{let i=e(o);return !Array.isArray(i)||!i.includes(r(o))};case "exists":return o=>e(o)!==void 0;case "notExists":return o=>e(o)===void 0;case "matches":return o=>{let i=e(o),f=r(o);return typeof i!="string"||typeof f!="string"?false:new RegExp(f).test(i)};case "notMatches":return o=>{let i=e(o),f=r(o);return typeof i!="string"||typeof f!="string"?true:!new RegExp(f).test(i)};case "startsWith":return o=>{let i=e(o),f=r(o);return typeof i=="string"&&typeof f=="string"&&i.startsWith(f)};case "endsWith":return o=>{let i=e(o),f=r(o);return typeof i=="string"&&typeof f=="string"&&i.endsWith(f)}}}function An(n,t,s){let e=n.conditions.map(o=>m(o,t,s)),r=e.length;if(r===1)return o=>!!e[0](o);if(r===2){let[o,i]=e;return n.logic==="AND"?f=>!!o(f)&&!!i(f):f=>!!o(f)||!!i(f)}if(r===3){let[o,i,f]=e;return n.logic==="AND"?l=>!!o(l)&&!!i(l)&&!!f(l):l=>!!o(l)||!!i(l)||!!f(l)}return n.logic==="AND"?o=>{for(let i=0;i<r;i++)if(!e[i](o))return false;return true}:o=>{for(let i=0;i<r;i++)if(e[i](o))return true;return false}}function $n(n,t,s={}){return N(n,s).fn(t)}var v=class{constructor(t=1e3){this.cache=new Map,this._maxSize=t;}get(t,s={}){let e=JSON.stringify(t),r=this.cache.get(e);if(r)return this.cache.delete(e),this.cache.set(e,r),r;let o=N(t,s);if(this.cache.size>=this._maxSize){let i=this.cache.keys().next().value;i&&this.cache.delete(i);}return this.cache.set(e,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);}}},K=new v;function Sn(n,t={}){return K.get(n,t)}function M(n,t="root",s={}){let e=[];return $(n,t,e,s),{valid:e.length===0,errors:e}}function $(n,t,s,e){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let i=0;i<n.length;i++)$(n[i],`${t}[${i}]`,s,e);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,e),$(n.then,`${t}.then`,s,e),n.else!==void 0&&$(n.else,`${t}.else`,s,e);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 i=0;i<n.$pipe.length;i++)$(n.$pipe[i],`${t}.$pipe[${i}]`,s,e);return}if(b(n)){if(!n.$fn||typeof n.$fn!="string"){s.push(`${t}: invalid function, $fn must be non-empty string`);return}if(e.scope&&!(n.$fn in e.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 i=0;i<n.args.length;i++){let f=n.args[i];typeof f!="function"&&$(f,`${t}.args[${i}]`,s,e);}return}if(h(n)){x.has(n.op)||s.push(`${t}: invalid operator "${n.op}"`),$(n.left,`${t}.left`,s,e),n.right!==void 0&&$(n.right,`${t}.right`,s,e);return}if(E(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 i=0;i<n.conditions.length;i++)$(n.conditions[i],`${t}.conditions[${i}]`,s,e);return}let r=n,o=Object.keys(r);for(let i=0;i<o.length;i++){let f=o[i];$(r[f],`${t}.${f}`,s,e);}}function kn(n,t={}){let s=M(n,"root",t);if(!s.valid)throw new Error(`Invalid expression: ${s.errors.join("; ")}`)}function wn(n,t={}){return M(n,"root",t).valid}var U={};rn(U,{$:()=>P,$cond:()=>Q,$fn:()=>Y,$if:()=>On,$pipe:()=>H,cond:()=>Nn,fn:()=>Rn,pipe:()=>Fn,ref:()=>xn});function P(n){return {$:n}}var xn=P;function Y(n,t){return t===void 0||t.length===0?{$fn:n}:{$fn:n,args:t}}var Rn=Y;function On(n,t,s){return s===void 0?{$if:n,then:t}:{$if:n,then:t,else:s}}function H(...n){return {$pipe:n}}var Fn=H;function Q(n,t,s){return s===void 0?{left:n,op:t}:{left:n,op:t,right:s}}var Nn=Q;var z="data",Z="scope",vn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function G(n,t={}){let{dataParam:s=z,scopeParam:e=Z,noPrefixes:r=false,useAccessor:o=false,lexicalPrefix:i}=t;return g(n,s,e,r,o,i)}function g(n,t,s,e,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(i=>g(i,t,s,e,r,o)));if(y(n))return jn(n.$,t,e,r,o);if(T(n))return Wn(n,t,s,e,r,o);if(C(n))return In(n.$pipe,t,s,e,r,o);if(b(n))return Dn(n,t,s,e,r,o);if(h(n))return Mn(n,t,s,e,r,o);if(E(n))return zn(n,t,s,e,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,e,r,o)));return omniAst.builders.objectExpression(f)}return omniAst.builders.literal(null)}var L="accessor";function V(n,t){return t?n===t||n.startsWith(t+"."):false}function jn(n,t,s,e,r){return e?V(n,r)?w(n,t,true):omniAst.builders.callExpression(omniAst.builders.identifier(L),[omniAst.builders.literal(n),omniAst.builders.identifier(t)]):n.includes("[*]")?Gn(n,t,s):w(n,t,s)}function w(n,t,s){let e=j(n);if(e.length===0)return s?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(t);let r;if(s){let o=e[0];r=omniAst.builders.identifier(o.value);for(let i=1;i<e.length;i++){let f=e[i];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 e)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 Gn(n,t,s){let e=n.indexOf("[*]"),r=n.slice(0,e),o=n.slice(e+3),i;if(r?i=w(r,t,s):i=s?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(t),!o||o==="")return i;if(o.includes("[*]"))return nn(i,o);let f="_i",l=o.startsWith(".")?o.slice(1):o,c=omniAst.builders.identifier(f);if(l){let a=j(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(i,omniAst.builders.identifier("map"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(f)],c)])}function nn(n,t){let s=t.indexOf("[*]"),e=t.slice(0,s),r=t.slice(s+3),o="_i",i=e.startsWith(".")?e.slice(1):e,f=omniAst.builders.identifier(o);if(i){let c=j(i);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=nn(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=j(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 Wn(n,t,s,e,r,o){let i;if(typeof n.$if=="string"){let c=n.$if.startsWith("!"),a=c?n.$if.slice(1):n.$if,p;r?V(a,o)?p=w(a,t,true):p=omniAst.builders.callExpression(omniAst.builders.identifier(L),[omniAst.builders.literal(a),omniAst.builders.identifier(t)]):p=w(a,t,e),i=c?omniAst.builders.unaryExpression("!",p):p;}else i=g(n.$if,t,s,e,r,o);let f=g(n.then,t,s,e,r,o),l=n.else!==void 0?g(n.else,t,s,e,r,o):omniAst.builders.identifier("undefined");return omniAst.builders.conditionalExpression(i,f,l)}function Dn(n,t,s,e,r,o){let i=e?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 i;let f=n.args.map(l=>typeof l=="function"?omniAst.builders.literal(null):g(l,t,s,e,r,o));return omniAst.builders.callExpression(i,f)}function In(n,t,s,e,r,o){if(n.length===0)return omniAst.builders.identifier("undefined");if(n.length===1)return g(n[0],t,s,e,r,o);let i=g(n[0],t,s,e,r,o);for(let f=1;f<n.length;f++){let l=g(n[f],t,s,e,r,o);i=omniAst.builders.callExpression(l,[i]);}return i}function X(n,t,s,e,r,o){if(y(n)){let i=n.$;return r?V(i,o)?w(i,t,true):omniAst.builders.callExpression(omniAst.builders.identifier(L),[omniAst.builders.literal(i),omniAst.builders.identifier(t)]):w(i,t,e)}return g(n,t,s,e,r,o)}function Mn(n,t,s,e,r,o){let i=X(n.left,t,s,e,r,o),f=n.right!==void 0?X(n.right,t,s,e,r,o):omniAst.builders.literal(null),l=vn[n.op];if(l)return omniAst.builders.binaryExpression(l,i,f);switch(n.op){case "in":return omniAst.builders.callExpression(omniAst.builders.memberExpression(f,omniAst.builders.identifier("includes")),[i]);case "notIn":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(f,omniAst.builders.identifier("includes")),[i]));case "contains":return omniAst.builders.callExpression(omniAst.builders.memberExpression(i,omniAst.builders.identifier("includes"),false,true),[f]);case "notContains":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(i,omniAst.builders.identifier("includes"),false,true),[f]));case "exists":return omniAst.builders.binaryExpression("!=",i,omniAst.builders.literal(null));case "notExists":return omniAst.builders.binaryExpression("==",i,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")),[i]);case "notMatches":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[f]),omniAst.builders.identifier("test")),[i]));case "startsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(i,omniAst.builders.identifier("startsWith"),false,true),[f]);case "endsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(i,omniAst.builders.identifier("endsWith"),false,true),[f]);default:return omniAst.builders.binaryExpression("===",i,f)}}function zn(n,t,s,e,r,o){let{logic:i,conditions:f}=n,l=i==="AND"?"&&":"||";if(f.length===0)return omniAst.builders.literal(i==="AND");if(f.length===1)return g(f[0],t,s,e,r,o);let c=g(f[0],t,s,e,r,o);for(let a=1;a<f.length;a++){let p=g(f[a],t,s,e,r,o);c=omniAst.builders.logicalExpression(l,c,p);}return c}function j(n){let t=[],s=n.length,e=0,r="";for(;e<s;){let o=n[e];if(o===".")r&&(t.push({type:"key",value:r}),r=""),e++;else if(o==="["){r&&(t.push({type:"key",value:r}),r=""),e++;let i=e;for(;e<s&&n[e]!=="]";)e++;let f=n.slice(i,e);if(e++,f!=="*"){let l=parseInt(f,10);t.push({type:"index",value:isNaN(l)?f:l});}}else r+=o,e++;}return r&&t.push({type:"key",value:r}),t}function tn(n,t=[z]){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 e of n)S(e,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 e of n.$pipe)S(e,t);return}if(b(n)){if(t.add(n.$fn),n.args)for(let e of n.args)typeof e!="function"&&S(e,t);return}if(h(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(E(n)){for(let e of n.conditions)S(e,t);return}let s=n;for(let e of Object.keys(s))S(s[e],t);}function D(n){let t=new Set;for(let s of n){let e=s.indexOf("."),r=s.indexOf("["),o=s.length;e!==-1&&(o=Math.min(o,e)),r!==-1&&(o=Math.min(o,r));let i=s.slice(0,o);i&&t.add(i);}return t}function Vn(n){return JSON.stringify(n)}function _n(n,t,s,e,r){let o=G(n,{noPrefixes:true,useAccessor:e,lexicalPrefix:r}),i=omniAst.generate(o),f="";e?r&&(f=`const{${r}}=data??{};`):t.size>0&&(f=`const{${[...t].join(",")}}=data??{};`);let l=e?new Set([...s,"accessor"]):s,c=l.size>0?`const{${[...l].join(",")}}=scope;`:"";return c?`(function(scope){${c}return function(data){${f}return ${i}}})`:`(function(){return function(data){${f}return ${i}}})`}function _(n,t={}){let{scope:s={},returnCode:e=false,useAccessor:r=false,lexicalPrefix:o}=t,i=k(n),f=D(i),l=W(n),c=Vn(n),a=_n(n,f,l,r,o);if(e)return {code:a,deps:i,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:i,hash:c}}function en(n,t,s={}){let{fn:e}=_(n,s);return e(t)}var ht="0.1.1";exports.ExpressionCache=v;exports.VERSION=ht;exports.assertValid=kn;exports.builders=U;exports.cache=K;exports.cached=Sn;exports.clearPathCache=pn;exports.compile=N;exports.compileAST=_;exports.compilePath=O;exports.dslToAST=G;exports.evaluate=$n;exports.evaluateAST=en;exports.extractDataRoots=D;exports.extractDeps=k;exports.extractScopeFns=W;exports.get=an;exports.getPathCacheSize=dn;exports.hasDeps=gn;exports.hasWildcard=J;exports.isCondition=h;exports.isConditionExpr=sn;exports.isConditionGroup=E;exports.isConditional=T;exports.isFn=b;exports.isLiteral=I;exports.isPipe=C;exports.isPure=mn;exports.isRef=y;exports.isValid=wn;exports.normalizePath=F;exports.validate=M;exports.wrapInFunction=tn;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,3 @@
1
- import { ConditionExpr, Condition, ConditionGroup } from '@statedelta-libs/conditions';
2
- export { Condition, ConditionExpr, ConditionGroup, Ref } from '@statedelta-libs/conditions';
3
1
  import { types } from 'omni-ast';
4
2
 
5
3
  /**
@@ -7,7 +5,10 @@ import { types } from 'omni-ast';
7
5
  *
8
6
  * Core types for expression compilation.
9
7
  */
10
-
8
+ /**
9
+ * Condition operators
10
+ */
11
+ type ConditionOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "contains" | "notContains" | "exists" | "notExists" | "matches" | "notMatches" | "startsWith" | "endsWith";
11
12
  /**
12
13
  * Reference to a path in data object
13
14
  * @example { "$": "user.name" }
@@ -25,14 +26,26 @@ interface ConditionalExpr {
25
26
  then: Expression;
26
27
  else?: Expression;
27
28
  }
29
+ /**
30
+ * Callback function passed as argument to $fn (predicates, mappers, etc.)
31
+ * These are native JS functions, not DSL expressions.
32
+ * @example (item) => item.active
33
+ * @example (n) => n * 2
34
+ */
35
+ type CallbackFn = (...args: any[]) => any;
36
+ /**
37
+ * Argument to a $fn expression: can be a DSL expression or a native callback
38
+ */
39
+ type FnArg = Expression | CallbackFn;
28
40
  /**
29
41
  * Function call expression
30
42
  * Calls a function from the provided scope with compiled arguments
31
43
  * @example { "$fn": "add", "args": [{ "$": "a" }, { "$": "b" }] }
44
+ * @example { "$fn": "filter", "args": [(item) => item.active] }
32
45
  */
33
46
  interface FnExpr {
34
47
  $fn: string;
35
- args?: Expression[];
48
+ args?: FnArg[];
36
49
  }
37
50
  /**
38
51
  * Pipe expression (DSL syntax for composition with initial value)
@@ -49,16 +62,31 @@ type Literal = string | number | boolean | null | Literal[] | {
49
62
  [key: string]: Literal;
50
63
  };
51
64
  /**
52
- * Callback function - used as argument in $fn (e.g., predicates, mappers)
53
- * Not serializable to JSON, but valid in code.
54
- * @example (item) => item.active
55
- * @example (a, b) => a + b
65
+ * Condition expression - both sides accept any Expression
66
+ * @example { left: { $: "age" }, op: "gte", right: 18 }
67
+ * @example { left: { $fn: "getAge", args: [{ $: "user" }] }, op: "gte", right: 18 }
68
+ */
69
+ interface Condition {
70
+ left: Expression;
71
+ op: ConditionOp;
72
+ right?: Expression;
73
+ }
74
+ /**
75
+ * Condition group with AND/OR logic
76
+ * @example { logic: "AND", conditions: [...] }
56
77
  */
57
- type CallbackFn = (...args: any[]) => unknown;
78
+ interface ConditionGroup {
79
+ logic: "AND" | "OR";
80
+ conditions: Expression[];
81
+ }
82
+ /**
83
+ * Union of condition types
84
+ */
85
+ type ConditionExpr = Condition | ConditionGroup;
58
86
  /**
59
87
  * Union of all expression types
60
88
  */
61
- type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | ConditionExpr | CallbackFn;
89
+ type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | ConditionExpr;
62
90
  /**
63
91
  * Compiled expression function
64
92
  */
@@ -95,7 +123,13 @@ interface ValidationResult {
95
123
  errors: string[];
96
124
  }
97
125
  /**
98
- * Function scope - functions available to $fn expressions
126
+ * Function scope - functions available to $fn expressions.
127
+ *
128
+ * Uses `any` for function parameters because TypeScript's contravariance
129
+ * makes it impossible to assign typed functions like `(a: number, b: number) => number`
130
+ * to `(...args: unknown[]) => unknown`. This is the standard pattern for
131
+ * heterogeneous function registries (similar to Lodash, Ramda, etc.).
132
+ *
99
133
  * @example { add, subtract, multiply, filter, map, sum }
100
134
  */
101
135
  type Scope = Record<string, (...args: any[]) => any>;
@@ -132,16 +166,14 @@ declare const isFn: (v: unknown) => v is FnExpr;
132
166
  */
133
167
  declare const isPipe: (v: unknown) => v is PipeExpr;
134
168
  /**
135
- * Check if value is a condition (from @statedelta-libs/conditions)
169
+ * Check if value is a condition expression
136
170
  *
137
- * IMPORTANT: Must verify that `op` is a valid condition operator,
138
- * not just any string. Effect objects also have `path` and `op`
139
- * properties (e.g., { resource: "x", op: "set", path: "y", value: z })
140
- * but "set" is NOT a condition operator.
171
+ * Verifies `op` is a valid condition operator to distinguish from
172
+ * effect objects that also have `left` and `op` (e.g. op: "set").
141
173
  */
142
174
  declare const isCondition: (v: unknown) => v is Condition;
143
175
  /**
144
- * Check if value is a condition group (from @statedelta-libs/conditions)
176
+ * Check if value is a condition group
145
177
  */
146
178
  declare const isConditionGroup: (v: unknown) => v is ConditionGroup;
147
179
  /**
@@ -408,7 +440,7 @@ declare const ref: typeof $;
408
440
  * $fn("sum") // no args - returns function reference
409
441
  * $fn("now", []) // empty args - calls function
410
442
  */
411
- declare function $fn(name: string, args?: Expression[]): FnExpr;
443
+ declare function $fn(name: string, args?: FnArg[]): FnExpr;
412
444
  /**
413
445
  * Alias for $fn (function builder)
414
446
  */
@@ -442,16 +474,36 @@ declare function $pipe(...steps: Expression[]): PipeExpr;
442
474
  * Alias for $pipe (pipe builder)
443
475
  */
444
476
  declare const pipe: typeof $pipe;
477
+ /**
478
+ * Create a condition expression.
479
+ *
480
+ * @param left - Left side (any expression)
481
+ * @param op - Condition operator
482
+ * @param right - Right side (any expression, optional for exists/notExists)
483
+ * @returns Condition
484
+ *
485
+ * @example
486
+ * $cond($("age"), "gte", 18)
487
+ * $cond($fn("getScore", [$("user")]), "gt", 100)
488
+ * $cond($("email"), "exists")
489
+ */
490
+ declare function $cond(left: Expression, op: ConditionOp, right?: Expression): Condition;
491
+ /**
492
+ * Alias for $cond (condition builder)
493
+ */
494
+ declare const cond: typeof $cond;
445
495
 
446
496
  declare const builders_$: typeof $;
497
+ declare const builders_$cond: typeof $cond;
447
498
  declare const builders_$fn: typeof $fn;
448
499
  declare const builders_$if: typeof $if;
449
500
  declare const builders_$pipe: typeof $pipe;
501
+ declare const builders_cond: typeof cond;
450
502
  declare const builders_fn: typeof fn;
451
503
  declare const builders_pipe: typeof pipe;
452
504
  declare const builders_ref: typeof ref;
453
505
  declare namespace builders {
454
- export { builders_$ as $, builders_$fn as $fn, builders_$if as $if, builders_$pipe as $pipe, builders_fn as fn, builders_pipe as pipe, builders_ref as ref };
506
+ 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 };
455
507
  }
456
508
 
457
509
  /**
@@ -674,4 +726,4 @@ declare function evaluateAST<T = unknown, R = unknown>(expr: Expression, data: T
674
726
  */
675
727
  declare const VERSION = "0.1.1";
676
728
 
677
- export { type AccessorFn, type CallbackFn, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type ConditionalExpr, type Expression, ExpressionCache, type FnExpr, type Literal, type PathGetter, type PipeExpr, type RefExpr, type Scope, type TransformOptions, 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, normalizePath, validate, wrapInFunction };
729
+ export { type AccessorFn, type CallbackFn, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type Expression, ExpressionCache, type FnArg, type FnExpr, type Literal, type PathGetter, type PipeExpr, type RefExpr, type Scope, type TransformOptions, 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, normalizePath, validate, wrapInFunction };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { ConditionExpr, Condition, ConditionGroup } from '@statedelta-libs/conditions';
2
- export { Condition, ConditionExpr, ConditionGroup, Ref } from '@statedelta-libs/conditions';
3
1
  import { types } from 'omni-ast';
4
2
 
5
3
  /**
@@ -7,7 +5,10 @@ import { types } from 'omni-ast';
7
5
  *
8
6
  * Core types for expression compilation.
9
7
  */
10
-
8
+ /**
9
+ * Condition operators
10
+ */
11
+ type ConditionOp = "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "notIn" | "contains" | "notContains" | "exists" | "notExists" | "matches" | "notMatches" | "startsWith" | "endsWith";
11
12
  /**
12
13
  * Reference to a path in data object
13
14
  * @example { "$": "user.name" }
@@ -25,14 +26,26 @@ interface ConditionalExpr {
25
26
  then: Expression;
26
27
  else?: Expression;
27
28
  }
29
+ /**
30
+ * Callback function passed as argument to $fn (predicates, mappers, etc.)
31
+ * These are native JS functions, not DSL expressions.
32
+ * @example (item) => item.active
33
+ * @example (n) => n * 2
34
+ */
35
+ type CallbackFn = (...args: any[]) => any;
36
+ /**
37
+ * Argument to a $fn expression: can be a DSL expression or a native callback
38
+ */
39
+ type FnArg = Expression | CallbackFn;
28
40
  /**
29
41
  * Function call expression
30
42
  * Calls a function from the provided scope with compiled arguments
31
43
  * @example { "$fn": "add", "args": [{ "$": "a" }, { "$": "b" }] }
44
+ * @example { "$fn": "filter", "args": [(item) => item.active] }
32
45
  */
33
46
  interface FnExpr {
34
47
  $fn: string;
35
- args?: Expression[];
48
+ args?: FnArg[];
36
49
  }
37
50
  /**
38
51
  * Pipe expression (DSL syntax for composition with initial value)
@@ -49,16 +62,31 @@ type Literal = string | number | boolean | null | Literal[] | {
49
62
  [key: string]: Literal;
50
63
  };
51
64
  /**
52
- * Callback function - used as argument in $fn (e.g., predicates, mappers)
53
- * Not serializable to JSON, but valid in code.
54
- * @example (item) => item.active
55
- * @example (a, b) => a + b
65
+ * Condition expression - both sides accept any Expression
66
+ * @example { left: { $: "age" }, op: "gte", right: 18 }
67
+ * @example { left: { $fn: "getAge", args: [{ $: "user" }] }, op: "gte", right: 18 }
68
+ */
69
+ interface Condition {
70
+ left: Expression;
71
+ op: ConditionOp;
72
+ right?: Expression;
73
+ }
74
+ /**
75
+ * Condition group with AND/OR logic
76
+ * @example { logic: "AND", conditions: [...] }
56
77
  */
57
- type CallbackFn = (...args: any[]) => unknown;
78
+ interface ConditionGroup {
79
+ logic: "AND" | "OR";
80
+ conditions: Expression[];
81
+ }
82
+ /**
83
+ * Union of condition types
84
+ */
85
+ type ConditionExpr = Condition | ConditionGroup;
58
86
  /**
59
87
  * Union of all expression types
60
88
  */
61
- type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | ConditionExpr | CallbackFn;
89
+ type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | ConditionExpr;
62
90
  /**
63
91
  * Compiled expression function
64
92
  */
@@ -95,7 +123,13 @@ interface ValidationResult {
95
123
  errors: string[];
96
124
  }
97
125
  /**
98
- * Function scope - functions available to $fn expressions
126
+ * Function scope - functions available to $fn expressions.
127
+ *
128
+ * Uses `any` for function parameters because TypeScript's contravariance
129
+ * makes it impossible to assign typed functions like `(a: number, b: number) => number`
130
+ * to `(...args: unknown[]) => unknown`. This is the standard pattern for
131
+ * heterogeneous function registries (similar to Lodash, Ramda, etc.).
132
+ *
99
133
  * @example { add, subtract, multiply, filter, map, sum }
100
134
  */
101
135
  type Scope = Record<string, (...args: any[]) => any>;
@@ -132,16 +166,14 @@ declare const isFn: (v: unknown) => v is FnExpr;
132
166
  */
133
167
  declare const isPipe: (v: unknown) => v is PipeExpr;
134
168
  /**
135
- * Check if value is a condition (from @statedelta-libs/conditions)
169
+ * Check if value is a condition expression
136
170
  *
137
- * IMPORTANT: Must verify that `op` is a valid condition operator,
138
- * not just any string. Effect objects also have `path` and `op`
139
- * properties (e.g., { resource: "x", op: "set", path: "y", value: z })
140
- * but "set" is NOT a condition operator.
171
+ * Verifies `op` is a valid condition operator to distinguish from
172
+ * effect objects that also have `left` and `op` (e.g. op: "set").
141
173
  */
142
174
  declare const isCondition: (v: unknown) => v is Condition;
143
175
  /**
144
- * Check if value is a condition group (from @statedelta-libs/conditions)
176
+ * Check if value is a condition group
145
177
  */
146
178
  declare const isConditionGroup: (v: unknown) => v is ConditionGroup;
147
179
  /**
@@ -408,7 +440,7 @@ declare const ref: typeof $;
408
440
  * $fn("sum") // no args - returns function reference
409
441
  * $fn("now", []) // empty args - calls function
410
442
  */
411
- declare function $fn(name: string, args?: Expression[]): FnExpr;
443
+ declare function $fn(name: string, args?: FnArg[]): FnExpr;
412
444
  /**
413
445
  * Alias for $fn (function builder)
414
446
  */
@@ -442,16 +474,36 @@ declare function $pipe(...steps: Expression[]): PipeExpr;
442
474
  * Alias for $pipe (pipe builder)
443
475
  */
444
476
  declare const pipe: typeof $pipe;
477
+ /**
478
+ * Create a condition expression.
479
+ *
480
+ * @param left - Left side (any expression)
481
+ * @param op - Condition operator
482
+ * @param right - Right side (any expression, optional for exists/notExists)
483
+ * @returns Condition
484
+ *
485
+ * @example
486
+ * $cond($("age"), "gte", 18)
487
+ * $cond($fn("getScore", [$("user")]), "gt", 100)
488
+ * $cond($("email"), "exists")
489
+ */
490
+ declare function $cond(left: Expression, op: ConditionOp, right?: Expression): Condition;
491
+ /**
492
+ * Alias for $cond (condition builder)
493
+ */
494
+ declare const cond: typeof $cond;
445
495
 
446
496
  declare const builders_$: typeof $;
497
+ declare const builders_$cond: typeof $cond;
447
498
  declare const builders_$fn: typeof $fn;
448
499
  declare const builders_$if: typeof $if;
449
500
  declare const builders_$pipe: typeof $pipe;
501
+ declare const builders_cond: typeof cond;
450
502
  declare const builders_fn: typeof fn;
451
503
  declare const builders_pipe: typeof pipe;
452
504
  declare const builders_ref: typeof ref;
453
505
  declare namespace builders {
454
- export { builders_$ as $, builders_$fn as $fn, builders_$if as $if, builders_$pipe as $pipe, builders_fn as fn, builders_pipe as pipe, builders_ref as ref };
506
+ 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 };
455
507
  }
456
508
 
457
509
  /**
@@ -674,4 +726,4 @@ declare function evaluateAST<T = unknown, R = unknown>(expr: Expression, data: T
674
726
  */
675
727
  declare const VERSION = "0.1.1";
676
728
 
677
- export { type AccessorFn, type CallbackFn, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type ConditionalExpr, type Expression, ExpressionCache, type FnExpr, type Literal, type PathGetter, type PipeExpr, type RefExpr, type Scope, type TransformOptions, 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, normalizePath, validate, wrapInFunction };
729
+ export { type AccessorFn, type CallbackFn, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type Expression, ExpressionCache, type FnArg, type FnExpr, type Literal, type PathGetter, type PipeExpr, type RefExpr, type Scope, type TransformOptions, 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, normalizePath, validate, wrapInFunction };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import {isRef,compile,validate}from'@statedelta-libs/conditions';import {builders,generate}from'omni-ast';var on=Object.defineProperty;var rn=(n,e)=>{for(var i in e)on(n,i,{get:e[i],enumerable:true});};var g=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,h=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,T=n=>n!==null&&typeof n=="object"&&"$fn"in n&&typeof n.$fn=="string",b=n=>n!==null&&typeof n=="object"&&"$pipe"in n&&Array.isArray(n.$pipe),_=new Set(["eq","neq","gt","gte","lt","lte","in","notIn","contains","notContains","exists","notExists","matches","notMatches","startsWith","endsWith"]),y=n=>n!==null&&typeof n=="object"&&"path"in n&&"op"in n&&_.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),E=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,sn=n=>y(n)||E(n),D=n=>{if(n===null)return true;let e=typeof n;if(e==="string"||e==="number"||e==="boolean"||Array.isArray(n))return true;if(e==="object"&&n!==null){let i=n,t="path"in i&&"op"in i&&_.has(i.op);return !("$"in i)&&!("$if"in i)&&!("$fn"in i)&&!("$pipe"in i)&&!t&&!("logic"in i)}return false};var x=new Map;function q(n){let e=[],i=n.length,t=0,r="";for(;t<i;){let f=n[t];if(f===".")r&&(e.push({type:"key",value:r}),r=""),t++;else if(f==="["){r&&(e.push({type:"key",value:r}),r=""),t++;let o=t;for(;t<i&&n[t]!=="]";)t++;let s=n.slice(o,t);if(t++,s==="*")e.push({type:"wildcard",value:"*"});else {let u=parseInt(s,10);e.push({type:"index",value:isNaN(u)?s:u});}}else r+=f,t++;}return r&&e.push({type:"key",value:r}),e}function J(n){return n.includes("[*]")}function O(n){let e=x.get(n);return e||(e=J(n)?fn(n):ln(n),x.set(n,e),e)}function ln(n){if(!n.includes(".")&&!n.includes("["))return r=>r?.[n];let e=q(n),i=e.length;if(i===2){let[r,f]=e,o=r.value,s=f.value;return u=>u?.[o]?.[s]}if(i===3){let[r,f,o]=e,s=r.value,u=f.value,a=o.value;return c=>c?.[s]?.[u]?.[a]}let t=e.map(r=>r.value);return r=>{let f=r;for(let o=0;o<i&&f!=null;o++)f=f[t[o]];return f}}function fn(n){let e=q(n),i=[];for(let t=0;t<e.length;t++)e[t].type==="wildcard"&&i.push(t);return i.length===1?un(e,i[0]):an(e,i)}function un(n,e){let i=n.slice(0,e).map(o=>o.value),t=n.slice(e+1).map(o=>o.value),r=i.length,f=t.length;if(f===0){if(r===1){let o=i[0];return s=>s?.[o]}return o=>{let s=o;for(let u=0;u<r&&s!=null;u++)s=s[i[u]];return s}}if(f===1){let o=t[0];if(r===1){let s=i[0];return u=>{let a=u?.[s];if(Array.isArray(a))return a.map(c=>c?.[o])}}return s=>{let u=s;for(let a=0;a<r&&u!=null;a++)u=u[i[a]];if(Array.isArray(u))return u.map(a=>a?.[o])}}return o=>{let s=o;for(let u=0;u<r&&s!=null;u++)s=s[i[u]];if(Array.isArray(s))return s.map(u=>{let a=u;for(let c=0;c<f&&a!=null;c++)a=a[t[c]];return a})}}function an(n,e){let i=[],t=0;for(let f=0;f<e.length;f++){let o=e[f],s=f===e.length-1,u=n.slice(t,o).map(a=>a.value);u.length>0&&i.push({type:"access",keys:u}),i.push({type:s?"map":"flatMap",keys:[]}),t=o+1;}let r=n.slice(t).map(f=>f.value);return f=>{let o=f;for(let s of i){if(o==null)return;if(s.type==="access")for(let u of s.keys){if(o==null)return;o=o[u];}else if(s.type==="flatMap"){if(!Array.isArray(o))return;o=o.flatMap(u=>{let a=u;return Array.isArray(a)?a:[a]});}else if(s.type==="map"){if(!Array.isArray(o))return;r.length>0&&(o=o.map(u=>{let a=u;for(let c of r){if(a==null)return;a=a[c];}return a}));}}return o}}function cn(n,e){return O(e)(n)}function R(n){let e=n.indexOf("[*]");return e===-1?n:n.slice(0,e)}function pn(){x.clear();}function dn(){return x.size}function w(n){let e=new Set;return S(n,e),Array.from(e)}function S(n,e){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r=0;r<n.length;r++)S(n[r],e);return}if(g(n)){e.add(R(n.$));return}if(h(n)){if(typeof n.$if=="string"){let r=n.$if.startsWith("!")?n.$if.slice(1):n.$if;e.add(R(r));}else S(n.$if,e);S(n.then,e),n.else!==void 0&&S(n.else,e);return}if(b(n)){for(let r=0;r<n.$pipe.length;r++)S(n.$pipe[r],e);return}if(T(n)){if(n.args)for(let r=0;r<n.args.length;r++)S(n.args[r],e);return}if(y(n)){e.add(R(n.path)),n.value!==void 0&&isRef(n.value)&&e.add(R(n.value.$));return}if(E(n)){for(let r=0;r<n.conditions.length;r++)S(n.conditions[r],e);return}let i=n,t=Object.keys(i);for(let r=0;r<t.length;r++)S(i[t[r]],e);}function gn(n){return w(n).length>0}function yn(n){return w(n).length===0}function En(n){return JSON.stringify(n)}function F(n,e={}){let i=e.scope??{},t=e.accessor,r=C(n,i,t),f=w(n),o=En(n);return {fn:r,deps:f,hash:o}}function C(n,e,i){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let t=n.map(r=>C(r,e,i));return r=>t.map(f=>f(r))}if(g(n))return hn(n,i);if(h(n))return Tn(n,e,i);if(b(n))return bn(n,e,i);if(T(n))return Cn(n,e,i);if(y(n))return compile(n,i?{accessor:i}:void 0);if(E(n))return compile(n,i?{accessor:i}:void 0);if(D(n)){let t=n,r=Object.keys(t),f=r.map(o=>C(t[o],e,i));return o=>{let s={};for(let u=0;u<r.length;u++)s[r[u]]=f[u](o);return s}}return ()=>n}function K(n,e){return e?i=>e(n,i):O(n)}function hn(n,e){return K(n.$,e)}function Tn(n,e,i){let t;if(typeof n.$if=="string"){let o=n.$if.startsWith("!")?n.$if.slice(1):n.$if,s=K(o,i);t=n.$if.startsWith("!")?a=>!s(a):a=>!!s(a);}else {let o=C(n.$if,e,i);t=s=>!!o(s);}let r=C(n.then,e,i),f=n.else!==void 0?C(n.else,e,i):()=>{};return o=>t(o)?r(o):f(o)}function bn(n,e,i){let t=n.$pipe;if(t.length===0)return ()=>{};if(t.length===1)return C(t[0],e,i);let r=C(t[0],e,i),f=t.slice(1).map(s=>C(s,e,i)),o=f.length;if(o===1){let[s]=f;return u=>{let a=r(u),c=s(u);return typeof c=="function"?c(a):c}}if(o===2){let[s,u]=f;return a=>{let c=r(a),p=s(a);return c=typeof p=="function"?p(c):p,p=u(a),typeof p=="function"?p(c):p}}if(o===3){let[s,u,a]=f;return c=>{let p=r(c),d=s(c);return p=typeof d=="function"?d(p):d,d=u(c),p=typeof d=="function"?d(p):d,d=a(c),typeof d=="function"?d(p):d}}return s=>{let u=r(s);for(let a=0;a<o;a++){let c=f[a](s);u=typeof c=="function"?c(u):c;}return u}}function Cn(n,e,i){let t=n.$fn,r=n.args;if(r===void 0)return ()=>{let s=e[t];if(!s)throw new Error(`Function not found in scope: ${t}`);return s};let f=r.map(s=>C(s,e,i)),o=f.length;if(o===0)return s=>{let u=e[t];if(!u)throw new Error(`Function not found in scope: ${t}`);return u()};if(o===1){let[s]=f;return u=>{let a=e[t];if(!a)throw new Error(`Function not found in scope: ${t}`);return a(s(u))}}if(o===2){let[s,u]=f;return a=>{let c=e[t];if(!c)throw new Error(`Function not found in scope: ${t}`);return c(s(a),u(a))}}if(o===3){let[s,u,a]=f;return c=>{let p=e[t];if(!p)throw new Error(`Function not found in scope: ${t}`);return p(s(c),u(c),a(c))}}return s=>{let u=e[t];if(!u)throw new Error(`Function not found in scope: ${t}`);return u(...f.map(a=>a(s)))}}function $n(n,e,i={}){return F(n,i).fn(e)}var v=class{constructor(e=1e3){this.cache=new Map,this._maxSize=e;}get(e,i={}){let t=JSON.stringify(e),r=this.cache.get(t);if(r)return this.cache.delete(t),this.cache.set(t,r),r;let f=F(e,i);if(this.cache.size>=this._maxSize){let o=this.cache.keys().next().value;o&&this.cache.delete(o);}return this.cache.set(t,f),f}has(e){return this.cache.has(JSON.stringify(e))}delete(e){return this.cache.delete(JSON.stringify(e))}clear(){this.cache.clear();}get size(){return this.cache.size}get maxSize(){return this._maxSize}set maxSize(e){for(this._maxSize=e;this.cache.size>this._maxSize;){let i=this.cache.keys().next().value;i&&this.cache.delete(i);}}},Y=new v;function Sn(n,e={}){return Y.get(n,e)}function I(n,e="root",i={}){let t=[];return k(n,e,t,i),{valid:t.length===0,errors:t}}function k(n,e,i,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let o=0;o<n.length;o++)k(n[o],`${e}[${o}]`,i,t);return}if(g(n)){(!n.$||typeof n.$!="string")&&i.push(`${e}: invalid reference, $ must be non-empty string`);return}if(h(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||i.push(`${e}.$if: empty path in string shorthand`):k(n.$if,`${e}.$if`,i,t),k(n.then,`${e}.then`,i,t),n.else!==void 0&&k(n.else,`${e}.else`,i,t);return}if(b(n)){if(!Array.isArray(n.$pipe)){i.push(`${e}.$pipe: must be an array`);return}if(n.$pipe.length===0){i.push(`${e}.$pipe: must have at least one element`);return}for(let o=0;o<n.$pipe.length;o++)k(n.$pipe[o],`${e}.$pipe[${o}]`,i,t);return}if(T(n)){if(!n.$fn||typeof n.$fn!="string"){i.push(`${e}: invalid function, $fn must be non-empty string`);return}if(t.scope&&!(n.$fn in t.scope)&&i.push(`${e}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))i.push(`${e}.args: must be an array`);else for(let o=0;o<n.args.length;o++)k(n.args[o],`${e}.args[${o}]`,i,t);return}if(y(n)){let o=validate(n,e);o.valid||i.push(...o.errors);return}if(E(n)){let o=validate(n,e);o.valid||i.push(...o.errors);return}let r=n,f=Object.keys(r);for(let o=0;o<f.length;o++){let s=f[o];k(r[s],`${e}.${s}`,i,t);}}function An(n,e={}){let i=I(n,"root",e);if(!i.valid)throw new Error(`Invalid expression: ${i.errors.join("; ")}`)}function kn(n,e={}){return I(n,"root",e).valid}var Z={};rn(Z,{$:()=>Q,$fn:()=>U,$if:()=>xn,$pipe:()=>X,fn:()=>Rn,pipe:()=>On,ref:()=>wn});function Q(n){return {$:n}}var wn=Q;function U(n,e){return e===void 0||e.length===0?{$fn:n}:{$fn:n,args:e}}var Rn=U;function xn(n,e,i){return i===void 0?{$if:n,then:e}:{$if:n,then:e,else:i}}function X(...n){return {$pipe:n}}var On=X;var L="data",P="scope",Fn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function W(n,e={}){let{dataParam:i=L,scopeParam:t=P,noPrefixes:r=false,useAccessor:f=false,lexicalPrefix:o}=e;return m(n,i,t,r,f,o)}function m(n,e,i,t,r,f){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(o=>m(o,e,i,t,r,f)));if(g(n))return vn(n.$,e,t,r,f);if(h(n))return jn(n,e,i,t,r,f);if(b(n))return Wn(n.$pipe,e,i,t,r,f);if(T(n))return Gn(n,e,i,t,r,f);if(y(n))return zn(n,e,i,t,r,f);if(E(n))return Mn(n,e,i,t,r,f);if(typeof n=="object"){let s=Object.entries(n).map(([u,a])=>builders.property(builders.identifier(u),m(a,e,i,t,r,f)));return builders.objectExpression(s)}return builders.literal(null)}var N="accessor";function j(n,e){return e?n===e||n.startsWith(e+"."):false}function vn(n,e,i,t,r){return t?j(n,r)?A(n,e,true):builders.callExpression(builders.identifier(N),[builders.literal(n),builders.identifier(e)]):n.includes("[*]")?Nn(n,e,i):A(n,e,i)}function A(n,e,i){let t=G(n);if(t.length===0)return i?builders.identifier("undefined"):builders.identifier(e);let r;if(i){let f=t[0];r=builders.identifier(f.value);for(let o=1;o<t.length;o++){let s=t[o];s.type==="key"?r=builders.memberExpression(r,builders.identifier(s.value),false,true):r=builders.memberExpression(r,builders.literal(s.value),true,true);}}else {r=builders.identifier(e);for(let f of t)f.type==="key"?r=builders.memberExpression(r,builders.identifier(f.value),false,true):r=builders.memberExpression(r,builders.literal(f.value),true,true);}return r}function Nn(n,e,i){let t=n.indexOf("[*]"),r=n.slice(0,t),f=n.slice(t+3),o;if(r?o=A(r,e,i):o=i?builders.identifier("undefined"):builders.identifier(e),!f||f==="")return o;if(f.includes("[*]"))return nn(o,f);let s="_i",u=f.startsWith(".")?f.slice(1):f,a=builders.identifier(s);if(u){let c=G(u);for(let p of c)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(o,builders.identifier("map"),false,true),[builders.arrowFunctionExpression([builders.identifier(s)],a)])}function nn(n,e){let i=e.indexOf("[*]"),t=e.slice(0,i),r=e.slice(i+3),f="_i",o=t.startsWith(".")?t.slice(1):t,s=builders.identifier(f);if(o){let a=G(o);for(let c of a)c.type==="key"&&(s=builders.memberExpression(s,builders.identifier(c.value),false,true));}if(r.includes("[*]")){let a=nn(s,r);return builders.callExpression(builders.memberExpression(n,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([builders.identifier(f)],a)])}let u=r.startsWith(".")?r.slice(1):r;if(u){let a=G(u);for(let c of a)c.type==="key"&&(s=builders.memberExpression(s,builders.identifier(c.value),false,true));}return builders.callExpression(builders.memberExpression(n,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([builders.identifier(f)],s)])}function jn(n,e,i,t,r,f){let o;if(typeof n.$if=="string"){let a=n.$if.startsWith("!"),c=a?n.$if.slice(1):n.$if,p;r?j(c,f)?p=A(c,e,true):p=builders.callExpression(builders.identifier(N),[builders.literal(c),builders.identifier(e)]):p=A(c,e,t),o=a?builders.unaryExpression("!",p):p;}else o=m(n.$if,e,i,t,r,f);let s=m(n.then,e,i,t,r,f),u=n.else!==void 0?m(n.else,e,i,t,r,f):builders.identifier("undefined");return builders.conditionalExpression(o,s,u)}function Gn(n,e,i,t,r,f){let o=t?builders.identifier(n.$fn):builders.memberExpression(builders.identifier(i),builders.identifier(n.$fn),false,false);if(n.args===void 0)return o;let s=n.args.map(u=>m(u,e,i,t,r,f));return builders.callExpression(o,s)}function Wn(n,e,i,t,r,f){if(n.length===0)return builders.identifier("undefined");if(n.length===1)return m(n[0],e,i,t,r,f);let o=m(n[0],e,i,t,r,f);for(let s=1;s<n.length;s++){let u=m(n[s],e,i,t,r,f);o=builders.callExpression(u,[o]);}return o}function zn(n,e,i,t,r,f){let o;r?j(n.path,f)?o=A(n.path,e,true):o=builders.callExpression(builders.identifier(N),[builders.literal(n.path),builders.identifier(e)]):o=A(n.path,e,t);let s=n.value!==void 0?g(n.value)?r?j(n.value.$,f)?A(n.value.$,e,true):builders.callExpression(builders.identifier(N),[builders.literal(n.value.$),builders.identifier(e)]):A(n.value.$,e,t):m(n.value,e,i,t,r,f):builders.literal(null),u=Fn[n.op];if(u)return builders.binaryExpression(u,o,s);switch(n.op){case "in":return builders.callExpression(builders.memberExpression(s,builders.identifier("includes")),[o]);case "notIn":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(s,builders.identifier("includes")),[o]));case "contains":return builders.callExpression(builders.memberExpression(o,builders.identifier("includes"),false,true),[s]);case "notContains":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(o,builders.identifier("includes"),false,true),[s]));case "exists":return builders.binaryExpression("!=",o,builders.literal(null));case "notExists":return builders.binaryExpression("==",o,builders.literal(null));case "matches":return builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[s]),builders.identifier("test")),[o]);case "notMatches":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[s]),builders.identifier("test")),[o]));case "startsWith":return builders.callExpression(builders.memberExpression(o,builders.identifier("startsWith"),false,true),[s]);case "endsWith":return builders.callExpression(builders.memberExpression(o,builders.identifier("endsWith"),false,true),[s]);default:return builders.binaryExpression("===",o,s)}}function Mn(n,e,i,t,r,f){let{logic:o,conditions:s}=n,u=o==="AND"?"&&":"||";if(s.length===0)return builders.literal(o==="AND");if(s.length===1)return m(s[0],e,i,t,r,f);let a=m(s[0],e,i,t,r,f);for(let c=1;c<s.length;c++){let p=m(s[c],e,i,t,r,f);a=builders.logicalExpression(u,a,p);}return a}function G(n){let e=[],i=n.length,t=0,r="";for(;t<i;){let f=n[t];if(f===".")r&&(e.push({type:"key",value:r}),r=""),t++;else if(f==="["){r&&(e.push({type:"key",value:r}),r=""),t++;let o=t;for(;t<i&&n[t]!=="]";)t++;let s=n.slice(o,t);if(t++,s!=="*"){let u=parseInt(s,10);e.push({type:"index",value:isNaN(u)?s:u});}}else r+=f,t++;}return r&&e.push({type:"key",value:r}),e}function en(n,e=[L]){return builders.arrowFunctionExpression(e.map(i=>builders.identifier(i)),n)}function z(n){let e=new Set;return $(n,e),e}function $(n,e){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let t of n)$(t,e);return}if(g(n))return;if(h(n)){$(n.$if,e),$(n.then,e),n.else!==void 0&&$(n.else,e);return}if(b(n)){for(let t of n.$pipe)$(t,e);return}if(T(n)){if(e.add(n.$fn),n.args)for(let t of n.args)$(t,e);return}if(y(n)){n.value!==void 0&&typeof n.value=="object"&&$(n.value,e);return}if(E(n)){for(let t of n.conditions)$(t,e);return}let i=n;for(let t of Object.keys(i))$(i[t],e);}function M(n){let e=new Set;for(let i of n){let t=i.indexOf("."),r=i.indexOf("["),f=i.length;t!==-1&&(f=Math.min(f,t)),r!==-1&&(f=Math.min(f,r));let o=i.slice(0,f);o&&e.add(o);}return e}function In(n){return JSON.stringify(n)}function Ln(n,e,i,t,r){let f=W(n,{noPrefixes:true,useAccessor:t,lexicalPrefix:r}),o=generate(f),s="";t?r&&(s=`const{${r}}=data??{};`):e.size>0&&(s=`const{${[...e].join(",")}}=data??{};`);let u=t?new Set([...i,"accessor"]):i,a=u.size>0?`const{${[...u].join(",")}}=scope;`:"";return a?`(function(scope){${a}return function(data){${s}return ${o}}})`:`(function(){return function(data){${s}return ${o}}})`}function V(n,e={}){let{scope:i={},returnCode:t=false,useAccessor:r=false,lexicalPrefix:f}=e,o=w(n),s=M(o),u=z(n),a=In(n),c=Ln(n,s,u,r,f);if(t)return {code:c,deps:o,hash:a,dataRoots:[...s],scopeFns:[...u]};let p;try{p=new Function(`return ${c}`)()(i);}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:o,hash:a}}function tn(n,e,i={}){let{fn:t}=V(n,i);return t(e)}var he="0.1.1";export{v as ExpressionCache,he as VERSION,An as assertValid,Z as builders,Y as cache,Sn as cached,pn as clearPathCache,F as compile,V as compileAST,O as compilePath,W as dslToAST,$n as evaluate,tn as evaluateAST,M as extractDataRoots,w as extractDeps,z as extractScopeFns,cn as get,dn as getPathCacheSize,gn as hasDeps,J as hasWildcard,y as isCondition,sn as isConditionExpr,E as isConditionGroup,h as isConditional,T as isFn,D as isLiteral,b as isPipe,yn as isPure,g as isRef,kn as isValid,R as normalizePath,I as validate,en as wrapInFunction};
1
+ import {builders,generate}from'omni-ast';var on=Object.defineProperty;var rn=(n,t)=>{for(var s in t)on(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"]),h=n=>n!==null&&typeof n=="object"&&"left"in n&&"op"in n&&x.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),E=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,sn=n=>h(n)||E(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,e="left"in s&&"op"in s&&x.has(s.op);return !("$"in s)&&!("$if"in s)&&!("$fn"in s)&&!("$pipe"in s)&&!e&&!("logic"in s)}return false};var R=new Map;function q(n){let t=[],s=n.length,e=0,r="";for(;e<s;){let o=n[e];if(o===".")r&&(t.push({type:"key",value:r}),r=""),e++;else if(o==="["){r&&(t.push({type:"key",value:r}),r=""),e++;let i=e;for(;e<s&&n[e]!=="]";)e++;let f=n.slice(i,e);if(e++,f==="*")t.push({type:"wildcard",value:"*"});else {let l=parseInt(f,10);t.push({type:"index",value:isNaN(l)?f:l});}}else r+=o,e++;}return r&&t.push({type:"key",value:r}),t}function J(n){return n.includes("[*]")}function O(n){let t=R.get(n);return t||(t=J(n)?un(n):fn(n),R.set(n,t),t)}function fn(n){if(!n.includes(".")&&!n.includes("["))return r=>r?.[n];let t=q(n),s=t.length;if(s===2){let[r,o]=t,i=r.value,f=o.value;return l=>l?.[i]?.[f]}if(s===3){let[r,o,i]=t,f=r.value,l=o.value,c=i.value;return a=>a?.[f]?.[l]?.[c]}let e=t.map(r=>r.value);return r=>{let o=r;for(let i=0;i<s&&o!=null;i++)o=o[e[i]];return o}}function un(n){let t=q(n),s=[];for(let e=0;e<t.length;e++)t[e].type==="wildcard"&&s.push(e);return s.length===1?ln(t,s[0]):cn(t,s)}function ln(n,t){let s=n.slice(0,t).map(i=>i.value),e=n.slice(t+1).map(i=>i.value),r=s.length,o=e.length;if(o===0){if(r===1){let i=s[0];return f=>f?.[i]}return i=>{let f=i;for(let l=0;l<r&&f!=null;l++)f=f[s[l]];return f}}if(o===1){let i=e[0];if(r===1){let f=s[0];return l=>{let c=l?.[f];if(Array.isArray(c))return c.map(a=>a?.[i])}}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?.[i])}}return i=>{let f=i;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[e[a]];return c})}}function cn(n,t){let s=[],e=0;for(let o=0;o<t.length;o++){let i=t[o],f=o===t.length-1,l=n.slice(e,i).map(c=>c.value);l.length>0&&s.push({type:"access",keys:l}),s.push({type:f?"map":"flatMap",keys:[]}),e=i+1;}let r=n.slice(e).map(o=>o.value);return o=>{let i=o;for(let f of s){if(i==null)return;if(f.type==="access")for(let l of f.keys){if(i==null)return;i=i[l];}else if(f.type==="flatMap"){if(!Array.isArray(i))return;i=i.flatMap(l=>{let c=l;return Array.isArray(c)?c:[c]});}else if(f.type==="map"){if(!Array.isArray(i))return;r.length>0&&(i=i.map(l=>{let c=l;for(let a of r){if(c==null)return;c=c[a];}return c}));}}return i}}function an(n,t){return O(t)(n)}function F(n){let t=n.indexOf("[*]");return t===-1?n:n.slice(0,t)}function pn(){R.clear();}function dn(){return R.size}function k(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++){let o=n.args[r];typeof o!="function"&&A(o,t);}return}if(h(n)){A(n.left,t),n.right!==void 0&&A(n.right,t);return}if(E(n)){for(let r=0;r<n.conditions.length;r++)A(n.conditions[r],t);return}let s=n,e=Object.keys(s);for(let r=0;r<e.length;r++)A(s[e[r]],t);}function gn(n){return k(n).length>0}function mn(n){return k(n).length===0}function yn(n){return JSON.stringify(n)}function N(n,t={}){let s=t.scope??{},e=t.accessor,r=m(n,s,e),o=k(n),i=yn(n);return {fn:r,deps:o,hash:i}}function m(n,t,s){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let e=n.map(r=>m(r,t,s));return r=>e.map(o=>o(r))}if(y(n))return hn(n,s);if(T(n))return En(n,t,s);if(C(n))return Tn(n,t,s);if(b(n))return bn(n,t,s);if(h(n))return Cn(n,t,s);if(E(n))return An(n,t,s);if(I(n)){let e=n,r=Object.keys(e),o=r.map(i=>m(e[i],t,s));return i=>{let f={};for(let l=0;l<r.length;l++)f[r[l]]=o[l](i);return f}}return ()=>n}function B(n,t){return t?s=>t(n,s):O(n)}function hn(n,t){return B(n.$,t)}function En(n,t,s){let e;if(typeof n.$if=="string"){let i=n.$if.startsWith("!")?n.$if.slice(1):n.$if,f=B(i,s);e=n.$if.startsWith("!")?c=>!f(c):c=>!!f(c);}else {let i=m(n.$if,t,s);e=f=>!!i(f);}let r=m(n.then,t,s),o=n.else!==void 0?m(n.else,t,s):()=>{};return i=>e(i)?r(i):o(i)}function Tn(n,t,s){let e=n.$pipe;if(e.length===0)return ()=>{};if(e.length===1)return m(e[0],t,s);let r=m(e[0],t,s),o=e.slice(1).map(f=>m(f,t,s)),i=o.length;if(i===1){let[f]=o;return l=>{let c=r(l),a=f(l);return typeof a=="function"?a(c):a}}if(i===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(i===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<i;c++){let a=o[c](f);l=typeof a=="function"?a(l):a;}return l}}function bn(n,t,s){let e=n.$fn,r=n.args;if(r===void 0)return ()=>{let f=t[e];if(!f)throw new Error(`Function not found in scope: ${e}`);return f};let o=r.map(f=>typeof f=="function"?()=>f:m(f,t,s)),i=o.length;if(i===0)return f=>{let l=t[e];if(!l)throw new Error(`Function not found in scope: ${e}`);return l()};if(i===1){let[f]=o;return l=>{let c=t[e];if(!c)throw new Error(`Function not found in scope: ${e}`);return c(f(l))}}if(i===2){let[f,l]=o;return c=>{let a=t[e];if(!a)throw new Error(`Function not found in scope: ${e}`);return a(f(c),l(c))}}if(i===3){let[f,l,c]=o;return a=>{let p=t[e];if(!p)throw new Error(`Function not found in scope: ${e}`);return p(f(a),l(a),c(a))}}return f=>{let l=t[e];if(!l)throw new Error(`Function not found in scope: ${e}`);return l(...o.map(c=>c(f)))}}function Cn(n,t,s){let e=m(n.left,t,s),r=n.right!==void 0?m(n.right,t,s):()=>{};switch(n.op){case "eq":return o=>e(o)===r(o);case "neq":return o=>e(o)!==r(o);case "gt":return o=>e(o)>r(o);case "gte":return o=>e(o)>=r(o);case "lt":return o=>e(o)<r(o);case "lte":return o=>e(o)<=r(o);case "in":return o=>{let i=r(o);return Array.isArray(i)&&i.includes(e(o))};case "notIn":return o=>{let i=r(o);return !Array.isArray(i)||!i.includes(e(o))};case "contains":return o=>{let i=e(o);return Array.isArray(i)&&i.includes(r(o))};case "notContains":return o=>{let i=e(o);return !Array.isArray(i)||!i.includes(r(o))};case "exists":return o=>e(o)!==void 0;case "notExists":return o=>e(o)===void 0;case "matches":return o=>{let i=e(o),f=r(o);return typeof i!="string"||typeof f!="string"?false:new RegExp(f).test(i)};case "notMatches":return o=>{let i=e(o),f=r(o);return typeof i!="string"||typeof f!="string"?true:!new RegExp(f).test(i)};case "startsWith":return o=>{let i=e(o),f=r(o);return typeof i=="string"&&typeof f=="string"&&i.startsWith(f)};case "endsWith":return o=>{let i=e(o),f=r(o);return typeof i=="string"&&typeof f=="string"&&i.endsWith(f)}}}function An(n,t,s){let e=n.conditions.map(o=>m(o,t,s)),r=e.length;if(r===1)return o=>!!e[0](o);if(r===2){let[o,i]=e;return n.logic==="AND"?f=>!!o(f)&&!!i(f):f=>!!o(f)||!!i(f)}if(r===3){let[o,i,f]=e;return n.logic==="AND"?l=>!!o(l)&&!!i(l)&&!!f(l):l=>!!o(l)||!!i(l)||!!f(l)}return n.logic==="AND"?o=>{for(let i=0;i<r;i++)if(!e[i](o))return false;return true}:o=>{for(let i=0;i<r;i++)if(e[i](o))return true;return false}}function $n(n,t,s={}){return N(n,s).fn(t)}var v=class{constructor(t=1e3){this.cache=new Map,this._maxSize=t;}get(t,s={}){let e=JSON.stringify(t),r=this.cache.get(e);if(r)return this.cache.delete(e),this.cache.set(e,r),r;let o=N(t,s);if(this.cache.size>=this._maxSize){let i=this.cache.keys().next().value;i&&this.cache.delete(i);}return this.cache.set(e,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);}}},K=new v;function Sn(n,t={}){return K.get(n,t)}function M(n,t="root",s={}){let e=[];return $(n,t,e,s),{valid:e.length===0,errors:e}}function $(n,t,s,e){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let i=0;i<n.length;i++)$(n[i],`${t}[${i}]`,s,e);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,e),$(n.then,`${t}.then`,s,e),n.else!==void 0&&$(n.else,`${t}.else`,s,e);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 i=0;i<n.$pipe.length;i++)$(n.$pipe[i],`${t}.$pipe[${i}]`,s,e);return}if(b(n)){if(!n.$fn||typeof n.$fn!="string"){s.push(`${t}: invalid function, $fn must be non-empty string`);return}if(e.scope&&!(n.$fn in e.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 i=0;i<n.args.length;i++){let f=n.args[i];typeof f!="function"&&$(f,`${t}.args[${i}]`,s,e);}return}if(h(n)){x.has(n.op)||s.push(`${t}: invalid operator "${n.op}"`),$(n.left,`${t}.left`,s,e),n.right!==void 0&&$(n.right,`${t}.right`,s,e);return}if(E(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 i=0;i<n.conditions.length;i++)$(n.conditions[i],`${t}.conditions[${i}]`,s,e);return}let r=n,o=Object.keys(r);for(let i=0;i<o.length;i++){let f=o[i];$(r[f],`${t}.${f}`,s,e);}}function kn(n,t={}){let s=M(n,"root",t);if(!s.valid)throw new Error(`Invalid expression: ${s.errors.join("; ")}`)}function wn(n,t={}){return M(n,"root",t).valid}var U={};rn(U,{$:()=>P,$cond:()=>Q,$fn:()=>Y,$if:()=>On,$pipe:()=>H,cond:()=>Nn,fn:()=>Rn,pipe:()=>Fn,ref:()=>xn});function P(n){return {$:n}}var xn=P;function Y(n,t){return t===void 0||t.length===0?{$fn:n}:{$fn:n,args:t}}var Rn=Y;function On(n,t,s){return s===void 0?{$if:n,then:t}:{$if:n,then:t,else:s}}function H(...n){return {$pipe:n}}var Fn=H;function Q(n,t,s){return s===void 0?{left:n,op:t}:{left:n,op:t,right:s}}var Nn=Q;var z="data",Z="scope",vn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function G(n,t={}){let{dataParam:s=z,scopeParam:e=Z,noPrefixes:r=false,useAccessor:o=false,lexicalPrefix:i}=t;return g(n,s,e,r,o,i)}function g(n,t,s,e,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(i=>g(i,t,s,e,r,o)));if(y(n))return jn(n.$,t,e,r,o);if(T(n))return Wn(n,t,s,e,r,o);if(C(n))return In(n.$pipe,t,s,e,r,o);if(b(n))return Dn(n,t,s,e,r,o);if(h(n))return Mn(n,t,s,e,r,o);if(E(n))return zn(n,t,s,e,r,o);if(typeof n=="object"){let f=Object.entries(n).map(([l,c])=>builders.property(builders.identifier(l),g(c,t,s,e,r,o)));return builders.objectExpression(f)}return builders.literal(null)}var L="accessor";function V(n,t){return t?n===t||n.startsWith(t+"."):false}function jn(n,t,s,e,r){return e?V(n,r)?w(n,t,true):builders.callExpression(builders.identifier(L),[builders.literal(n),builders.identifier(t)]):n.includes("[*]")?Gn(n,t,s):w(n,t,s)}function w(n,t,s){let e=j(n);if(e.length===0)return s?builders.identifier("undefined"):builders.identifier(t);let r;if(s){let o=e[0];r=builders.identifier(o.value);for(let i=1;i<e.length;i++){let f=e[i];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 e)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 Gn(n,t,s){let e=n.indexOf("[*]"),r=n.slice(0,e),o=n.slice(e+3),i;if(r?i=w(r,t,s):i=s?builders.identifier("undefined"):builders.identifier(t),!o||o==="")return i;if(o.includes("[*]"))return nn(i,o);let f="_i",l=o.startsWith(".")?o.slice(1):o,c=builders.identifier(f);if(l){let a=j(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(i,builders.identifier("map"),false,true),[builders.arrowFunctionExpression([builders.identifier(f)],c)])}function nn(n,t){let s=t.indexOf("[*]"),e=t.slice(0,s),r=t.slice(s+3),o="_i",i=e.startsWith(".")?e.slice(1):e,f=builders.identifier(o);if(i){let c=j(i);for(let a of c)a.type==="key"&&(f=builders.memberExpression(f,builders.identifier(a.value),false,true));}if(r.includes("[*]")){let c=nn(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=j(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 Wn(n,t,s,e,r,o){let i;if(typeof n.$if=="string"){let c=n.$if.startsWith("!"),a=c?n.$if.slice(1):n.$if,p;r?V(a,o)?p=w(a,t,true):p=builders.callExpression(builders.identifier(L),[builders.literal(a),builders.identifier(t)]):p=w(a,t,e),i=c?builders.unaryExpression("!",p):p;}else i=g(n.$if,t,s,e,r,o);let f=g(n.then,t,s,e,r,o),l=n.else!==void 0?g(n.else,t,s,e,r,o):builders.identifier("undefined");return builders.conditionalExpression(i,f,l)}function Dn(n,t,s,e,r,o){let i=e?builders.identifier(n.$fn):builders.memberExpression(builders.identifier(s),builders.identifier(n.$fn),false,false);if(n.args===void 0)return i;let f=n.args.map(l=>typeof l=="function"?builders.literal(null):g(l,t,s,e,r,o));return builders.callExpression(i,f)}function In(n,t,s,e,r,o){if(n.length===0)return builders.identifier("undefined");if(n.length===1)return g(n[0],t,s,e,r,o);let i=g(n[0],t,s,e,r,o);for(let f=1;f<n.length;f++){let l=g(n[f],t,s,e,r,o);i=builders.callExpression(l,[i]);}return i}function X(n,t,s,e,r,o){if(y(n)){let i=n.$;return r?V(i,o)?w(i,t,true):builders.callExpression(builders.identifier(L),[builders.literal(i),builders.identifier(t)]):w(i,t,e)}return g(n,t,s,e,r,o)}function Mn(n,t,s,e,r,o){let i=X(n.left,t,s,e,r,o),f=n.right!==void 0?X(n.right,t,s,e,r,o):builders.literal(null),l=vn[n.op];if(l)return builders.binaryExpression(l,i,f);switch(n.op){case "in":return builders.callExpression(builders.memberExpression(f,builders.identifier("includes")),[i]);case "notIn":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(f,builders.identifier("includes")),[i]));case "contains":return builders.callExpression(builders.memberExpression(i,builders.identifier("includes"),false,true),[f]);case "notContains":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(i,builders.identifier("includes"),false,true),[f]));case "exists":return builders.binaryExpression("!=",i,builders.literal(null));case "notExists":return builders.binaryExpression("==",i,builders.literal(null));case "matches":return builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[f]),builders.identifier("test")),[i]);case "notMatches":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[f]),builders.identifier("test")),[i]));case "startsWith":return builders.callExpression(builders.memberExpression(i,builders.identifier("startsWith"),false,true),[f]);case "endsWith":return builders.callExpression(builders.memberExpression(i,builders.identifier("endsWith"),false,true),[f]);default:return builders.binaryExpression("===",i,f)}}function zn(n,t,s,e,r,o){let{logic:i,conditions:f}=n,l=i==="AND"?"&&":"||";if(f.length===0)return builders.literal(i==="AND");if(f.length===1)return g(f[0],t,s,e,r,o);let c=g(f[0],t,s,e,r,o);for(let a=1;a<f.length;a++){let p=g(f[a],t,s,e,r,o);c=builders.logicalExpression(l,c,p);}return c}function j(n){let t=[],s=n.length,e=0,r="";for(;e<s;){let o=n[e];if(o===".")r&&(t.push({type:"key",value:r}),r=""),e++;else if(o==="["){r&&(t.push({type:"key",value:r}),r=""),e++;let i=e;for(;e<s&&n[e]!=="]";)e++;let f=n.slice(i,e);if(e++,f!=="*"){let l=parseInt(f,10);t.push({type:"index",value:isNaN(l)?f:l});}}else r+=o,e++;}return r&&t.push({type:"key",value:r}),t}function tn(n,t=[z]){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 e of n)S(e,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 e of n.$pipe)S(e,t);return}if(b(n)){if(t.add(n.$fn),n.args)for(let e of n.args)typeof e!="function"&&S(e,t);return}if(h(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(E(n)){for(let e of n.conditions)S(e,t);return}let s=n;for(let e of Object.keys(s))S(s[e],t);}function D(n){let t=new Set;for(let s of n){let e=s.indexOf("."),r=s.indexOf("["),o=s.length;e!==-1&&(o=Math.min(o,e)),r!==-1&&(o=Math.min(o,r));let i=s.slice(0,o);i&&t.add(i);}return t}function Vn(n){return JSON.stringify(n)}function _n(n,t,s,e,r){let o=G(n,{noPrefixes:true,useAccessor:e,lexicalPrefix:r}),i=generate(o),f="";e?r&&(f=`const{${r}}=data??{};`):t.size>0&&(f=`const{${[...t].join(",")}}=data??{};`);let l=e?new Set([...s,"accessor"]):s,c=l.size>0?`const{${[...l].join(",")}}=scope;`:"";return c?`(function(scope){${c}return function(data){${f}return ${i}}})`:`(function(){return function(data){${f}return ${i}}})`}function _(n,t={}){let{scope:s={},returnCode:e=false,useAccessor:r=false,lexicalPrefix:o}=t,i=k(n),f=D(i),l=W(n),c=Vn(n),a=_n(n,f,l,r,o);if(e)return {code:a,deps:i,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:i,hash:c}}function en(n,t,s={}){let{fn:e}=_(n,s);return e(t)}var ht="0.1.1";export{v as ExpressionCache,ht as VERSION,kn as assertValid,U as builders,K as cache,Sn as cached,pn as clearPathCache,N as compile,_ as compileAST,O as compilePath,G as dslToAST,$n as evaluate,en as evaluateAST,D as extractDataRoots,k as extractDeps,W as extractScopeFns,an as get,dn as getPathCacheSize,gn as hasDeps,J as hasWildcard,h as isCondition,sn as isConditionExpr,E as isConditionGroup,T as isConditional,b as isFn,I as isLiteral,C as isPipe,mn as isPure,y as isRef,wn as isValid,F as normalizePath,M as validate,tn as wrapInFunction};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statedelta-libs/expressions",
3
- "version": "0.2.1",
3
+ "version": "1.1.0",
4
4
  "description": "JSON DSL compiler for optimized functions - StateDelta expression engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -14,8 +14,7 @@
14
14
  }
15
15
  },
16
16
  "dependencies": {
17
- "@statedelta-libs/conditions": "^0.1.1",
18
- "omni-ast": "^2.0.0"
17
+ "omni-ast": "^2.0.2"
19
18
  },
20
19
  "files": [
21
20
  "dist",