@statedelta-libs/expressions 2.0.1 → 2.2.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 +276 -2
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +240 -3
- package/dist/index.d.ts +240 -3
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,13 +10,16 @@
|
|
|
10
10
|
- **DSL Puro** - 100% JSON-serializável, sem callbacks inline
|
|
11
11
|
- **Compilação** - Compila uma vez, executa milhões de vezes
|
|
12
12
|
- **Alta performance** - ~25-30M ops/s após compilação
|
|
13
|
-
- **Scope externo** - Funções vêm via scope, não hardcoded
|
|
13
|
+
- **Scope externo** - Funções puras vêm via scope, não hardcoded
|
|
14
|
+
- **Context externo** - HOCs de continuidade via context (`tryCatch`, `transaction`, etc.)
|
|
14
15
|
- **Accessor customizado** - Suporte a `ctx.get(path)` para objetos especiais
|
|
15
16
|
- **$pipe** - Composição com valor inicial (sintaxe DSL)
|
|
17
|
+
- **$cb** - Callback expressions para HOCs de continuidade
|
|
16
18
|
- **Path syntax** - Suporte a wildcards (`items[*].price`)
|
|
17
19
|
- **Dependency extraction** - Para dirty tracking/reatividade
|
|
18
20
|
- **Conditions nativo** - Condicionais integradas com expressions nos lados
|
|
19
21
|
- **normalize()** - Helper externo para custom transforms (`$query`, `$mapper`, etc.)
|
|
22
|
+
- **resolveBoundaries()** - Resolve boundaries customizados (`$simulate`, `$context`, etc.) com compilação independente
|
|
20
23
|
- **Type-safe** - TypeScript nativo com inferência
|
|
21
24
|
|
|
22
25
|
## Instalação
|
|
@@ -297,6 +300,76 @@ Condicionais compiladas internamente. Ambos os lados aceitam qualquer expressão
|
|
|
297
300
|
|
|
298
301
|
**Operadores:** `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `notIn`, `contains`, `notContains`, `exists`, `notExists`, `matches`, `notMatches`, `startsWith`, `endsWith`
|
|
299
302
|
|
|
303
|
+
### Callback ($cb)
|
|
304
|
+
|
|
305
|
+
HOC de continuidade - executa body dentro de um context function.
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
// Básico - tryCatch
|
|
309
|
+
{ $cb: "tryCatch", body: { $fn: "query" } }
|
|
310
|
+
|
|
311
|
+
// Com parâmetros
|
|
312
|
+
{ $cb: "transaction", body: { $fn: "save" }, params: { isolation: "serializable" } }
|
|
313
|
+
|
|
314
|
+
// Aninhado
|
|
315
|
+
{
|
|
316
|
+
$cb: "tryCatch",
|
|
317
|
+
body: {
|
|
318
|
+
$cb: "transaction",
|
|
319
|
+
body: { $fn: "save" }
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Context
|
|
325
|
+
|
|
326
|
+
O context define HOCs disponíveis para `$cb`. Diferente de scope (funções puras), context functions controlam a execução do body:
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
import type { Context, ContextFn } from '@statedelta-libs/expressions';
|
|
330
|
+
|
|
331
|
+
const tryCatch: ContextFn = (cb, data, get, params) => {
|
|
332
|
+
try {
|
|
333
|
+
return cb(data, get);
|
|
334
|
+
} catch {
|
|
335
|
+
return params?.fallback ?? null;
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const transaction: ContextFn = (cb, data, get, params) => {
|
|
340
|
+
const tx = db.beginTransaction(params);
|
|
341
|
+
try {
|
|
342
|
+
const result = cb({ ...data, tx }, get);
|
|
343
|
+
tx.commit();
|
|
344
|
+
return result;
|
|
345
|
+
} catch (e) {
|
|
346
|
+
tx.rollback();
|
|
347
|
+
throw e;
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
// Context function pode ignorar o cb e retornar outro valor
|
|
352
|
+
const cached: ContextFn = (cb, data, get, params) => {
|
|
353
|
+
if (cache.has(params?.key)) {
|
|
354
|
+
return cache.get(params.key); // Não executa cb
|
|
355
|
+
}
|
|
356
|
+
return cb(data, get);
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
const context: Context = { tryCatch, transaction, cached };
|
|
360
|
+
|
|
361
|
+
compile(expression, { scope, context });
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**Parâmetros do ContextFn:**
|
|
365
|
+
|
|
366
|
+
| Parâmetro | Tipo | Descrição |
|
|
367
|
+
|-----------|------|-----------|
|
|
368
|
+
| `cb` | `(data, get) => R` | Body compilado como callback |
|
|
369
|
+
| `data` | `T` | Dados do runtime |
|
|
370
|
+
| `get` | `(path) => unknown` | Resolver de paths |
|
|
371
|
+
| `params` | `unknown` | Parâmetros do `$cb.params` |
|
|
372
|
+
|
|
300
373
|
## Scope
|
|
301
374
|
|
|
302
375
|
O scope define quais funções estão disponíveis para `$fn`:
|
|
@@ -392,6 +465,156 @@ normalize({ $loop: "test" }, badTransforms);
|
|
|
392
465
|
// Error: Transform "$loop" returned object with same key — infinite loop
|
|
393
466
|
```
|
|
394
467
|
|
|
468
|
+
## Boundaries (resolveBoundaries)
|
|
469
|
+
|
|
470
|
+
Para DSL customizados que precisam de **compilação independente** dos slots internos, use `resolveBoundaries()`. Diferente de `normalize()` (que apenas transforma), boundaries param o fluxo de compilação e delegam para um resolver externo.
|
|
471
|
+
|
|
472
|
+
### Conceito
|
|
473
|
+
|
|
474
|
+
Um **boundary** é um "corpo estranho" no DSL que:
|
|
475
|
+
1. **Para** o fluxo normal de compilação
|
|
476
|
+
2. **Delega** para um resolver customizado
|
|
477
|
+
3. O resolver **compila slots internos** independentemente
|
|
478
|
+
4. **Substitui** por uma referência no scope
|
|
479
|
+
|
|
480
|
+
```
|
|
481
|
+
DSL "rico" DSL puro
|
|
482
|
+
{ $simulate: {...} } → { $fn: "__simulate_0", args: [] }
|
|
483
|
+
+ scope["__simulate_0"] = fn compilada
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
### Uso básico
|
|
487
|
+
|
|
488
|
+
```typescript
|
|
489
|
+
import { resolveBoundaries, compile, type BoundaryResolvers } from '@statedelta-libs/expressions';
|
|
490
|
+
|
|
491
|
+
const resolvers: BoundaryResolvers = {
|
|
492
|
+
$context: (node, { compile: compileFn, genId, scope }) => {
|
|
493
|
+
const id = `__context_${genId()}`;
|
|
494
|
+
const body = (node.$context as { body: Expression }).body;
|
|
495
|
+
|
|
496
|
+
// Compila o body internamente
|
|
497
|
+
const bodyFn = compileFn(body, { scope }).fn;
|
|
498
|
+
|
|
499
|
+
// Retorna função com lifecycle begin/end
|
|
500
|
+
const contextFn = () => (data: unknown) => {
|
|
501
|
+
console.log("begin");
|
|
502
|
+
try {
|
|
503
|
+
return bodyFn(data);
|
|
504
|
+
} finally {
|
|
505
|
+
console.log("end");
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
return {
|
|
510
|
+
expr: { $fn: id, args: [] },
|
|
511
|
+
scopeEntry: [id, contextFn],
|
|
512
|
+
};
|
|
513
|
+
},
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
// 1. Resolve boundaries (extrai e compila internamente)
|
|
517
|
+
const { expr, scope } = resolveBoundaries(
|
|
518
|
+
{ $context: { body: { $fn: "add", args: [{ $: "a" }, { $: "b" }] } } },
|
|
519
|
+
{ resolvers, scope: { add: (a, b) => a + b } }
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
// 2. Compila DSL puro resultante
|
|
523
|
+
const { fn } = compile(expr, { scope });
|
|
524
|
+
|
|
525
|
+
// 3. Executa
|
|
526
|
+
const contextFn = fn({}); // Retorna a função com lifecycle
|
|
527
|
+
const result = contextFn({ a: 1, b: 2 }); // "begin" → 3 → "end"
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### Caso de uso: $simulate com múltiplos slots
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
interface SimulateNode {
|
|
534
|
+
$simulate: {
|
|
535
|
+
effects: Expression[];
|
|
536
|
+
query: Expression;
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const resolvers: BoundaryResolvers = {
|
|
541
|
+
$simulate: (node, { compile: compileFn, genId, scope }) => {
|
|
542
|
+
const id = `__simulate_${genId()}`;
|
|
543
|
+
const sim = (node as unknown as SimulateNode).$simulate;
|
|
544
|
+
|
|
545
|
+
// Compila cada slot independentemente
|
|
546
|
+
const effectFns = sim.effects.map((e) => compileFn(e, { scope }).fn);
|
|
547
|
+
const queryFn = compileFn(sim.query, { scope }).fn;
|
|
548
|
+
|
|
549
|
+
// Cria função que orquestra a execução
|
|
550
|
+
const simulateFn = () => (data: unknown) => {
|
|
551
|
+
const effects = effectFns.map((fn) => fn(data));
|
|
552
|
+
const query = queryFn(data);
|
|
553
|
+
return { effects, query };
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
return {
|
|
557
|
+
expr: { $fn: id, args: [] },
|
|
558
|
+
scopeEntry: [id, simulateFn],
|
|
559
|
+
};
|
|
560
|
+
},
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
const { expr, scope } = resolveBoundaries(
|
|
564
|
+
{
|
|
565
|
+
$simulate: {
|
|
566
|
+
effects: [
|
|
567
|
+
{ $fn: "increment", args: [{ $: "hp" }] },
|
|
568
|
+
{ $fn: "decrement", args: [{ $: "mp" }] },
|
|
569
|
+
],
|
|
570
|
+
query: { $fn: "isAlive", args: [{ $: "hp" }] },
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
{ resolvers, scope: myScope }
|
|
574
|
+
);
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### Contexto do resolver
|
|
578
|
+
|
|
579
|
+
O resolver recebe um contexto com:
|
|
580
|
+
|
|
581
|
+
| Propriedade | Tipo | Descrição |
|
|
582
|
+
|-------------|------|-----------|
|
|
583
|
+
| `compile` | `typeof compile` | Mesmo compilador do fluxo principal |
|
|
584
|
+
| `genId` | `() => string` | Gerador de IDs únicos |
|
|
585
|
+
| `scope` | `Scope` | Scope atual (read-only) |
|
|
586
|
+
| `options` | `CompileOptions` | Opções de compilação |
|
|
587
|
+
|
|
588
|
+
### ID Generator customizado
|
|
589
|
+
|
|
590
|
+
Por padrão, IDs são gerados como `"0"`, `"1"`, `"2"`... Para IDs únicos globais, passe um `genId` customizado:
|
|
591
|
+
|
|
592
|
+
```typescript
|
|
593
|
+
import { nanoid } from 'nanoid';
|
|
594
|
+
|
|
595
|
+
const { expr, scope } = resolveBoundaries(expr, {
|
|
596
|
+
resolvers,
|
|
597
|
+
scope: baseScope,
|
|
598
|
+
genId: () => nanoid(), // IDs únicos globais
|
|
599
|
+
});
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### Diferença entre normalize e resolveBoundaries
|
|
603
|
+
|
|
604
|
+
| | `normalize()` | `resolveBoundaries()` |
|
|
605
|
+
|---|---|---|
|
|
606
|
+
| **Propósito** | Transformar sintaxe | Compilação independente |
|
|
607
|
+
| **Retorno** | `Expression` | `{ expr, scope }` |
|
|
608
|
+
| **Compila slots** | Não | Sim (via `ctx.compile`) |
|
|
609
|
+
| **Acumula scope** | Não | Sim |
|
|
610
|
+
| **Uso típico** | `$query` → `$fn` | `$simulate`, `$context` |
|
|
611
|
+
|
|
612
|
+
Use `normalize()` para sugar syntax simples. Use `resolveBoundaries()` quando precisar:
|
|
613
|
+
- Compilar múltiplos slots independentemente
|
|
614
|
+
- Controlar ordem/momento de execução
|
|
615
|
+
- Adicionar lógica de lifecycle (begin/end, try/finally)
|
|
616
|
+
- DSL completamente diferente internamente
|
|
617
|
+
|
|
395
618
|
## Builders
|
|
396
619
|
|
|
397
620
|
Funções declarativas para construir expressões:
|
|
@@ -399,7 +622,7 @@ Funções declarativas para construir expressões:
|
|
|
399
622
|
```typescript
|
|
400
623
|
import { builders } from '@statedelta-libs/expressions';
|
|
401
624
|
|
|
402
|
-
const { $, $fn, $if, $pipe, $cond } = builders;
|
|
625
|
+
const { $, $fn, $if, $pipe, $cond, $cb } = builders;
|
|
403
626
|
|
|
404
627
|
// Path reference
|
|
405
628
|
$("player.hp") // { $: "player.hp" }
|
|
@@ -420,6 +643,10 @@ $pipe(
|
|
|
420
643
|
|
|
421
644
|
// Condition
|
|
422
645
|
$cond($("age"), "gte", 18) // { left: ..., op: "gte", right: 18 }
|
|
646
|
+
|
|
647
|
+
// Callback (context)
|
|
648
|
+
$cb("tryCatch", $fn("query")) // { $cb: "tryCatch", body: {...} }
|
|
649
|
+
$cb("transaction", $fn("save"), { isolation: "serializable" })
|
|
423
650
|
```
|
|
424
651
|
|
|
425
652
|
## TypeScript
|
|
@@ -432,15 +659,27 @@ import type {
|
|
|
432
659
|
ConditionalExpr,
|
|
433
660
|
FnExpr,
|
|
434
661
|
PipeExpr,
|
|
662
|
+
CbExpr,
|
|
435
663
|
Condition,
|
|
436
664
|
ConditionGroup,
|
|
437
665
|
ConditionExpr,
|
|
438
666
|
ConditionOp,
|
|
439
667
|
Scope,
|
|
668
|
+
Context,
|
|
669
|
+
ContextFn,
|
|
670
|
+
PathGetterFn,
|
|
440
671
|
CompileOptions,
|
|
441
672
|
AccessorFn,
|
|
442
673
|
TransformFn,
|
|
443
674
|
Transforms,
|
|
675
|
+
// Boundaries
|
|
676
|
+
BoundaryResolver,
|
|
677
|
+
BoundaryResolvers,
|
|
678
|
+
ResolverContext,
|
|
679
|
+
ResolverResult,
|
|
680
|
+
ResolveBoundariesOptions,
|
|
681
|
+
ResolveBoundariesResult,
|
|
682
|
+
IdGenerator,
|
|
444
683
|
} from '@statedelta-libs/expressions';
|
|
445
684
|
|
|
446
685
|
// Type guards
|
|
@@ -449,6 +688,7 @@ import {
|
|
|
449
688
|
isConditional,
|
|
450
689
|
isFn,
|
|
451
690
|
isPipe,
|
|
691
|
+
isCb,
|
|
452
692
|
isCondition,
|
|
453
693
|
isLiteral,
|
|
454
694
|
} from '@statedelta-libs/expressions';
|
|
@@ -505,6 +745,40 @@ Funções só são acessíveis se existirem no `scope` fornecido pelo desenvolve
|
|
|
505
745
|
|
|
506
746
|
4. **Novos tipos**: `Transforms` (alias para `Record<string, TransformFn>`)
|
|
507
747
|
|
|
748
|
+
### v1.2 → v2.0
|
|
749
|
+
|
|
750
|
+
1. **Novo tipo `$cb`**: HOC de continuidade para wrapping contextual:
|
|
751
|
+
```typescript
|
|
752
|
+
// tryCatch, transaction, cached, etc.
|
|
753
|
+
{ $cb: "tryCatch", body: { $fn: "query" }, params: { fallback: [] } }
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
2. **Novo `context` em CompileOptions**: Separado de `scope` para HOCs:
|
|
757
|
+
```typescript
|
|
758
|
+
compile(expr, { scope, context });
|
|
759
|
+
compileAST(expr, { scope, context });
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
3. **Novos tipos**: `CbExpr`, `Context`, `ContextFn`, `PathGetterFn`
|
|
763
|
+
|
|
764
|
+
4. **Novo type guard**: `isCb()`
|
|
765
|
+
|
|
766
|
+
5. **Novo builder**: `$cb(name, body, params?)`
|
|
767
|
+
|
|
768
|
+
6. **Novo extractor**: `extractContextFns()`
|
|
769
|
+
|
|
770
|
+
7. **Novo `resolveBoundaries()`**: Para DSL customizados com compilação independente de slots:
|
|
771
|
+
```typescript
|
|
772
|
+
const { expr, scope } = resolveBoundaries(richExpr, {
|
|
773
|
+
resolvers: { $simulate: (node, ctx) => ... },
|
|
774
|
+
scope: baseScope,
|
|
775
|
+
genId: () => nanoid(), // opcional
|
|
776
|
+
});
|
|
777
|
+
compile(expr, { scope });
|
|
778
|
+
```
|
|
779
|
+
|
|
780
|
+
8. **Novos tipos**: `BoundaryResolver`, `BoundaryResolvers`, `ResolverContext`, `ResolverResult`, `ResolveBoundariesOptions`, `ResolveBoundariesResult`, `IdGenerator`
|
|
781
|
+
|
|
508
782
|
## Licença
|
|
509
783
|
|
|
510
784
|
MIT © Anderson D. Rosa
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var omniAst=require('omni-ast');var rn=Object.defineProperty;var sn=(n,t)=>{for(var s in t)rn(n,s,{get:t[s],enumerable:true});};var y=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,T=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,b=n=>n!==null&&typeof n=="object"&&"$fn"in n&&typeof n.$fn=="string",C=n=>n!==null&&typeof n=="object"&&"$pipe"in n&&Array.isArray(n.$pipe),x=new Set(["eq","neq","gt","gte","lt","lte","in","notIn","contains","notContains","exists","notExists","matches","notMatches","startsWith","endsWith"]),E=n=>n!==null&&typeof n=="object"&&"left"in n&&"op"in n&&x.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),h=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,fn=n=>E(n)||h(n),I=n=>{if(n===null)return true;let t=typeof n;if(t==="string"||t==="number"||t==="boolean"||Array.isArray(n))return true;if(t==="object"&&n!==null){let s=n,i="left"in s&&"op"in s&&x.has(s.op);return !("$"in s)&&!("$if"in s)&&!("$fn"in s)&&!("$pipe"in s)&&!i&&!("logic"in s)}return false};var R=new Map;function J(n){let t=[],s=n.length,i=0,r="";for(;i<s;){let o=n[i];if(o===".")r&&(t.push({type:"key",value:r}),r=""),i++;else if(o==="["){r&&(t.push({type:"key",value:r}),r=""),i++;let e=i;for(;i<s&&n[i]!=="]";)i++;let f=n.slice(e,i);if(i++,f==="*")t.push({type:"wildcard",value:"*"});else {let l=parseInt(f,10);t.push({type:"index",value:isNaN(l)?f:l});}}else r+=o,i++;}return r&&t.push({type:"key",value:r}),t}function B(n){return n.includes("[*]")}function O(n){let t=R.get(n);return t||(t=B(n)?ln(n):un(n),R.set(n,t),t)}function un(n){if(!n.includes(".")&&!n.includes("["))return r=>r?.[n];let t=J(n),s=t.length;if(s===2){let[r,o]=t,e=r.value,f=o.value;return l=>l?.[e]?.[f]}if(s===3){let[r,o,e]=t,f=r.value,l=o.value,c=e.value;return a=>a?.[f]?.[l]?.[c]}let i=t.map(r=>r.value);return r=>{let o=r;for(let e=0;e<s&&o!=null;e++)o=o[i[e]];return o}}function ln(n){let t=J(n),s=[];for(let i=0;i<t.length;i++)t[i].type==="wildcard"&&s.push(i);return s.length===1?cn(t,s[0]):an(t,s)}function cn(n,t){let s=n.slice(0,t).map(e=>e.value),i=n.slice(t+1).map(e=>e.value),r=s.length,o=i.length;if(o===0){if(r===1){let e=s[0];return f=>f?.[e]}return e=>{let f=e;for(let l=0;l<r&&f!=null;l++)f=f[s[l]];return f}}if(o===1){let e=i[0];if(r===1){let f=s[0];return l=>{let c=l?.[f];if(Array.isArray(c))return c.map(a=>a?.[e])}}return f=>{let l=f;for(let c=0;c<r&&l!=null;c++)l=l[s[c]];if(Array.isArray(l))return l.map(c=>c?.[e])}}return e=>{let f=e;for(let l=0;l<r&&f!=null;l++)f=f[s[l]];if(Array.isArray(f))return f.map(l=>{let c=l;for(let a=0;a<o&&c!=null;a++)c=c[i[a]];return c})}}function an(n,t){let s=[],i=0;for(let o=0;o<t.length;o++){let e=t[o],f=o===t.length-1,l=n.slice(i,e).map(c=>c.value);l.length>0&&s.push({type:"access",keys:l}),s.push({type:f?"map":"flatMap",keys:[]}),i=e+1;}let r=n.slice(i).map(o=>o.value);return o=>{let e=o;for(let f of s){if(e==null)return;if(f.type==="access")for(let l of f.keys){if(e==null)return;e=e[l];}else if(f.type==="flatMap"){if(!Array.isArray(e))return;e=e.flatMap(l=>{let c=l;return Array.isArray(c)?c:[c]});}else if(f.type==="map"){if(!Array.isArray(e))return;r.length>0&&(e=e.map(l=>{let c=l;for(let a of r){if(c==null)return;c=c[a];}return c}));}}return e}}function pn(n,t){return O(t)(n)}function F(n){let t=n.indexOf("[*]");return t===-1?n:n.slice(0,t)}function dn(){R.clear();}function gn(){return R.size}function w(n){let t=new Set;return A(n,t),Array.from(t)}function A(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r=0;r<n.length;r++)A(n[r],t);return}if(y(n)){t.add(F(n.$));return}if(T(n)){if(typeof n.$if=="string"){let r=n.$if.startsWith("!")?n.$if.slice(1):n.$if;t.add(F(r));}else A(n.$if,t);A(n.then,t),n.else!==void 0&&A(n.else,t);return}if(C(n)){for(let r=0;r<n.$pipe.length;r++)A(n.$pipe[r],t);return}if(b(n)){if(n.args)for(let r=0;r<n.args.length;r++)A(n.args[r],t);return}if(E(n)){A(n.left,t),n.right!==void 0&&A(n.right,t);return}if(h(n)){for(let r=0;r<n.conditions.length;r++)A(n.conditions[r],t);return}let s=n,i=Object.keys(s);for(let r=0;r<i.length;r++)A(s[i[r]],t);}function mn(n){return w(n).length>0}function yn(n){return w(n).length===0}function En(n){return JSON.stringify(n)}function N(n,t={}){let s=t.scope??{},i=t.accessor,r=m(n,s,i),o=w(n),e=En(n);return {fn:r,deps:o,hash:e}}function m(n,t,s){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let i=n.map(r=>m(r,t,s));return r=>i.map(o=>o(r))}if(y(n))return hn(n,s);if(T(n))return Tn(n,t,s);if(C(n))return bn(n,t,s);if(b(n))return Cn(n,t,s);if(E(n))return An(n,t,s);if(h(n))return $n(n,t,s);if(I(n)){let i=n,r=Object.keys(i),o=r.map(e=>m(i[e],t,s));return e=>{let f={};for(let l=0;l<r.length;l++)f[r[l]]=o[l](e);return f}}return ()=>n}function K(n,t){return t?s=>t(n,s):O(n)}function hn(n,t){return K(n.$,t)}function Tn(n,t,s){let i;if(typeof n.$if=="string"){let e=n.$if.startsWith("!")?n.$if.slice(1):n.$if,f=K(e,s);i=n.$if.startsWith("!")?c=>!f(c):c=>!!f(c);}else {let e=m(n.$if,t,s);i=f=>!!e(f);}let r=m(n.then,t,s),o=n.else!==void 0?m(n.else,t,s):()=>{};return e=>i(e)?r(e):o(e)}function bn(n,t,s){let i=n.$pipe;if(i.length===0)return ()=>{};if(i.length===1)return m(i[0],t,s);let r=m(i[0],t,s),o=i.slice(1).map(f=>m(f,t,s)),e=o.length;if(e===1){let[f]=o;return l=>{let c=r(l),a=f(l);return typeof a=="function"?a(c):a}}if(e===2){let[f,l]=o;return c=>{let a=r(c),p=f(c);return a=typeof p=="function"?p(a):p,p=l(c),typeof p=="function"?p(a):p}}if(e===3){let[f,l,c]=o;return a=>{let p=r(a),d=f(a);return p=typeof d=="function"?d(p):d,d=l(a),p=typeof d=="function"?d(p):d,d=c(a),typeof d=="function"?d(p):d}}return f=>{let l=r(f);for(let c=0;c<e;c++){let a=o[c](f);l=typeof a=="function"?a(l):a;}return l}}function Cn(n,t,s){let i=n.$fn,r=n.args;if(r===void 0)return ()=>{let f=t[i];if(!f)throw new Error(`Function not found in scope: ${i}`);return f};let o=r.map(f=>m(f,t,s)),e=o.length;if(e===0)return f=>{let l=t[i];if(!l)throw new Error(`Function not found in scope: ${i}`);return l()};if(e===1){let[f]=o;return l=>{let c=t[i];if(!c)throw new Error(`Function not found in scope: ${i}`);return c(f(l))}}if(e===2){let[f,l]=o;return c=>{let a=t[i];if(!a)throw new Error(`Function not found in scope: ${i}`);return a(f(c),l(c))}}if(e===3){let[f,l,c]=o;return a=>{let p=t[i];if(!p)throw new Error(`Function not found in scope: ${i}`);return p(f(a),l(a),c(a))}}return f=>{let l=t[i];if(!l)throw new Error(`Function not found in scope: ${i}`);return l(...o.map(c=>c(f)))}}function An(n,t,s){let i=m(n.left,t,s),r=n.right!==void 0?m(n.right,t,s):()=>{};switch(n.op){case "eq":return o=>i(o)===r(o);case "neq":return o=>i(o)!==r(o);case "gt":return o=>i(o)>r(o);case "gte":return o=>i(o)>=r(o);case "lt":return o=>i(o)<r(o);case "lte":return o=>i(o)<=r(o);case "in":return o=>{let e=r(o);return Array.isArray(e)&&e.includes(i(o))};case "notIn":return o=>{let e=r(o);return !Array.isArray(e)||!e.includes(i(o))};case "contains":return o=>{let e=i(o);return Array.isArray(e)&&e.includes(r(o))};case "notContains":return o=>{let e=i(o);return !Array.isArray(e)||!e.includes(r(o))};case "exists":return o=>i(o)!==void 0;case "notExists":return o=>i(o)===void 0;case "matches":return o=>{let e=i(o),f=r(o);return typeof e!="string"||typeof f!="string"?false:new RegExp(f).test(e)};case "notMatches":return o=>{let e=i(o),f=r(o);return typeof e!="string"||typeof f!="string"?true:!new RegExp(f).test(e)};case "startsWith":return o=>{let e=i(o),f=r(o);return typeof e=="string"&&typeof f=="string"&&e.startsWith(f)};case "endsWith":return o=>{let e=i(o),f=r(o);return typeof e=="string"&&typeof f=="string"&&e.endsWith(f)}}}function $n(n,t,s){let i=n.conditions.map(o=>m(o,t,s)),r=i.length;if(r===1)return o=>!!i[0](o);if(r===2){let[o,e]=i;return n.logic==="AND"?f=>!!o(f)&&!!e(f):f=>!!o(f)||!!e(f)}if(r===3){let[o,e,f]=i;return n.logic==="AND"?l=>!!o(l)&&!!e(l)&&!!f(l):l=>!!o(l)||!!e(l)||!!f(l)}return n.logic==="AND"?o=>{for(let e=0;e<r;e++)if(!i[e](o))return false;return true}:o=>{for(let e=0;e<r;e++)if(i[e](o))return true;return false}}function Sn(n,t,s={}){return N(n,s).fn(t)}var j=class{constructor(t=1e3){this.cache=new Map,this._maxSize=t;}get(t,s={}){let i=JSON.stringify(t),r=this.cache.get(i);if(r)return this.cache.delete(i),this.cache.set(i,r),r;let o=N(t,s);if(this.cache.size>=this._maxSize){let e=this.cache.keys().next().value;e&&this.cache.delete(e);}return this.cache.set(i,o),o}has(t){return this.cache.has(JSON.stringify(t))}delete(t){return this.cache.delete(JSON.stringify(t))}clear(){this.cache.clear();}get size(){return this.cache.size}get maxSize(){return this._maxSize}set maxSize(t){for(this._maxSize=t;this.cache.size>this._maxSize;){let s=this.cache.keys().next().value;s&&this.cache.delete(s);}}},P=new j;function wn(n,t={}){return P.get(n,t)}function M(n,t="root",s={}){let i=[];return $(n,t,i,s),{valid:i.length===0,errors:i}}function $(n,t,s,i){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let e=0;e<n.length;e++)$(n[e],`${t}[${e}]`,s,i);return}if(y(n)){(!n.$||typeof n.$!="string")&&s.push(`${t}: invalid reference, $ must be non-empty string`);return}if(T(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||s.push(`${t}.$if: empty path in string shorthand`):$(n.$if,`${t}.$if`,s,i),$(n.then,`${t}.then`,s,i),n.else!==void 0&&$(n.else,`${t}.else`,s,i);return}if(C(n)){if(!Array.isArray(n.$pipe)){s.push(`${t}.$pipe: must be an array`);return}if(n.$pipe.length===0){s.push(`${t}.$pipe: must have at least one element`);return}for(let e=0;e<n.$pipe.length;e++)$(n.$pipe[e],`${t}.$pipe[${e}]`,s,i);return}if(b(n)){if(!n.$fn||typeof n.$fn!="string"){s.push(`${t}: invalid function, $fn must be non-empty string`);return}if(i.scope&&!(n.$fn in i.scope)&&s.push(`${t}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))s.push(`${t}.args: must be an array`);else for(let e=0;e<n.args.length;e++)$(n.args[e],`${t}.args[${e}]`,s,i);return}if(E(n)){x.has(n.op)||s.push(`${t}: invalid operator "${n.op}"`),$(n.left,`${t}.left`,s,i),n.right!==void 0&&$(n.right,`${t}.right`,s,i);return}if(h(n)){if(n.logic!=="AND"&&n.logic!=="OR"&&s.push(`${t}: invalid logic "${n.logic}", must be "AND" or "OR"`),!Array.isArray(n.conditions)){s.push(`${t}.conditions: must be an array`);return}for(let e=0;e<n.conditions.length;e++)$(n.conditions[e],`${t}.conditions[${e}]`,s,i);return}let r=n,o=Object.keys(r);for(let e=0;e<o.length;e++){let f=o[e];$(r[f],`${t}.${f}`,s,i);}}function kn(n,t={}){let s=M(n,"root",t);if(!s.valid)throw new Error(`Invalid expression: ${s.errors.join("; ")}`)}function xn(n,t={}){return M(n,"root",t).valid}var X={};sn(X,{$:()=>Y,$cond:()=>U,$fn:()=>H,$if:()=>Fn,$pipe:()=>Q,cond:()=>jn,fn:()=>On,pipe:()=>Nn,ref:()=>Rn});function Y(n){return {$:n}}var Rn=Y;function H(n,t){return t===void 0||t.length===0?{$fn:n}:{$fn:n,args:t}}var On=H;function Fn(n,t,s){return s===void 0?{$if:n,then:t}:{$if:n,then:t,else:s}}function Q(...n){return {$pipe:n}}var Nn=Q;function U(n,t,s){return s===void 0?{left:n,op:t}:{left:n,op:t,right:s}}var jn=U;var V="data",nn="scope",vn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function G(n,t={}){let{dataParam:s=V,scopeParam:i=nn,noPrefixes:r=false,useAccessor:o=false,lexicalPrefix:e}=t;return g(n,s,i,r,o,e)}function g(n,t,s,i,r,o){if(n===null)return omniAst.builders.literal(null);if(typeof n=="string")return omniAst.builders.literal(n);if(typeof n=="number")return omniAst.builders.literal(n);if(typeof n=="boolean")return omniAst.builders.literal(n);if(Array.isArray(n))return omniAst.builders.arrayExpression(n.map(e=>g(e,t,s,i,r,o)));if(y(n))return Gn(n.$,t,i,r,o);if(T(n))return Dn(n,t,s,i,r,o);if(C(n))return In(n.$pipe,t,s,i,r,o);if(b(n))return zn(n,t,s,i,r,o);if(E(n))return Mn(n,t,s,i,r,o);if(h(n))return Vn(n,t,s,i,r,o);if(typeof n=="object"){let f=Object.entries(n).map(([l,c])=>omniAst.builders.property(omniAst.builders.identifier(l),g(c,t,s,i,r,o)));return omniAst.builders.objectExpression(f)}return omniAst.builders.literal(null)}var _="accessor";function L(n,t){return t?n===t||n.startsWith(t+"."):false}function Gn(n,t,s,i,r){return i?L(n,r)?k(n,t,true):omniAst.builders.callExpression(omniAst.builders.identifier(_),[omniAst.builders.literal(n),omniAst.builders.identifier(t)]):n.includes("[*]")?Wn(n,t,s):k(n,t,s)}function k(n,t,s){let i=v(n);if(i.length===0)return s?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(t);let r;if(s){let o=i[0];r=omniAst.builders.identifier(o.value);for(let e=1;e<i.length;e++){let f=i[e];f.type==="key"?r=omniAst.builders.memberExpression(r,omniAst.builders.identifier(f.value),false,true):r=omniAst.builders.memberExpression(r,omniAst.builders.literal(f.value),true,true);}}else {r=omniAst.builders.identifier(t);for(let o of i)o.type==="key"?r=omniAst.builders.memberExpression(r,omniAst.builders.identifier(o.value),false,true):r=omniAst.builders.memberExpression(r,omniAst.builders.literal(o.value),true,true);}return r}function Wn(n,t,s){let i=n.indexOf("[*]"),r=n.slice(0,i),o=n.slice(i+3),e;if(r?e=k(r,t,s):e=s?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(t),!o||o==="")return e;if(o.includes("[*]"))return tn(e,o);let f="_i",l=o.startsWith(".")?o.slice(1):o,c=omniAst.builders.identifier(f);if(l){let a=v(l);for(let p of a)p.type==="key"?c=omniAst.builders.memberExpression(c,omniAst.builders.identifier(p.value),false,true):c=omniAst.builders.memberExpression(c,omniAst.builders.literal(p.value),true,true);}return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("map"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(f)],c)])}function tn(n,t){let s=t.indexOf("[*]"),i=t.slice(0,s),r=t.slice(s+3),o="_i",e=i.startsWith(".")?i.slice(1):i,f=omniAst.builders.identifier(o);if(e){let c=v(e);for(let a of c)a.type==="key"&&(f=omniAst.builders.memberExpression(f,omniAst.builders.identifier(a.value),false,true));}if(r.includes("[*]")){let c=tn(f,r);return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(o)],c)])}let l=r.startsWith(".")?r.slice(1):r;if(l){let c=v(l);for(let a of c)a.type==="key"&&(f=omniAst.builders.memberExpression(f,omniAst.builders.identifier(a.value),false,true));}return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(o)],f)])}function Dn(n,t,s,i,r,o){let e;if(typeof n.$if=="string"){let c=n.$if.startsWith("!"),a=c?n.$if.slice(1):n.$if,p;r?L(a,o)?p=k(a,t,true):p=omniAst.builders.callExpression(omniAst.builders.identifier(_),[omniAst.builders.literal(a),omniAst.builders.identifier(t)]):p=k(a,t,i),e=c?omniAst.builders.unaryExpression("!",p):p;}else e=g(n.$if,t,s,i,r,o);let f=g(n.then,t,s,i,r,o),l=n.else!==void 0?g(n.else,t,s,i,r,o):omniAst.builders.identifier("undefined");return omniAst.builders.conditionalExpression(e,f,l)}function zn(n,t,s,i,r,o){let e=i?omniAst.builders.identifier(n.$fn):omniAst.builders.memberExpression(omniAst.builders.identifier(s),omniAst.builders.identifier(n.$fn),false,false);if(n.args===void 0)return e;let f=n.args.map(l=>g(l,t,s,i,r,o));return omniAst.builders.callExpression(e,f)}function In(n,t,s,i,r,o){if(n.length===0)return omniAst.builders.identifier("undefined");if(n.length===1)return g(n[0],t,s,i,r,o);let e=g(n[0],t,s,i,r,o);for(let f=1;f<n.length;f++){let l=g(n[f],t,s,i,r,o);e=omniAst.builders.callExpression(l,[e]);}return e}function Z(n,t,s,i,r,o){if(y(n)){let e=n.$;return r?L(e,o)?k(e,t,true):omniAst.builders.callExpression(omniAst.builders.identifier(_),[omniAst.builders.literal(e),omniAst.builders.identifier(t)]):k(e,t,i)}return g(n,t,s,i,r,o)}function Mn(n,t,s,i,r,o){let e=Z(n.left,t,s,i,r,o),f=n.right!==void 0?Z(n.right,t,s,i,r,o):omniAst.builders.literal(null),l=vn[n.op];if(l)return omniAst.builders.binaryExpression(l,e,f);switch(n.op){case "in":return omniAst.builders.callExpression(omniAst.builders.memberExpression(f,omniAst.builders.identifier("includes")),[e]);case "notIn":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(f,omniAst.builders.identifier("includes")),[e]));case "contains":return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("includes"),false,true),[f]);case "notContains":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("includes"),false,true),[f]));case "exists":return omniAst.builders.binaryExpression("!=",e,omniAst.builders.literal(null));case "notExists":return omniAst.builders.binaryExpression("==",e,omniAst.builders.literal(null));case "matches":return omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[f]),omniAst.builders.identifier("test")),[e]);case "notMatches":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[f]),omniAst.builders.identifier("test")),[e]));case "startsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("startsWith"),false,true),[f]);case "endsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("endsWith"),false,true),[f]);default:return omniAst.builders.binaryExpression("===",e,f)}}function Vn(n,t,s,i,r,o){let{logic:e,conditions:f}=n,l=e==="AND"?"&&":"||";if(f.length===0)return omniAst.builders.literal(e==="AND");if(f.length===1)return g(f[0],t,s,i,r,o);let c=g(f[0],t,s,i,r,o);for(let a=1;a<f.length;a++){let p=g(f[a],t,s,i,r,o);c=omniAst.builders.logicalExpression(l,c,p);}return c}function v(n){let t=[],s=n.length,i=0,r="";for(;i<s;){let o=n[i];if(o===".")r&&(t.push({type:"key",value:r}),r=""),i++;else if(o==="["){r&&(t.push({type:"key",value:r}),r=""),i++;let e=i;for(;i<s&&n[i]!=="]";)i++;let f=n.slice(e,i);if(i++,f!=="*"){let l=parseInt(f,10);t.push({type:"index",value:isNaN(l)?f:l});}}else r+=o,i++;}return r&&t.push({type:"key",value:r}),t}function en(n,t=[V]){return omniAst.builders.arrowFunctionExpression(t.map(s=>omniAst.builders.identifier(s)),n)}function W(n){let t=new Set;return S(n,t),t}function S(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let i of n)S(i,t);return}if(y(n))return;if(T(n)){S(n.$if,t),S(n.then,t),n.else!==void 0&&S(n.else,t);return}if(C(n)){for(let i of n.$pipe)S(i,t);return}if(b(n)){if(t.add(n.$fn),n.args)for(let i of n.args)S(i,t);return}if(E(n)){n.left!==void 0&&typeof n.left=="object"&&S(n.left,t),n.right!==void 0&&typeof n.right=="object"&&S(n.right,t);return}if(h(n)){for(let i of n.conditions)S(i,t);return}let s=n;for(let i of Object.keys(s))S(s[i],t);}function D(n){let t=new Set;for(let s of n){let i=s.indexOf("."),r=s.indexOf("["),o=s.length;i!==-1&&(o=Math.min(o,i)),r!==-1&&(o=Math.min(o,r));let e=s.slice(0,o);e&&t.add(e);}return t}function Ln(n){return JSON.stringify(n)}function qn(n,t,s,i,r){let o=G(n,{noPrefixes:true,useAccessor:i,lexicalPrefix:r}),e=omniAst.generate(o),f="";i?r&&(f=`const{${r}}=data??{};`):t.size>0&&(f=`const{${[...t].join(",")}}=data??{};`);let l=i?new Set([...s,"accessor"]):s,c=l.size>0?`const{${[...l].join(",")}}=scope;`:"";return c?`(function(scope){${c}return function(data){${f}return ${e}}})`:`(function(){return function(data){${f}return ${e}}})`}function q(n,t={}){let{scope:s={},returnCode:i=false,useAccessor:r=false,lexicalPrefix:o}=t,e=w(n),f=D(e),l=W(n),c=Ln(n),a=qn(n,f,l,r,o);if(i)return {code:a,deps:e,hash:c,dataRoots:[...f],scopeFns:[...l]};let p;try{p=new Function(`return ${a}`)()(s);}catch(d){throw new Error(`AST compilation failed. If this is due to CSP, use the standard compile() function instead. Error: ${d instanceof Error?d.message:String(d)}`)}return {fn:p,deps:e,hash:c}}function on(n,t,s={}){let{fn:i}=q(n,s);return i(t)}function Jn(n,t){return z(n,t)}function z(n,t){if(n===null)return null;if(typeof n!="object")return n;if(Array.isArray(n))return n.map(o=>z(o,t));let s=n,i=Object.keys(s);for(let o of i)if(o in t){let e=t[o](s);if(typeof e=="object"&&e!==null&&o in e)throw new Error(`Transform "${o}" returned object with same key \u2014 infinite loop`);return z(e,t)}let r={};for(let o of i)r[o]=z(s[o],t);return r}var bt="2.0.0";exports.ExpressionCache=j;exports.VERSION=bt;exports.assertValid=kn;exports.builders=X;exports.cache=P;exports.cached=wn;exports.clearPathCache=dn;exports.compile=N;exports.compileAST=q;exports.compilePath=O;exports.dslToAST=G;exports.evaluate=Sn;exports.evaluateAST=on;exports.extractDataRoots=D;exports.extractDeps=w;exports.extractScopeFns=W;exports.get=pn;exports.getPathCacheSize=gn;exports.hasDeps=mn;exports.hasWildcard=B;exports.isCondition=E;exports.isConditionExpr=fn;exports.isConditionGroup=h;exports.isConditional=T;exports.isFn=b;exports.isLiteral=I;exports.isPipe=C;exports.isPure=yn;exports.isRef=y;exports.isValid=xn;exports.normalize=Jn;exports.normalizePath=F;exports.validate=M;exports.wrapInFunction=en;
|
|
1
|
+
'use strict';var omniAst=require('omni-ast');var mn=Object.defineProperty;var En=(n,t)=>{for(var o in t)mn(n,o,{get:t[o],enumerable:true});};var E=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,S=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,k=n=>n!==null&&typeof n=="object"&&"$fn"in n&&typeof n.$fn=="string",x=n=>n!==null&&typeof n=="object"&&"$pipe"in n&&Array.isArray(n.$pipe),R=n=>n!==null&&typeof n=="object"&&"$cb"in n&&typeof n.$cb=="string"&&"body"in n,G=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&&G.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),b=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,hn=n=>h(n)||b(n),q=n=>{if(n===null)return true;let t=typeof n;if(t==="string"||t==="number"||t==="boolean"||Array.isArray(n))return true;if(t==="object"&&n!==null){let o=n,r="left"in o&&"op"in o&&G.has(o.op);return !("$"in o)&&!("$if"in o)&&!("$fn"in o)&&!("$pipe"in o)&&!("$cb"in o)&&!r&&!("logic"in o)}return false};var I=new Map;function Q(n){let t=[],o=n.length,r=0,i="";for(;r<o;){let s=n[r];if(s===".")i&&(t.push({type:"key",value:i}),i=""),r++;else if(s==="["){i&&(t.push({type:"key",value:i}),i=""),r++;let e=r;for(;r<o&&n[r]!=="]";)r++;let f=n.slice(e,r);if(r++,f==="*")t.push({type:"wildcard",value:"*"});else {let u=parseInt(f,10);t.push({type:"index",value:isNaN(u)?f:u});}}else i+=s,r++;}return i&&t.push({type:"key",value:i}),t}function U(n){return n.includes("[*]")}function N(n){let t=I.get(n);return t||(t=U(n)?Cn(n):bn(n),I.set(n,t),t)}function bn(n){if(!n.includes(".")&&!n.includes("["))return i=>i?.[n];let t=Q(n),o=t.length;if(o===2){let[i,s]=t,e=i.value,f=s.value;return u=>u?.[e]?.[f]}if(o===3){let[i,s,e]=t,f=i.value,u=s.value,l=e.value;return a=>a?.[f]?.[u]?.[l]}let r=t.map(i=>i.value);return i=>{let s=i;for(let e=0;e<o&&s!=null;e++)s=s[r[e]];return s}}function Cn(n){let t=Q(n),o=[];for(let r=0;r<t.length;r++)t[r].type==="wildcard"&&o.push(r);return o.length===1?Tn(t,o[0]):$n(t,o)}function Tn(n,t){let o=n.slice(0,t).map(e=>e.value),r=n.slice(t+1).map(e=>e.value),i=o.length,s=r.length;if(s===0){if(i===1){let e=o[0];return f=>f?.[e]}return e=>{let f=e;for(let u=0;u<i&&f!=null;u++)f=f[o[u]];return f}}if(s===1){let e=r[0];if(i===1){let f=o[0];return u=>{let l=u?.[f];if(Array.isArray(l))return l.map(a=>a?.[e])}}return f=>{let u=f;for(let l=0;l<i&&u!=null;l++)u=u[o[l]];if(Array.isArray(u))return u.map(l=>l?.[e])}}return e=>{let f=e;for(let u=0;u<i&&f!=null;u++)f=f[o[u]];if(Array.isArray(f))return f.map(u=>{let l=u;for(let a=0;a<s&&l!=null;a++)l=l[r[a]];return l})}}function $n(n,t){let o=[],r=0;for(let s=0;s<t.length;s++){let e=t[s],f=s===t.length-1,u=n.slice(r,e).map(l=>l.value);u.length>0&&o.push({type:"access",keys:u}),o.push({type:f?"map":"flatMap",keys:[]}),r=e+1;}let i=n.slice(r).map(s=>s.value);return s=>{let e=s;for(let f of o){if(e==null)return;if(f.type==="access")for(let u of f.keys){if(e==null)return;e=e[u];}else if(f.type==="flatMap"){if(!Array.isArray(e))return;e=e.flatMap(u=>{let l=u;return Array.isArray(l)?l:[l]});}else if(f.type==="map"){if(!Array.isArray(e))return;i.length>0&&(e=e.map(u=>{let l=u;for(let a of i){if(l==null)return;l=l[a];}return l}));}}return e}}function An(n,t){return N(t)(n)}function W(n){let t=n.indexOf("[*]");return t===-1?n:n.slice(0,t)}function Sn(){I.clear();}function kn(){return I.size}function F(n){let t=new Set;return C(n,t),Array.from(t)}function C(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let i=0;i<n.length;i++)C(n[i],t);return}if(E(n)){t.add(W(n.$));return}if(S(n)){if(typeof n.$if=="string"){let i=n.$if.startsWith("!")?n.$if.slice(1):n.$if;t.add(W(i));}else C(n.$if,t);C(n.then,t),n.else!==void 0&&C(n.else,t);return}if(x(n)){for(let i=0;i<n.$pipe.length;i++)C(n.$pipe[i],t);return}if(k(n)){if(n.args)for(let i=0;i<n.args.length;i++)C(n.args[i],t);return}if(R(n)){C(n.body,t),n.params!==void 0&&C(n.params,t);return}if(h(n)){C(n.left,t),n.right!==void 0&&C(n.right,t);return}if(b(n)){for(let i=0;i<n.conditions.length;i++)C(n.conditions[i],t);return}let o=n,r=Object.keys(o);for(let i=0;i<r.length;i++)C(o[r[i]],t);}function xn(n){return F(n).length>0}function Rn(n){return F(n).length===0}function wn(n){return JSON.stringify(n)}function j(n,t={}){let o=t.scope??{},r=t.accessor,i=t.context??{},s=m(n,o,r,i),e=F(n),f=wn(n);return {fn:s,deps:e,hash:f}}function m(n,t,o,r){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let i=n.map(s=>m(s,t,o,r));return s=>i.map(e=>e(s))}if(E(n))return Fn(n,o);if(S(n))return On(n,t,o,r);if(x(n))return vn(n,t,o,r);if(k(n))return jn(n,t,o,r);if(R(n))return Nn(n,t,o,r);if(h(n))return Gn(n,t,o,r);if(b(n))return In(n,t,o,r);if(q(n)){let i=n,s=Object.keys(i),e=s.map(f=>m(i[f],t,o,r));return f=>{let u={};for(let l=0;l<s.length;l++)u[s[l]]=e[l](f);return u}}return ()=>n}function Z(n,t){return t?o=>t(n,o):N(n)}function Fn(n,t){return Z(n.$,t)}function On(n,t,o,r){let i;if(typeof n.$if=="string"){let f=n.$if.startsWith("!")?n.$if.slice(1):n.$if,u=Z(f,o);i=n.$if.startsWith("!")?a=>!u(a):a=>!!u(a);}else {let f=m(n.$if,t,o,r);i=u=>!!f(u);}let s=m(n.then,t,o,r),e=n.else!==void 0?m(n.else,t,o,r):()=>{};return f=>i(f)?s(f):e(f)}function vn(n,t,o,r){let i=n.$pipe;if(i.length===0)return ()=>{};if(i.length===1)return m(i[0],t,o,r);let s=m(i[0],t,o,r),e=i.slice(1).map(u=>m(u,t,o,r)),f=e.length;if(f===1){let[u]=e;return l=>{let a=s(l),p=u(l);return typeof p=="function"?p(a):p}}if(f===2){let[u,l]=e;return a=>{let p=s(a),d=u(a);return p=typeof d=="function"?d(p):d,d=l(a),typeof d=="function"?d(p):d}}if(f===3){let[u,l,a]=e;return p=>{let d=s(p),g=u(p);return d=typeof g=="function"?g(d):g,g=l(p),d=typeof g=="function"?g(d):g,g=a(p),typeof g=="function"?g(d):g}}return u=>{let l=s(u);for(let a=0;a<f;a++){let p=e[a](u);l=typeof p=="function"?p(l):p;}return l}}function jn(n,t,o,r){let i=n.$fn,s=n.args;if(s===void 0)return ()=>{let u=t[i];if(!u)throw new Error(`Function not found in scope: ${i}`);return u};let e=s.map(u=>m(u,t,o,r)),f=e.length;if(f===0)return ()=>{let u=t[i];if(!u)throw new Error(`Function not found in scope: ${i}`);return u()};if(f===1){let[u]=e;return l=>{let a=t[i];if(!a)throw new Error(`Function not found in scope: ${i}`);return a(u(l))}}if(f===2){let[u,l]=e;return a=>{let p=t[i];if(!p)throw new Error(`Function not found in scope: ${i}`);return p(u(a),l(a))}}if(f===3){let[u,l,a]=e;return p=>{let d=t[i];if(!d)throw new Error(`Function not found in scope: ${i}`);return d(u(p),l(p),a(p))}}return u=>{let l=t[i];if(!l)throw new Error(`Function not found in scope: ${i}`);return l(...e.map(a=>a(u)))}}function Nn(n,t,o,r){let i=n.$cb,s=m(n.body,t,o,r),e=n.params?m(n.params,t,o,r):void 0,f=u=>o?l=>o(l,u):l=>N(l)(u);return u=>{let l=r?.[i];if(!l)throw new Error(`Context function not found: ${i}`);let a=(g,w)=>s(g),p=f(u),d=e?e(u):void 0;return l(a,u,p,d)}}function Gn(n,t,o,r){let i=m(n.left,t,o,r),s=n.right!==void 0?m(n.right,t,o,r):()=>{};switch(n.op){case "eq":return e=>i(e)===s(e);case "neq":return e=>i(e)!==s(e);case "gt":return e=>i(e)>s(e);case "gte":return e=>i(e)>=s(e);case "lt":return e=>i(e)<s(e);case "lte":return e=>i(e)<=s(e);case "in":return e=>{let f=s(e);return Array.isArray(f)&&f.includes(i(e))};case "notIn":return e=>{let f=s(e);return !Array.isArray(f)||!f.includes(i(e))};case "contains":return e=>{let f=i(e);return Array.isArray(f)&&f.includes(s(e))};case "notContains":return e=>{let f=i(e);return !Array.isArray(f)||!f.includes(s(e))};case "exists":return e=>i(e)!==void 0;case "notExists":return e=>i(e)===void 0;case "matches":return e=>{let f=i(e),u=s(e);return typeof f!="string"||typeof u!="string"?false:new RegExp(u).test(f)};case "notMatches":return e=>{let f=i(e),u=s(e);return typeof f!="string"||typeof u!="string"?true:!new RegExp(u).test(f)};case "startsWith":return e=>{let f=i(e),u=s(e);return typeof f=="string"&&typeof u=="string"&&f.startsWith(u)};case "endsWith":return e=>{let f=i(e),u=s(e);return typeof f=="string"&&typeof u=="string"&&f.endsWith(u)}}}function In(n,t,o,r){let i=n.conditions.map(e=>m(e,t,o,r)),s=i.length;if(s===1)return e=>!!i[0](e);if(s===2){let[e,f]=i;return n.logic==="AND"?u=>!!e(u)&&!!f(u):u=>!!e(u)||!!f(u)}if(s===3){let[e,f,u]=i;return n.logic==="AND"?l=>!!e(l)&&!!f(l)&&!!u(l):l=>!!e(l)||!!f(l)||!!u(l)}return n.logic==="AND"?e=>{for(let f=0;f<s;f++)if(!i[f](e))return false;return true}:e=>{for(let f=0;f<s;f++)if(i[f](e))return true;return false}}function Wn(n,t,o={}){return j(n,o).fn(t)}var z=class{constructor(t=1e3){this.cache=new Map,this._maxSize=t;}get(t,o={}){let r=JSON.stringify(t),i=this.cache.get(r);if(i)return this.cache.delete(r),this.cache.set(r,i),i;let s=j(t,o);if(this.cache.size>=this._maxSize){let e=this.cache.keys().next().value;e&&this.cache.delete(e);}return this.cache.set(r,s),s}has(t){return this.cache.has(JSON.stringify(t))}delete(t){return this.cache.delete(JSON.stringify(t))}clear(){this.cache.clear();}get size(){return this.cache.size}get maxSize(){return this._maxSize}set maxSize(t){for(this._maxSize=t;this.cache.size>this._maxSize;){let o=this.cache.keys().next().value;o&&this.cache.delete(o);}}},nn=new z;function zn(n,t={}){return nn.get(n,t)}function J(n,t="root",o={}){let r=[];return T(n,t,r,o),{valid:r.length===0,errors:r}}function T(n,t,o,r){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let e=0;e<n.length;e++)T(n[e],`${t}[${e}]`,o,r);return}if(E(n)){(!n.$||typeof n.$!="string")&&o.push(`${t}: invalid reference, $ must be non-empty string`);return}if(S(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||o.push(`${t}.$if: empty path in string shorthand`):T(n.$if,`${t}.$if`,o,r),T(n.then,`${t}.then`,o,r),n.else!==void 0&&T(n.else,`${t}.else`,o,r);return}if(x(n)){if(!Array.isArray(n.$pipe)){o.push(`${t}.$pipe: must be an array`);return}if(n.$pipe.length===0){o.push(`${t}.$pipe: must have at least one element`);return}for(let e=0;e<n.$pipe.length;e++)T(n.$pipe[e],`${t}.$pipe[${e}]`,o,r);return}if(k(n)){if(!n.$fn||typeof n.$fn!="string"){o.push(`${t}: invalid function, $fn must be non-empty string`);return}if(r.scope&&!(n.$fn in r.scope)&&o.push(`${t}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))o.push(`${t}.args: must be an array`);else for(let e=0;e<n.args.length;e++)T(n.args[e],`${t}.args[${e}]`,o,r);return}if(R(n)){if(!n.$cb||typeof n.$cb!="string"){o.push(`${t}: invalid callback, $cb must be non-empty string`);return}r.context&&!(n.$cb in r.context)&&o.push(`${t}: context function "${n.$cb}" not found`),T(n.body,`${t}.body`,o,r),n.params!==void 0&&T(n.params,`${t}.params`,o,r);return}if(h(n)){G.has(n.op)||o.push(`${t}: invalid operator "${n.op}"`),T(n.left,`${t}.left`,o,r),n.right!==void 0&&T(n.right,`${t}.right`,o,r);return}if(b(n)){if(n.logic!=="AND"&&n.logic!=="OR"&&o.push(`${t}: invalid logic "${n.logic}", must be "AND" or "OR"`),!Array.isArray(n.conditions)){o.push(`${t}.conditions: must be an array`);return}for(let e=0;e<n.conditions.length;e++)T(n.conditions[e],`${t}.conditions[${e}]`,o,r);return}let i=n,s=Object.keys(i);for(let e=0;e<s.length;e++){let f=s[e];T(i[f],`${t}.${f}`,o,r);}}function Dn(n,t={}){let o=J(n,"root",t);if(!o.valid)throw new Error(`Invalid expression: ${o.errors.join("; ")}`)}function Mn(n,t={}){return J(n,"root",t).valid}var un={};En(un,{$:()=>tn,$call:()=>fn,$cb:()=>sn,$cond:()=>rn,$fn:()=>en,$if:()=>Vn,$pipe:()=>on,call:()=>Kn,cb:()=>Jn,cond:()=>qn,fn:()=>_n,pipe:()=>Ln,ref:()=>Bn});function tn(n){return {$:n}}var Bn=tn;function en(n,t){return t===void 0||t.length===0?{$fn:n}:{$fn:n,args:t}}var _n=en;function Vn(n,t,o){return o===void 0?{$if:n,then:t}:{$if:n,then:t,else:o}}function on(...n){return {$pipe:n}}var Ln=on;function rn(n,t,o){return o===void 0?{left:n,op:t}:{left:n,op:t,right:o}}var qn=rn;function sn(n,t,o){return o===void 0?{$cb:n,body:t}:{$cb:n,body:t,params:o}}var Jn=sn;function fn(n,t=[]){return {$fn:n,args:t}}var Kn=fn;var K="data",ln="scope",Xn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function M(n,t={}){let{dataParam:o=K,scopeParam:r=ln,noPrefixes:i=false,useAccessor:s=false,lexicalPrefix:e}=t;return y(n,o,r,i,s,e)}function y(n,t,o,r,i,s){if(n===null)return omniAst.builders.literal(null);if(typeof n=="string")return omniAst.builders.literal(n);if(typeof n=="number")return omniAst.builders.literal(n);if(typeof n=="boolean")return omniAst.builders.literal(n);if(Array.isArray(n))return omniAst.builders.arrayExpression(n.map(e=>y(e,t,o,r,i,s)));if(E(n))return Yn(n.$,t,r,i,s);if(S(n))return Pn(n,t,o,r,i,s);if(x(n))return nt(n.$pipe,t,o,r,i,s);if(k(n))return Qn(n,t,o,r,i,s);if(R(n))return Zn(n,t,o,r,i,s);if(h(n))return tt(n,t,o,r,i,s);if(b(n))return et(n,t,o,r,i,s);if(typeof n=="object"){let f=Object.entries(n).map(([u,l])=>omniAst.builders.property(omniAst.builders.identifier(u),y(l,t,o,r,i,s)));return omniAst.builders.objectExpression(f)}return omniAst.builders.literal(null)}var X="accessor";function Y(n,t){return t?n===t||n.startsWith(t+"."):false}function Yn(n,t,o,r,i){return r?Y(n,i)?O(n,t,true):omniAst.builders.callExpression(omniAst.builders.identifier(X),[omniAst.builders.literal(n),omniAst.builders.identifier(t)]):n.includes("[*]")?Hn(n,t,o):O(n,t,o)}function O(n,t,o){let r=D(n);if(r.length===0)return o?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(t);let i;if(o){let s=r[0];i=omniAst.builders.identifier(s.value);for(let e=1;e<r.length;e++){let f=r[e];f.type==="key"?i=omniAst.builders.memberExpression(i,omniAst.builders.identifier(f.value),false,true):i=omniAst.builders.memberExpression(i,omniAst.builders.literal(f.value),true,true);}}else {i=omniAst.builders.identifier(t);for(let s of r)s.type==="key"?i=omniAst.builders.memberExpression(i,omniAst.builders.identifier(s.value),false,true):i=omniAst.builders.memberExpression(i,omniAst.builders.literal(s.value),true,true);}return i}function Hn(n,t,o){let r=n.indexOf("[*]"),i=n.slice(0,r),s=n.slice(r+3),e;if(i?e=O(i,t,o):e=o?omniAst.builders.identifier("undefined"):omniAst.builders.identifier(t),!s||s==="")return e;if(s.includes("[*]"))return an(e,s);let f="_i",u=s.startsWith(".")?s.slice(1):s,l=omniAst.builders.identifier(f);if(u){let a=D(u);for(let p of a)p.type==="key"?l=omniAst.builders.memberExpression(l,omniAst.builders.identifier(p.value),false,true):l=omniAst.builders.memberExpression(l,omniAst.builders.literal(p.value),true,true);}return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("map"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(f)],l)])}function an(n,t){let o=t.indexOf("[*]"),r=t.slice(0,o),i=t.slice(o+3),s="_i",e=r.startsWith(".")?r.slice(1):r,f=omniAst.builders.identifier(s);if(e){let l=D(e);for(let a of l)a.type==="key"&&(f=omniAst.builders.memberExpression(f,omniAst.builders.identifier(a.value),false,true));}if(i.includes("[*]")){let l=an(f,i);return omniAst.builders.callExpression(omniAst.builders.memberExpression(n,omniAst.builders.identifier("flatMap"),false,true),[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(s)],l)])}let u=i.startsWith(".")?i.slice(1):i;if(u){let l=D(u);for(let a of l)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(s)],f)])}function Pn(n,t,o,r,i,s){let e;if(typeof n.$if=="string"){let l=n.$if.startsWith("!"),a=l?n.$if.slice(1):n.$if,p;i?Y(a,s)?p=O(a,t,true):p=omniAst.builders.callExpression(omniAst.builders.identifier(X),[omniAst.builders.literal(a),omniAst.builders.identifier(t)]):p=O(a,t,r),e=l?omniAst.builders.unaryExpression("!",p):p;}else e=y(n.$if,t,o,r,i,s);let f=y(n.then,t,o,r,i,s),u=n.else!==void 0?y(n.else,t,o,r,i,s):omniAst.builders.identifier("undefined");return omniAst.builders.conditionalExpression(e,f,u)}function Qn(n,t,o,r,i,s){let e=r?omniAst.builders.identifier(n.$fn):omniAst.builders.memberExpression(omniAst.builders.identifier(o),omniAst.builders.identifier(n.$fn),false,false);if(n.args===void 0)return e;let f=n.args.map(u=>y(u,t,o,r,i,s));return omniAst.builders.callExpression(e,f)}var Un="context";function Zn(n,t,o,r,i,s){let e=r?omniAst.builders.identifier(n.$cb):omniAst.builders.memberExpression(omniAst.builders.identifier(Un),omniAst.builders.identifier(n.$cb),false,false),f=y(n.body,t,o,r,i,s),l=[omniAst.builders.arrowFunctionExpression([omniAst.builders.identifier(t),omniAst.builders.identifier("get")],f),omniAst.builders.identifier(t),omniAst.builders.identifier("get")];if(n.params!==void 0){let a=y(n.params,t,o,r,i,s);l.push(a);}return omniAst.builders.callExpression(e,l)}function nt(n,t,o,r,i,s){if(n.length===0)return omniAst.builders.identifier("undefined");if(n.length===1)return y(n[0],t,o,r,i,s);let e=y(n[0],t,o,r,i,s);for(let f=1;f<n.length;f++){let u=y(n[f],t,o,r,i,s);e=omniAst.builders.callExpression(u,[e]);}return e}function cn(n,t,o,r,i,s){if(E(n)){let e=n.$;return i?Y(e,s)?O(e,t,true):omniAst.builders.callExpression(omniAst.builders.identifier(X),[omniAst.builders.literal(e),omniAst.builders.identifier(t)]):O(e,t,r)}return y(n,t,o,r,i,s)}function tt(n,t,o,r,i,s){let e=cn(n.left,t,o,r,i,s),f=n.right!==void 0?cn(n.right,t,o,r,i,s):omniAst.builders.literal(null),u=Xn[n.op];if(u)return omniAst.builders.binaryExpression(u,e,f);switch(n.op){case "in":return omniAst.builders.callExpression(omniAst.builders.memberExpression(f,omniAst.builders.identifier("includes")),[e]);case "notIn":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(f,omniAst.builders.identifier("includes")),[e]));case "contains":return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("includes"),false,true),[f]);case "notContains":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("includes"),false,true),[f]));case "exists":return omniAst.builders.binaryExpression("!=",e,omniAst.builders.literal(null));case "notExists":return omniAst.builders.binaryExpression("==",e,omniAst.builders.literal(null));case "matches":return omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[f]),omniAst.builders.identifier("test")),[e]);case "notMatches":return omniAst.builders.unaryExpression("!",omniAst.builders.callExpression(omniAst.builders.memberExpression(omniAst.builders.newExpression(omniAst.builders.identifier("RegExp"),[f]),omniAst.builders.identifier("test")),[e]));case "startsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("startsWith"),false,true),[f]);case "endsWith":return omniAst.builders.callExpression(omniAst.builders.memberExpression(e,omniAst.builders.identifier("endsWith"),false,true),[f]);default:return omniAst.builders.binaryExpression("===",e,f)}}function et(n,t,o,r,i,s){let{logic:e,conditions:f}=n,u=e==="AND"?"&&":"||";if(f.length===0)return omniAst.builders.literal(e==="AND");if(f.length===1)return y(f[0],t,o,r,i,s);let l=y(f[0],t,o,r,i,s);for(let a=1;a<f.length;a++){let p=y(f[a],t,o,r,i,s);l=omniAst.builders.logicalExpression(u,l,p);}return l}function D(n){let t=[],o=n.length,r=0,i="";for(;r<o;){let s=n[r];if(s===".")i&&(t.push({type:"key",value:i}),i=""),r++;else if(s==="["){i&&(t.push({type:"key",value:i}),i=""),r++;let e=r;for(;r<o&&n[r]!=="]";)r++;let f=n.slice(e,r);if(r++,f!=="*"){let u=parseInt(f,10);t.push({type:"index",value:isNaN(u)?f:u});}}else i+=s,r++;}return i&&t.push({type:"key",value:i}),t}function pn(n,t=[K]){return omniAst.builders.arrowFunctionExpression(t.map(o=>omniAst.builders.identifier(o)),n)}function B(n){let t=new Set;return $(n,t),t}function $(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r of n)$(r,t);return}if(E(n))return;if(S(n)){$(n.$if,t),$(n.then,t),n.else!==void 0&&$(n.else,t);return}if(x(n)){for(let r of n.$pipe)$(r,t);return}if(k(n)){if(t.add(n.$fn),n.args)for(let r of n.args)$(r,t);return}if(R(n)){$(n.body,t),n.params!==void 0&&$(n.params,t);return}if(h(n)){n.left!==void 0&&typeof n.left=="object"&&$(n.left,t),n.right!==void 0&&typeof n.right=="object"&&$(n.right,t);return}if(b(n)){for(let r of n.conditions)$(r,t);return}let o=n;for(let r of Object.keys(o))$(o[r],t);}function _(n){let t=new Set;return A(n,t),t}function A(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r of n)A(r,t);return}if(E(n))return;if(S(n)){A(n.$if,t),A(n.then,t),n.else!==void 0&&A(n.else,t);return}if(x(n)){for(let r of n.$pipe)A(r,t);return}if(k(n)){if(n.args)for(let r of n.args)A(r,t);return}if(R(n)){t.add(n.$cb),A(n.body,t),n.params!==void 0&&A(n.params,t);return}if(h(n)){n.left!==void 0&&typeof n.left=="object"&&A(n.left,t),n.right!==void 0&&typeof n.right=="object"&&A(n.right,t);return}if(b(n)){for(let r of n.conditions)A(r,t);return}let o=n;for(let r of Object.keys(o))A(o[r],t);}function V(n){let t=new Set;for(let o of n){let r=o.indexOf("."),i=o.indexOf("["),s=o.length;r!==-1&&(s=Math.min(s,r)),i!==-1&&(s=Math.min(s,i));let e=o.slice(0,s);e&&t.add(e);}return t}function ot(n){return JSON.stringify(n)}function rt(n,t,o,r,i,s){let e=M(n,{noPrefixes:true,useAccessor:i,lexicalPrefix:s}),f=omniAst.generate(e),u="";i?s&&(u=`const{${s}}=data??{};`):t.size>0&&(u=`const{${[...t].join(",")}}=data??{};`);let l=i?new Set([...o,"accessor"]):o,a=l.size>0?`const{${[...l].join(",")}}=scope;`:"",p=r.size>0?`const{${[...r].join(",")}}=context;`:"",d=r.size>0,g="";d&&(i?g="const get=(path)=>accessor(path,data);":g="const get=(path)=>path.split('.').reduce((o,k)=>o?.[k],data);");let w=l.size>0,v;if(w||d){let gn=d?"scope,context":"scope",yn=`${u}${g}return ${f}`;v=`(function(${gn}){${a}${p}return function(data){${yn}}})`;}else v=`(function(){return function(data){${u}return ${f}}})`;return v}function H(n,t={}){let{scope:o={},context:r={},returnCode:i=false,useAccessor:s=false,lexicalPrefix:e}=t,f=F(n),u=V(f),l=B(n),a=_(n),p=ot(n),d=rt(n,u,l,a,s,e);if(i)return {code:d,deps:f,hash:p,dataRoots:[...u],scopeFns:[...l],contextFns:[...a]};let g;try{let w=a.size>0,v=new Function(`return ${d}`)();g=w?v(o,r):v(o);}catch(w){throw new Error(`AST compilation failed. If this is due to CSP, use the standard compile() function instead. Error: ${w instanceof Error?w.message:String(w)}`)}return {fn:g,deps:f,hash:p}}function dn(n,t,o={}){let{fn:r}=H(n,o);return r(t)}function st(n,t){return L(n,t)}function L(n,t){if(n===null)return null;if(typeof n!="object")return n;if(Array.isArray(n))return n.map(s=>L(s,t));let o=n,r=Object.keys(o);for(let s of r)if(s in t){let e=t[s](o);if(typeof e=="object"&&e!==null&&s in e)throw new Error(`Transform "${s}" returned object with same key \u2014 infinite loop`);return L(e,t)}let i={};for(let s of r)i[s]=L(o[s],t);return i}var ft=new Set(["$","$if","$fn","$pipe","$cb"]);function ut(){let n=0;return ()=>String(n++)}function ct(n,t){let{resolvers:o,scope:r={},genId:i,...s}=t,e=Object.keys(o);if(e.length===0)return {expr:n,scope:r};let f=new Set(e),u=[],l={compile:j,genId:i??ut(),scope:r,options:s},a=P(n,f,o,l,u),p={...r};for(let d=0;d<u.length;d++){let[g,w]=u[d];p[g]=w;}return {expr:a,scope:p}}function P(n,t,o,r,i){if(n===null)return null;if(typeof n!="object")return n;if(Array.isArray(n)){let l=n.length,a=new Array(l);for(let p=0;p<l;p++)a[p]=P(n[p],t,o,r,i);return a}let s=n,e=Object.keys(s),f=e.length;for(let l=0;l<f;l++){let a=e[l];if(a[0]==="$"&&!ft.has(a)&&t.has(a)){let p=o[a],d=p(s,r);return d.scopeEntry&&i.push(d.scopeEntry),d.expr}}let u={};for(let l=0;l<f;l++){let a=e[l];u[a]=P(s[a],t,o,r,i);}return u}var _t="2.0.0";exports.ExpressionCache=z;exports.VERSION=_t;exports.assertValid=Dn;exports.builders=un;exports.cache=nn;exports.cached=zn;exports.clearPathCache=Sn;exports.compile=j;exports.compileAST=H;exports.compilePath=N;exports.dslToAST=M;exports.evaluate=Wn;exports.evaluateAST=dn;exports.extractContextFns=_;exports.extractDataRoots=V;exports.extractDeps=F;exports.extractScopeFns=B;exports.get=An;exports.getPathCacheSize=kn;exports.hasDeps=xn;exports.hasWildcard=U;exports.isCb=R;exports.isCondition=h;exports.isConditionExpr=hn;exports.isConditionGroup=b;exports.isConditional=S;exports.isFn=k;exports.isLiteral=q;exports.isPipe=x;exports.isPure=Rn;exports.isRef=E;exports.isValid=Mn;exports.normalize=st;exports.normalizePath=W;exports.resolveBoundaries=ct;exports.validate=J;exports.wrapInFunction=pn;
|
package/dist/index.d.cts
CHANGED
|
@@ -44,6 +44,17 @@ interface FnExpr {
|
|
|
44
44
|
interface PipeExpr {
|
|
45
45
|
$pipe: Expression[];
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Callback expression - HOC de continuidade
|
|
49
|
+
* Executa body dentro de um context function (tryCatch, transaction, etc.)
|
|
50
|
+
* @example { $cb: "tryCatch", body: { $fn: "query" } }
|
|
51
|
+
* @example { $cb: "transaction", params: { isolation: "serializable" }, body: { $fn: "query" } }
|
|
52
|
+
*/
|
|
53
|
+
interface CbExpr {
|
|
54
|
+
$cb: string;
|
|
55
|
+
body: Expression;
|
|
56
|
+
params?: Expression;
|
|
57
|
+
}
|
|
47
58
|
/**
|
|
48
59
|
* Literal values (primitives, arrays, plain objects)
|
|
49
60
|
*/
|
|
@@ -75,7 +86,7 @@ type ConditionExpr = Condition | ConditionGroup;
|
|
|
75
86
|
/**
|
|
76
87
|
* Union of all expression types
|
|
77
88
|
*/
|
|
78
|
-
type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | ConditionExpr;
|
|
89
|
+
type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | CbExpr | ConditionExpr;
|
|
79
90
|
/**
|
|
80
91
|
* Compiled expression function
|
|
81
92
|
*/
|
|
@@ -122,6 +133,50 @@ interface ValidationResult {
|
|
|
122
133
|
* @example { add, subtract, multiply, filter, map, sum }
|
|
123
134
|
*/
|
|
124
135
|
type Scope = Record<string, (...args: any[]) => any>;
|
|
136
|
+
/**
|
|
137
|
+
* Path getter function for context callbacks
|
|
138
|
+
*/
|
|
139
|
+
type PathGetterFn = (path: string) => unknown;
|
|
140
|
+
/**
|
|
141
|
+
* Context function - HOC que controla execução do body.
|
|
142
|
+
* Recebe o body como callback e decide quando/se executá-lo.
|
|
143
|
+
*
|
|
144
|
+
* @param cb - Body compilado como callback (recebe data e get)
|
|
145
|
+
* @param data - Dados do runtime
|
|
146
|
+
* @param get - Resolver de paths (accessor)
|
|
147
|
+
* @param params - Parâmetros extras para o context (opcional)
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```ts
|
|
151
|
+
* const tryCatch: ContextFn = (cb, data, get, params) => {
|
|
152
|
+
* try {
|
|
153
|
+
* return cb(data, get);
|
|
154
|
+
* } catch (e) {
|
|
155
|
+
* return params?.fallback ?? null;
|
|
156
|
+
* }
|
|
157
|
+
* };
|
|
158
|
+
*
|
|
159
|
+
* const transaction: ContextFn = (cb, data, get, params) => {
|
|
160
|
+
* const tx = db.beginTransaction(params);
|
|
161
|
+
* try {
|
|
162
|
+
* const result = cb({ ...data, tx }, get);
|
|
163
|
+
* tx.commit();
|
|
164
|
+
* return result;
|
|
165
|
+
* } catch (e) {
|
|
166
|
+
* tx.rollback();
|
|
167
|
+
* throw e;
|
|
168
|
+
* }
|
|
169
|
+
* };
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
type ContextFn<T = any, R = any> = (cb: (data: T, get: PathGetterFn) => R, data: T, get: PathGetterFn, params?: unknown) => R;
|
|
173
|
+
/**
|
|
174
|
+
* Context registry - HOC functions available to $cb expressions.
|
|
175
|
+
* Separate from scope because context functions have different signature.
|
|
176
|
+
*
|
|
177
|
+
* @example { tryCatch, transaction, withRetry }
|
|
178
|
+
*/
|
|
179
|
+
type Context = Record<string, ContextFn>;
|
|
125
180
|
/**
|
|
126
181
|
* Options for compilation
|
|
127
182
|
*/
|
|
@@ -137,6 +192,18 @@ interface CompileOptions<T = unknown> {
|
|
|
137
192
|
* compile(expr, { accessor: (path, ctx) => ctx.get(path) })
|
|
138
193
|
*/
|
|
139
194
|
accessor?: AccessorFn<T>;
|
|
195
|
+
/**
|
|
196
|
+
* Context functions available to $cb expressions.
|
|
197
|
+
* HOC functions that control body execution (tryCatch, transaction, etc.).
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* compile(expr, {
|
|
201
|
+
* context: {
|
|
202
|
+
* tryCatch: (cb, data, get) => { try { return cb(data, get); } catch { return null; } }
|
|
203
|
+
* }
|
|
204
|
+
* })
|
|
205
|
+
*/
|
|
206
|
+
context?: Context;
|
|
140
207
|
}
|
|
141
208
|
/**
|
|
142
209
|
* Check if value is a reference expression
|
|
@@ -154,6 +221,10 @@ declare const isFn: (v: unknown) => v is FnExpr;
|
|
|
154
221
|
* Check if value is a pipe expression
|
|
155
222
|
*/
|
|
156
223
|
declare const isPipe: (v: unknown) => v is PipeExpr;
|
|
224
|
+
/**
|
|
225
|
+
* Check if value is a callback expression
|
|
226
|
+
*/
|
|
227
|
+
declare const isCb: (v: unknown) => v is CbExpr;
|
|
157
228
|
/**
|
|
158
229
|
* Check if value is a condition expression
|
|
159
230
|
*
|
|
@@ -359,6 +430,8 @@ declare function cached<T = unknown, R = unknown>(expr: Expression, options?: Co
|
|
|
359
430
|
interface ValidateOptions {
|
|
360
431
|
/** Scope to validate function names against (optional) */
|
|
361
432
|
scope?: Scope;
|
|
433
|
+
/** Context to validate $cb function names against (optional) */
|
|
434
|
+
context?: Context;
|
|
362
435
|
}
|
|
363
436
|
/**
|
|
364
437
|
* Validate expression structure
|
|
@@ -481,18 +554,60 @@ declare function $cond(left: Expression, op: ConditionOp, right?: Expression): C
|
|
|
481
554
|
* Alias for $cond (condition builder)
|
|
482
555
|
*/
|
|
483
556
|
declare const cond: typeof $cond;
|
|
557
|
+
/**
|
|
558
|
+
* Create a callback expression (HOC de continuidade).
|
|
559
|
+
*
|
|
560
|
+
* @param name - Context function name (from context)
|
|
561
|
+
* @param body - Expression to execute inside the context
|
|
562
|
+
* @param params - Optional parameters for the context function
|
|
563
|
+
* @returns CbExpr
|
|
564
|
+
*
|
|
565
|
+
* @example
|
|
566
|
+
* $cb("tryCatch", $fn("query"))
|
|
567
|
+
* // { $cb: "tryCatch", body: { $fn: "query" } }
|
|
568
|
+
*
|
|
569
|
+
* $cb("transaction", $fn("saveUser"), { isolation: "serializable" })
|
|
570
|
+
* // { $cb: "transaction", body: {...}, params: {...} }
|
|
571
|
+
*/
|
|
572
|
+
declare function $cb(name: string, body: Expression, params?: Expression): CbExpr;
|
|
573
|
+
/**
|
|
574
|
+
* Alias for $cb (callback builder)
|
|
575
|
+
*/
|
|
576
|
+
declare const cb: typeof $cb;
|
|
577
|
+
/**
|
|
578
|
+
* Create a function call expression that always calls the function.
|
|
579
|
+
* Unlike $fn which returns function reference when args is empty/undefined,
|
|
580
|
+
* $call always includes args (defaults to empty array).
|
|
581
|
+
*
|
|
582
|
+
* @param name - Function name (from scope)
|
|
583
|
+
* @param args - Arguments (can be expressions, defaults to [])
|
|
584
|
+
* @returns FnExpr with args always present
|
|
585
|
+
*
|
|
586
|
+
* @example
|
|
587
|
+
* $call("now") // { $fn: "now", args: [] } - calls function
|
|
588
|
+
* $call("add", [$("a"), 1]) // { $fn: "add", args: [...] }
|
|
589
|
+
*/
|
|
590
|
+
declare function $call(name: string, args?: Expression[]): FnExpr;
|
|
591
|
+
/**
|
|
592
|
+
* Alias for $call (call builder)
|
|
593
|
+
*/
|
|
594
|
+
declare const call: typeof $call;
|
|
484
595
|
|
|
485
596
|
declare const builders_$: typeof $;
|
|
597
|
+
declare const builders_$call: typeof $call;
|
|
598
|
+
declare const builders_$cb: typeof $cb;
|
|
486
599
|
declare const builders_$cond: typeof $cond;
|
|
487
600
|
declare const builders_$fn: typeof $fn;
|
|
488
601
|
declare const builders_$if: typeof $if;
|
|
489
602
|
declare const builders_$pipe: typeof $pipe;
|
|
603
|
+
declare const builders_call: typeof call;
|
|
604
|
+
declare const builders_cb: typeof cb;
|
|
490
605
|
declare const builders_cond: typeof cond;
|
|
491
606
|
declare const builders_fn: typeof fn;
|
|
492
607
|
declare const builders_pipe: typeof pipe;
|
|
493
608
|
declare const builders_ref: typeof ref;
|
|
494
609
|
declare namespace builders {
|
|
495
|
-
export { builders_$ as $, builders_$cond as $cond, builders_$fn as $fn, builders_$if as $if, builders_$pipe as $pipe, builders_cond as cond, builders_fn as fn, builders_pipe as pipe, builders_ref as ref };
|
|
610
|
+
export { builders_$ as $, builders_$call as $call, builders_$cb as $cb, builders_$cond as $cond, builders_$fn as $fn, builders_$if as $if, builders_$pipe as $pipe, builders_call as call, builders_cb as cb, builders_cond as cond, builders_fn as fn, builders_pipe as pipe, builders_ref as ref };
|
|
496
611
|
}
|
|
497
612
|
|
|
498
613
|
/**
|
|
@@ -590,6 +705,19 @@ declare function wrapInFunction(bodyAst: ASTNode, params?: string[]): ASTNode;
|
|
|
590
705
|
* ```
|
|
591
706
|
*/
|
|
592
707
|
declare function extractScopeFns(expr: Expression): Set<string>;
|
|
708
|
+
/**
|
|
709
|
+
* Extract all context function names used in an expression
|
|
710
|
+
*
|
|
711
|
+
* @param expr - DSL expression to analyze
|
|
712
|
+
* @returns Set of context function names used
|
|
713
|
+
*
|
|
714
|
+
* @example
|
|
715
|
+
* ```ts
|
|
716
|
+
* extractContextFns({ $cb: "tryCatch", body: { $fn: "query" } })
|
|
717
|
+
* // Set { "tryCatch" }
|
|
718
|
+
* ```
|
|
719
|
+
*/
|
|
720
|
+
declare function extractContextFns(expr: Expression): Set<string>;
|
|
593
721
|
/**
|
|
594
722
|
* Extract root-level data dependencies from paths
|
|
595
723
|
*
|
|
@@ -618,6 +746,8 @@ declare function extractDataRoots(deps: string[]): Set<string>;
|
|
|
618
746
|
interface CompileASTOptions {
|
|
619
747
|
/** Scope with functions available to the expression */
|
|
620
748
|
scope?: Scope;
|
|
749
|
+
/** Context with HOC functions available to $cb expressions */
|
|
750
|
+
context?: Context;
|
|
621
751
|
/** Return generated code instead of function (for debugging) */
|
|
622
752
|
returnCode?: boolean;
|
|
623
753
|
/**
|
|
@@ -639,6 +769,7 @@ interface CompileASTCodeResult {
|
|
|
639
769
|
hash: string;
|
|
640
770
|
dataRoots: string[];
|
|
641
771
|
scopeFns: string[];
|
|
772
|
+
contextFns: string[];
|
|
642
773
|
}
|
|
643
774
|
/**
|
|
644
775
|
* Compile DSL expression to optimized function using AST generation
|
|
@@ -746,6 +877,112 @@ type Transforms = Record<string, TransformFn>;
|
|
|
746
877
|
*/
|
|
747
878
|
declare function normalize(expr: unknown, transforms: Transforms): Expression;
|
|
748
879
|
|
|
880
|
+
/**
|
|
881
|
+
* @statedelta-libs/expressions - Boundaries
|
|
882
|
+
*
|
|
883
|
+
* Resolve custom boundaries ($simulate, $query, etc.) before compilation.
|
|
884
|
+
* Boundaries are "foreign bodies" that stop the expression flow and delegate
|
|
885
|
+
* to external handlers. The handler can compile internal slots independently.
|
|
886
|
+
*
|
|
887
|
+
* @example
|
|
888
|
+
* ```ts
|
|
889
|
+
* const { expr, scope } = resolveBoundaries(
|
|
890
|
+
* { $simulate: { effects: [...], query: {...} } },
|
|
891
|
+
* {
|
|
892
|
+
* scope: baseScope,
|
|
893
|
+
* resolvers: {
|
|
894
|
+
* $simulate: (node, { compile, genId }) => {
|
|
895
|
+
* const id = `__simulate_${genId()}`;
|
|
896
|
+
* const fn = buildSimulateFn(node, compile);
|
|
897
|
+
* return {
|
|
898
|
+
* expr: { $fn: id },
|
|
899
|
+
* scopeEntry: [id, fn]
|
|
900
|
+
* };
|
|
901
|
+
* }
|
|
902
|
+
* }
|
|
903
|
+
* }
|
|
904
|
+
* );
|
|
905
|
+
*
|
|
906
|
+
* compile(expr, { scope });
|
|
907
|
+
* ```
|
|
908
|
+
*/
|
|
909
|
+
|
|
910
|
+
/**
|
|
911
|
+
* Result returned by a boundary resolver
|
|
912
|
+
*/
|
|
913
|
+
interface ResolverResult {
|
|
914
|
+
/** Expression to replace the boundary with */
|
|
915
|
+
expr: Expression;
|
|
916
|
+
/** Optional entry to add to scope [key, value] */
|
|
917
|
+
scopeEntry?: [string, unknown];
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Context provided to boundary resolvers
|
|
921
|
+
*/
|
|
922
|
+
interface ResolverContext {
|
|
923
|
+
/** Compile function for compiling internal slots */
|
|
924
|
+
compile: typeof compile;
|
|
925
|
+
/** Generate unique ID for scope entries */
|
|
926
|
+
genId: () => string;
|
|
927
|
+
/** Current scope (read-only reference) */
|
|
928
|
+
scope: Readonly<Scope>;
|
|
929
|
+
/** Compile options passed to resolveBoundaries */
|
|
930
|
+
options: Readonly<CompileOptions>;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Boundary resolver function.
|
|
934
|
+
* Receives the raw node and context, returns replacement expression.
|
|
935
|
+
*/
|
|
936
|
+
type BoundaryResolver = (node: Record<string, unknown>, ctx: ResolverContext) => ResolverResult;
|
|
937
|
+
/**
|
|
938
|
+
* Map of boundary resolvers keyed by marker (e.g. "$simulate", "$query")
|
|
939
|
+
*/
|
|
940
|
+
type BoundaryResolvers = Record<string, BoundaryResolver>;
|
|
941
|
+
/**
|
|
942
|
+
* ID generator function
|
|
943
|
+
*/
|
|
944
|
+
type IdGenerator = () => string;
|
|
945
|
+
/**
|
|
946
|
+
* Options for resolveBoundaries
|
|
947
|
+
*/
|
|
948
|
+
interface ResolveBoundariesOptions extends CompileOptions {
|
|
949
|
+
/** Map of boundary resolvers */
|
|
950
|
+
resolvers: BoundaryResolvers;
|
|
951
|
+
/** Custom ID generator. Default: simple counter ("0", "1", "2"...) */
|
|
952
|
+
genId?: IdGenerator;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Result of resolveBoundaries
|
|
956
|
+
*/
|
|
957
|
+
interface ResolveBoundariesResult {
|
|
958
|
+
/** Pure expression with boundaries replaced */
|
|
959
|
+
expr: Expression;
|
|
960
|
+
/** Enriched scope with boundary handlers */
|
|
961
|
+
scope: Scope;
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Resolve boundaries in an expression tree.
|
|
965
|
+
*
|
|
966
|
+
* Boundaries are custom DSL nodes ($simulate, $query, etc.) that stop the
|
|
967
|
+
* normal expression compilation flow. Each boundary is extracted, processed
|
|
968
|
+
* by its resolver, and replaced with a standard expression.
|
|
969
|
+
*
|
|
970
|
+
* The resolver receives:
|
|
971
|
+
* - `node`: The raw boundary object (e.g. { $simulate: {...}, effects: [...] })
|
|
972
|
+
* - `ctx.compile`: Compile function for internal slots
|
|
973
|
+
* - `ctx.genId`: Unique ID generator
|
|
974
|
+
* - `ctx.scope`: Current scope (read-only)
|
|
975
|
+
*
|
|
976
|
+
* The resolver returns:
|
|
977
|
+
* - `expr`: Replacement expression (typically { $fn: "__id" })
|
|
978
|
+
* - `scopeEntry`: Optional [key, fn] to add to scope
|
|
979
|
+
*
|
|
980
|
+
* @param expr - Expression (possibly with boundaries)
|
|
981
|
+
* @param options - Resolvers, scope, and compile options
|
|
982
|
+
* @returns Pure expression and enriched scope
|
|
983
|
+
*/
|
|
984
|
+
declare function resolveBoundaries(expr: unknown, options: ResolveBoundariesOptions): ResolveBoundariesResult;
|
|
985
|
+
|
|
749
986
|
/**
|
|
750
987
|
* @statedelta-libs/expressions
|
|
751
988
|
*
|
|
@@ -781,4 +1018,4 @@ declare function normalize(expr: unknown, transforms: Transforms): Expression;
|
|
|
781
1018
|
*/
|
|
782
1019
|
declare const VERSION = "2.0.0";
|
|
783
1020
|
|
|
784
|
-
export { type AccessorFn, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type Expression, ExpressionCache, type FnExpr, type Literal, type PathGetter, type PipeExpr, type RefExpr, type Scope, type TransformFn, type TransformOptions, type Transforms, VERSION, type ValidateOptions, type ValidationResult, assertValid, builders, cache, cached, clearPathCache, compile, compileAST, compilePath, dslToAST, evaluate, evaluateAST, extractDataRoots, extractDeps, extractScopeFns, get, getPathCacheSize, hasDeps, hasWildcard, isCondition, isConditionExpr, isConditionGroup, isConditional, isFn, isLiteral, isPipe, isPure, isRef, isValid, normalize, normalizePath, validate, wrapInFunction };
|
|
1021
|
+
export { type AccessorFn, type BoundaryResolver, type BoundaryResolvers, type CbExpr, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type Context, type ContextFn, type Expression, ExpressionCache, type FnExpr, type IdGenerator, type Literal, type PathGetter, type PathGetterFn, type PipeExpr, type RefExpr, type ResolveBoundariesOptions, type ResolveBoundariesResult, type ResolverContext, type ResolverResult, type Scope, type TransformFn, type TransformOptions, type Transforms, VERSION, type ValidateOptions, type ValidationResult, assertValid, builders, cache, cached, clearPathCache, compile, compileAST, compilePath, dslToAST, evaluate, evaluateAST, extractContextFns, extractDataRoots, extractDeps, extractScopeFns, get, getPathCacheSize, hasDeps, hasWildcard, isCb, isCondition, isConditionExpr, isConditionGroup, isConditional, isFn, isLiteral, isPipe, isPure, isRef, isValid, normalize, normalizePath, resolveBoundaries, validate, wrapInFunction };
|
package/dist/index.d.ts
CHANGED
|
@@ -44,6 +44,17 @@ interface FnExpr {
|
|
|
44
44
|
interface PipeExpr {
|
|
45
45
|
$pipe: Expression[];
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Callback expression - HOC de continuidade
|
|
49
|
+
* Executa body dentro de um context function (tryCatch, transaction, etc.)
|
|
50
|
+
* @example { $cb: "tryCatch", body: { $fn: "query" } }
|
|
51
|
+
* @example { $cb: "transaction", params: { isolation: "serializable" }, body: { $fn: "query" } }
|
|
52
|
+
*/
|
|
53
|
+
interface CbExpr {
|
|
54
|
+
$cb: string;
|
|
55
|
+
body: Expression;
|
|
56
|
+
params?: Expression;
|
|
57
|
+
}
|
|
47
58
|
/**
|
|
48
59
|
* Literal values (primitives, arrays, plain objects)
|
|
49
60
|
*/
|
|
@@ -75,7 +86,7 @@ type ConditionExpr = Condition | ConditionGroup;
|
|
|
75
86
|
/**
|
|
76
87
|
* Union of all expression types
|
|
77
88
|
*/
|
|
78
|
-
type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | ConditionExpr;
|
|
89
|
+
type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | CbExpr | ConditionExpr;
|
|
79
90
|
/**
|
|
80
91
|
* Compiled expression function
|
|
81
92
|
*/
|
|
@@ -122,6 +133,50 @@ interface ValidationResult {
|
|
|
122
133
|
* @example { add, subtract, multiply, filter, map, sum }
|
|
123
134
|
*/
|
|
124
135
|
type Scope = Record<string, (...args: any[]) => any>;
|
|
136
|
+
/**
|
|
137
|
+
* Path getter function for context callbacks
|
|
138
|
+
*/
|
|
139
|
+
type PathGetterFn = (path: string) => unknown;
|
|
140
|
+
/**
|
|
141
|
+
* Context function - HOC que controla execução do body.
|
|
142
|
+
* Recebe o body como callback e decide quando/se executá-lo.
|
|
143
|
+
*
|
|
144
|
+
* @param cb - Body compilado como callback (recebe data e get)
|
|
145
|
+
* @param data - Dados do runtime
|
|
146
|
+
* @param get - Resolver de paths (accessor)
|
|
147
|
+
* @param params - Parâmetros extras para o context (opcional)
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* ```ts
|
|
151
|
+
* const tryCatch: ContextFn = (cb, data, get, params) => {
|
|
152
|
+
* try {
|
|
153
|
+
* return cb(data, get);
|
|
154
|
+
* } catch (e) {
|
|
155
|
+
* return params?.fallback ?? null;
|
|
156
|
+
* }
|
|
157
|
+
* };
|
|
158
|
+
*
|
|
159
|
+
* const transaction: ContextFn = (cb, data, get, params) => {
|
|
160
|
+
* const tx = db.beginTransaction(params);
|
|
161
|
+
* try {
|
|
162
|
+
* const result = cb({ ...data, tx }, get);
|
|
163
|
+
* tx.commit();
|
|
164
|
+
* return result;
|
|
165
|
+
* } catch (e) {
|
|
166
|
+
* tx.rollback();
|
|
167
|
+
* throw e;
|
|
168
|
+
* }
|
|
169
|
+
* };
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
type ContextFn<T = any, R = any> = (cb: (data: T, get: PathGetterFn) => R, data: T, get: PathGetterFn, params?: unknown) => R;
|
|
173
|
+
/**
|
|
174
|
+
* Context registry - HOC functions available to $cb expressions.
|
|
175
|
+
* Separate from scope because context functions have different signature.
|
|
176
|
+
*
|
|
177
|
+
* @example { tryCatch, transaction, withRetry }
|
|
178
|
+
*/
|
|
179
|
+
type Context = Record<string, ContextFn>;
|
|
125
180
|
/**
|
|
126
181
|
* Options for compilation
|
|
127
182
|
*/
|
|
@@ -137,6 +192,18 @@ interface CompileOptions<T = unknown> {
|
|
|
137
192
|
* compile(expr, { accessor: (path, ctx) => ctx.get(path) })
|
|
138
193
|
*/
|
|
139
194
|
accessor?: AccessorFn<T>;
|
|
195
|
+
/**
|
|
196
|
+
* Context functions available to $cb expressions.
|
|
197
|
+
* HOC functions that control body execution (tryCatch, transaction, etc.).
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* compile(expr, {
|
|
201
|
+
* context: {
|
|
202
|
+
* tryCatch: (cb, data, get) => { try { return cb(data, get); } catch { return null; } }
|
|
203
|
+
* }
|
|
204
|
+
* })
|
|
205
|
+
*/
|
|
206
|
+
context?: Context;
|
|
140
207
|
}
|
|
141
208
|
/**
|
|
142
209
|
* Check if value is a reference expression
|
|
@@ -154,6 +221,10 @@ declare const isFn: (v: unknown) => v is FnExpr;
|
|
|
154
221
|
* Check if value is a pipe expression
|
|
155
222
|
*/
|
|
156
223
|
declare const isPipe: (v: unknown) => v is PipeExpr;
|
|
224
|
+
/**
|
|
225
|
+
* Check if value is a callback expression
|
|
226
|
+
*/
|
|
227
|
+
declare const isCb: (v: unknown) => v is CbExpr;
|
|
157
228
|
/**
|
|
158
229
|
* Check if value is a condition expression
|
|
159
230
|
*
|
|
@@ -359,6 +430,8 @@ declare function cached<T = unknown, R = unknown>(expr: Expression, options?: Co
|
|
|
359
430
|
interface ValidateOptions {
|
|
360
431
|
/** Scope to validate function names against (optional) */
|
|
361
432
|
scope?: Scope;
|
|
433
|
+
/** Context to validate $cb function names against (optional) */
|
|
434
|
+
context?: Context;
|
|
362
435
|
}
|
|
363
436
|
/**
|
|
364
437
|
* Validate expression structure
|
|
@@ -481,18 +554,60 @@ declare function $cond(left: Expression, op: ConditionOp, right?: Expression): C
|
|
|
481
554
|
* Alias for $cond (condition builder)
|
|
482
555
|
*/
|
|
483
556
|
declare const cond: typeof $cond;
|
|
557
|
+
/**
|
|
558
|
+
* Create a callback expression (HOC de continuidade).
|
|
559
|
+
*
|
|
560
|
+
* @param name - Context function name (from context)
|
|
561
|
+
* @param body - Expression to execute inside the context
|
|
562
|
+
* @param params - Optional parameters for the context function
|
|
563
|
+
* @returns CbExpr
|
|
564
|
+
*
|
|
565
|
+
* @example
|
|
566
|
+
* $cb("tryCatch", $fn("query"))
|
|
567
|
+
* // { $cb: "tryCatch", body: { $fn: "query" } }
|
|
568
|
+
*
|
|
569
|
+
* $cb("transaction", $fn("saveUser"), { isolation: "serializable" })
|
|
570
|
+
* // { $cb: "transaction", body: {...}, params: {...} }
|
|
571
|
+
*/
|
|
572
|
+
declare function $cb(name: string, body: Expression, params?: Expression): CbExpr;
|
|
573
|
+
/**
|
|
574
|
+
* Alias for $cb (callback builder)
|
|
575
|
+
*/
|
|
576
|
+
declare const cb: typeof $cb;
|
|
577
|
+
/**
|
|
578
|
+
* Create a function call expression that always calls the function.
|
|
579
|
+
* Unlike $fn which returns function reference when args is empty/undefined,
|
|
580
|
+
* $call always includes args (defaults to empty array).
|
|
581
|
+
*
|
|
582
|
+
* @param name - Function name (from scope)
|
|
583
|
+
* @param args - Arguments (can be expressions, defaults to [])
|
|
584
|
+
* @returns FnExpr with args always present
|
|
585
|
+
*
|
|
586
|
+
* @example
|
|
587
|
+
* $call("now") // { $fn: "now", args: [] } - calls function
|
|
588
|
+
* $call("add", [$("a"), 1]) // { $fn: "add", args: [...] }
|
|
589
|
+
*/
|
|
590
|
+
declare function $call(name: string, args?: Expression[]): FnExpr;
|
|
591
|
+
/**
|
|
592
|
+
* Alias for $call (call builder)
|
|
593
|
+
*/
|
|
594
|
+
declare const call: typeof $call;
|
|
484
595
|
|
|
485
596
|
declare const builders_$: typeof $;
|
|
597
|
+
declare const builders_$call: typeof $call;
|
|
598
|
+
declare const builders_$cb: typeof $cb;
|
|
486
599
|
declare const builders_$cond: typeof $cond;
|
|
487
600
|
declare const builders_$fn: typeof $fn;
|
|
488
601
|
declare const builders_$if: typeof $if;
|
|
489
602
|
declare const builders_$pipe: typeof $pipe;
|
|
603
|
+
declare const builders_call: typeof call;
|
|
604
|
+
declare const builders_cb: typeof cb;
|
|
490
605
|
declare const builders_cond: typeof cond;
|
|
491
606
|
declare const builders_fn: typeof fn;
|
|
492
607
|
declare const builders_pipe: typeof pipe;
|
|
493
608
|
declare const builders_ref: typeof ref;
|
|
494
609
|
declare namespace builders {
|
|
495
|
-
export { builders_$ as $, builders_$cond as $cond, builders_$fn as $fn, builders_$if as $if, builders_$pipe as $pipe, builders_cond as cond, builders_fn as fn, builders_pipe as pipe, builders_ref as ref };
|
|
610
|
+
export { builders_$ as $, builders_$call as $call, builders_$cb as $cb, builders_$cond as $cond, builders_$fn as $fn, builders_$if as $if, builders_$pipe as $pipe, builders_call as call, builders_cb as cb, builders_cond as cond, builders_fn as fn, builders_pipe as pipe, builders_ref as ref };
|
|
496
611
|
}
|
|
497
612
|
|
|
498
613
|
/**
|
|
@@ -590,6 +705,19 @@ declare function wrapInFunction(bodyAst: ASTNode, params?: string[]): ASTNode;
|
|
|
590
705
|
* ```
|
|
591
706
|
*/
|
|
592
707
|
declare function extractScopeFns(expr: Expression): Set<string>;
|
|
708
|
+
/**
|
|
709
|
+
* Extract all context function names used in an expression
|
|
710
|
+
*
|
|
711
|
+
* @param expr - DSL expression to analyze
|
|
712
|
+
* @returns Set of context function names used
|
|
713
|
+
*
|
|
714
|
+
* @example
|
|
715
|
+
* ```ts
|
|
716
|
+
* extractContextFns({ $cb: "tryCatch", body: { $fn: "query" } })
|
|
717
|
+
* // Set { "tryCatch" }
|
|
718
|
+
* ```
|
|
719
|
+
*/
|
|
720
|
+
declare function extractContextFns(expr: Expression): Set<string>;
|
|
593
721
|
/**
|
|
594
722
|
* Extract root-level data dependencies from paths
|
|
595
723
|
*
|
|
@@ -618,6 +746,8 @@ declare function extractDataRoots(deps: string[]): Set<string>;
|
|
|
618
746
|
interface CompileASTOptions {
|
|
619
747
|
/** Scope with functions available to the expression */
|
|
620
748
|
scope?: Scope;
|
|
749
|
+
/** Context with HOC functions available to $cb expressions */
|
|
750
|
+
context?: Context;
|
|
621
751
|
/** Return generated code instead of function (for debugging) */
|
|
622
752
|
returnCode?: boolean;
|
|
623
753
|
/**
|
|
@@ -639,6 +769,7 @@ interface CompileASTCodeResult {
|
|
|
639
769
|
hash: string;
|
|
640
770
|
dataRoots: string[];
|
|
641
771
|
scopeFns: string[];
|
|
772
|
+
contextFns: string[];
|
|
642
773
|
}
|
|
643
774
|
/**
|
|
644
775
|
* Compile DSL expression to optimized function using AST generation
|
|
@@ -746,6 +877,112 @@ type Transforms = Record<string, TransformFn>;
|
|
|
746
877
|
*/
|
|
747
878
|
declare function normalize(expr: unknown, transforms: Transforms): Expression;
|
|
748
879
|
|
|
880
|
+
/**
|
|
881
|
+
* @statedelta-libs/expressions - Boundaries
|
|
882
|
+
*
|
|
883
|
+
* Resolve custom boundaries ($simulate, $query, etc.) before compilation.
|
|
884
|
+
* Boundaries are "foreign bodies" that stop the expression flow and delegate
|
|
885
|
+
* to external handlers. The handler can compile internal slots independently.
|
|
886
|
+
*
|
|
887
|
+
* @example
|
|
888
|
+
* ```ts
|
|
889
|
+
* const { expr, scope } = resolveBoundaries(
|
|
890
|
+
* { $simulate: { effects: [...], query: {...} } },
|
|
891
|
+
* {
|
|
892
|
+
* scope: baseScope,
|
|
893
|
+
* resolvers: {
|
|
894
|
+
* $simulate: (node, { compile, genId }) => {
|
|
895
|
+
* const id = `__simulate_${genId()}`;
|
|
896
|
+
* const fn = buildSimulateFn(node, compile);
|
|
897
|
+
* return {
|
|
898
|
+
* expr: { $fn: id },
|
|
899
|
+
* scopeEntry: [id, fn]
|
|
900
|
+
* };
|
|
901
|
+
* }
|
|
902
|
+
* }
|
|
903
|
+
* }
|
|
904
|
+
* );
|
|
905
|
+
*
|
|
906
|
+
* compile(expr, { scope });
|
|
907
|
+
* ```
|
|
908
|
+
*/
|
|
909
|
+
|
|
910
|
+
/**
|
|
911
|
+
* Result returned by a boundary resolver
|
|
912
|
+
*/
|
|
913
|
+
interface ResolverResult {
|
|
914
|
+
/** Expression to replace the boundary with */
|
|
915
|
+
expr: Expression;
|
|
916
|
+
/** Optional entry to add to scope [key, value] */
|
|
917
|
+
scopeEntry?: [string, unknown];
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Context provided to boundary resolvers
|
|
921
|
+
*/
|
|
922
|
+
interface ResolverContext {
|
|
923
|
+
/** Compile function for compiling internal slots */
|
|
924
|
+
compile: typeof compile;
|
|
925
|
+
/** Generate unique ID for scope entries */
|
|
926
|
+
genId: () => string;
|
|
927
|
+
/** Current scope (read-only reference) */
|
|
928
|
+
scope: Readonly<Scope>;
|
|
929
|
+
/** Compile options passed to resolveBoundaries */
|
|
930
|
+
options: Readonly<CompileOptions>;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Boundary resolver function.
|
|
934
|
+
* Receives the raw node and context, returns replacement expression.
|
|
935
|
+
*/
|
|
936
|
+
type BoundaryResolver = (node: Record<string, unknown>, ctx: ResolverContext) => ResolverResult;
|
|
937
|
+
/**
|
|
938
|
+
* Map of boundary resolvers keyed by marker (e.g. "$simulate", "$query")
|
|
939
|
+
*/
|
|
940
|
+
type BoundaryResolvers = Record<string, BoundaryResolver>;
|
|
941
|
+
/**
|
|
942
|
+
* ID generator function
|
|
943
|
+
*/
|
|
944
|
+
type IdGenerator = () => string;
|
|
945
|
+
/**
|
|
946
|
+
* Options for resolveBoundaries
|
|
947
|
+
*/
|
|
948
|
+
interface ResolveBoundariesOptions extends CompileOptions {
|
|
949
|
+
/** Map of boundary resolvers */
|
|
950
|
+
resolvers: BoundaryResolvers;
|
|
951
|
+
/** Custom ID generator. Default: simple counter ("0", "1", "2"...) */
|
|
952
|
+
genId?: IdGenerator;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Result of resolveBoundaries
|
|
956
|
+
*/
|
|
957
|
+
interface ResolveBoundariesResult {
|
|
958
|
+
/** Pure expression with boundaries replaced */
|
|
959
|
+
expr: Expression;
|
|
960
|
+
/** Enriched scope with boundary handlers */
|
|
961
|
+
scope: Scope;
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Resolve boundaries in an expression tree.
|
|
965
|
+
*
|
|
966
|
+
* Boundaries are custom DSL nodes ($simulate, $query, etc.) that stop the
|
|
967
|
+
* normal expression compilation flow. Each boundary is extracted, processed
|
|
968
|
+
* by its resolver, and replaced with a standard expression.
|
|
969
|
+
*
|
|
970
|
+
* The resolver receives:
|
|
971
|
+
* - `node`: The raw boundary object (e.g. { $simulate: {...}, effects: [...] })
|
|
972
|
+
* - `ctx.compile`: Compile function for internal slots
|
|
973
|
+
* - `ctx.genId`: Unique ID generator
|
|
974
|
+
* - `ctx.scope`: Current scope (read-only)
|
|
975
|
+
*
|
|
976
|
+
* The resolver returns:
|
|
977
|
+
* - `expr`: Replacement expression (typically { $fn: "__id" })
|
|
978
|
+
* - `scopeEntry`: Optional [key, fn] to add to scope
|
|
979
|
+
*
|
|
980
|
+
* @param expr - Expression (possibly with boundaries)
|
|
981
|
+
* @param options - Resolvers, scope, and compile options
|
|
982
|
+
* @returns Pure expression and enriched scope
|
|
983
|
+
*/
|
|
984
|
+
declare function resolveBoundaries(expr: unknown, options: ResolveBoundariesOptions): ResolveBoundariesResult;
|
|
985
|
+
|
|
749
986
|
/**
|
|
750
987
|
* @statedelta-libs/expressions
|
|
751
988
|
*
|
|
@@ -781,4 +1018,4 @@ declare function normalize(expr: unknown, transforms: Transforms): Expression;
|
|
|
781
1018
|
*/
|
|
782
1019
|
declare const VERSION = "2.0.0";
|
|
783
1020
|
|
|
784
|
-
export { type AccessorFn, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type Expression, ExpressionCache, type FnExpr, type Literal, type PathGetter, type PipeExpr, type RefExpr, type Scope, type TransformFn, type TransformOptions, type Transforms, VERSION, type ValidateOptions, type ValidationResult, assertValid, builders, cache, cached, clearPathCache, compile, compileAST, compilePath, dslToAST, evaluate, evaluateAST, extractDataRoots, extractDeps, extractScopeFns, get, getPathCacheSize, hasDeps, hasWildcard, isCondition, isConditionExpr, isConditionGroup, isConditional, isFn, isLiteral, isPipe, isPure, isRef, isValid, normalize, normalizePath, validate, wrapInFunction };
|
|
1021
|
+
export { type AccessorFn, type BoundaryResolver, type BoundaryResolvers, type CbExpr, type CompileASTCodeResult, type CompileASTOptions, type CompileOptions, type CompiledExpression, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type Context, type ContextFn, type Expression, ExpressionCache, type FnExpr, type IdGenerator, type Literal, type PathGetter, type PathGetterFn, type PipeExpr, type RefExpr, type ResolveBoundariesOptions, type ResolveBoundariesResult, type ResolverContext, type ResolverResult, type Scope, type TransformFn, type TransformOptions, type Transforms, VERSION, type ValidateOptions, type ValidationResult, assertValid, builders, cache, cached, clearPathCache, compile, compileAST, compilePath, dslToAST, evaluate, evaluateAST, extractContextFns, extractDataRoots, extractDeps, extractScopeFns, get, getPathCacheSize, hasDeps, hasWildcard, isCb, isCondition, isConditionExpr, isConditionGroup, isConditional, isFn, isLiteral, isPipe, isPure, isRef, isValid, normalize, normalizePath, resolveBoundaries, validate, wrapInFunction };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {builders,generate}from'omni-ast';var rn=Object.defineProperty;var sn=(n,t)=>{for(var s in t)rn(n,s,{get:t[s],enumerable:true});};var y=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,T=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,b=n=>n!==null&&typeof n=="object"&&"$fn"in n&&typeof n.$fn=="string",C=n=>n!==null&&typeof n=="object"&&"$pipe"in n&&Array.isArray(n.$pipe),x=new Set(["eq","neq","gt","gte","lt","lte","in","notIn","contains","notContains","exists","notExists","matches","notMatches","startsWith","endsWith"]),E=n=>n!==null&&typeof n=="object"&&"left"in n&&"op"in n&&x.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),h=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,fn=n=>E(n)||h(n),I=n=>{if(n===null)return true;let t=typeof n;if(t==="string"||t==="number"||t==="boolean"||Array.isArray(n))return true;if(t==="object"&&n!==null){let s=n,i="left"in s&&"op"in s&&x.has(s.op);return !("$"in s)&&!("$if"in s)&&!("$fn"in s)&&!("$pipe"in s)&&!i&&!("logic"in s)}return false};var R=new Map;function J(n){let t=[],s=n.length,i=0,r="";for(;i<s;){let o=n[i];if(o===".")r&&(t.push({type:"key",value:r}),r=""),i++;else if(o==="["){r&&(t.push({type:"key",value:r}),r=""),i++;let e=i;for(;i<s&&n[i]!=="]";)i++;let f=n.slice(e,i);if(i++,f==="*")t.push({type:"wildcard",value:"*"});else {let l=parseInt(f,10);t.push({type:"index",value:isNaN(l)?f:l});}}else r+=o,i++;}return r&&t.push({type:"key",value:r}),t}function B(n){return n.includes("[*]")}function O(n){let t=R.get(n);return t||(t=B(n)?ln(n):un(n),R.set(n,t),t)}function un(n){if(!n.includes(".")&&!n.includes("["))return r=>r?.[n];let t=J(n),s=t.length;if(s===2){let[r,o]=t,e=r.value,f=o.value;return l=>l?.[e]?.[f]}if(s===3){let[r,o,e]=t,f=r.value,l=o.value,c=e.value;return a=>a?.[f]?.[l]?.[c]}let i=t.map(r=>r.value);return r=>{let o=r;for(let e=0;e<s&&o!=null;e++)o=o[i[e]];return o}}function ln(n){let t=J(n),s=[];for(let i=0;i<t.length;i++)t[i].type==="wildcard"&&s.push(i);return s.length===1?cn(t,s[0]):an(t,s)}function cn(n,t){let s=n.slice(0,t).map(e=>e.value),i=n.slice(t+1).map(e=>e.value),r=s.length,o=i.length;if(o===0){if(r===1){let e=s[0];return f=>f?.[e]}return e=>{let f=e;for(let l=0;l<r&&f!=null;l++)f=f[s[l]];return f}}if(o===1){let e=i[0];if(r===1){let f=s[0];return l=>{let c=l?.[f];if(Array.isArray(c))return c.map(a=>a?.[e])}}return f=>{let l=f;for(let c=0;c<r&&l!=null;c++)l=l[s[c]];if(Array.isArray(l))return l.map(c=>c?.[e])}}return e=>{let f=e;for(let l=0;l<r&&f!=null;l++)f=f[s[l]];if(Array.isArray(f))return f.map(l=>{let c=l;for(let a=0;a<o&&c!=null;a++)c=c[i[a]];return c})}}function an(n,t){let s=[],i=0;for(let o=0;o<t.length;o++){let e=t[o],f=o===t.length-1,l=n.slice(i,e).map(c=>c.value);l.length>0&&s.push({type:"access",keys:l}),s.push({type:f?"map":"flatMap",keys:[]}),i=e+1;}let r=n.slice(i).map(o=>o.value);return o=>{let e=o;for(let f of s){if(e==null)return;if(f.type==="access")for(let l of f.keys){if(e==null)return;e=e[l];}else if(f.type==="flatMap"){if(!Array.isArray(e))return;e=e.flatMap(l=>{let c=l;return Array.isArray(c)?c:[c]});}else if(f.type==="map"){if(!Array.isArray(e))return;r.length>0&&(e=e.map(l=>{let c=l;for(let a of r){if(c==null)return;c=c[a];}return c}));}}return e}}function pn(n,t){return O(t)(n)}function F(n){let t=n.indexOf("[*]");return t===-1?n:n.slice(0,t)}function dn(){R.clear();}function gn(){return R.size}function w(n){let t=new Set;return A(n,t),Array.from(t)}function A(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r=0;r<n.length;r++)A(n[r],t);return}if(y(n)){t.add(F(n.$));return}if(T(n)){if(typeof n.$if=="string"){let r=n.$if.startsWith("!")?n.$if.slice(1):n.$if;t.add(F(r));}else A(n.$if,t);A(n.then,t),n.else!==void 0&&A(n.else,t);return}if(C(n)){for(let r=0;r<n.$pipe.length;r++)A(n.$pipe[r],t);return}if(b(n)){if(n.args)for(let r=0;r<n.args.length;r++)A(n.args[r],t);return}if(E(n)){A(n.left,t),n.right!==void 0&&A(n.right,t);return}if(h(n)){for(let r=0;r<n.conditions.length;r++)A(n.conditions[r],t);return}let s=n,i=Object.keys(s);for(let r=0;r<i.length;r++)A(s[i[r]],t);}function mn(n){return w(n).length>0}function yn(n){return w(n).length===0}function En(n){return JSON.stringify(n)}function N(n,t={}){let s=t.scope??{},i=t.accessor,r=m(n,s,i),o=w(n),e=En(n);return {fn:r,deps:o,hash:e}}function m(n,t,s){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let i=n.map(r=>m(r,t,s));return r=>i.map(o=>o(r))}if(y(n))return hn(n,s);if(T(n))return Tn(n,t,s);if(C(n))return bn(n,t,s);if(b(n))return Cn(n,t,s);if(E(n))return An(n,t,s);if(h(n))return $n(n,t,s);if(I(n)){let i=n,r=Object.keys(i),o=r.map(e=>m(i[e],t,s));return e=>{let f={};for(let l=0;l<r.length;l++)f[r[l]]=o[l](e);return f}}return ()=>n}function K(n,t){return t?s=>t(n,s):O(n)}function hn(n,t){return K(n.$,t)}function Tn(n,t,s){let i;if(typeof n.$if=="string"){let e=n.$if.startsWith("!")?n.$if.slice(1):n.$if,f=K(e,s);i=n.$if.startsWith("!")?c=>!f(c):c=>!!f(c);}else {let e=m(n.$if,t,s);i=f=>!!e(f);}let r=m(n.then,t,s),o=n.else!==void 0?m(n.else,t,s):()=>{};return e=>i(e)?r(e):o(e)}function bn(n,t,s){let i=n.$pipe;if(i.length===0)return ()=>{};if(i.length===1)return m(i[0],t,s);let r=m(i[0],t,s),o=i.slice(1).map(f=>m(f,t,s)),e=o.length;if(e===1){let[f]=o;return l=>{let c=r(l),a=f(l);return typeof a=="function"?a(c):a}}if(e===2){let[f,l]=o;return c=>{let a=r(c),p=f(c);return a=typeof p=="function"?p(a):p,p=l(c),typeof p=="function"?p(a):p}}if(e===3){let[f,l,c]=o;return a=>{let p=r(a),d=f(a);return p=typeof d=="function"?d(p):d,d=l(a),p=typeof d=="function"?d(p):d,d=c(a),typeof d=="function"?d(p):d}}return f=>{let l=r(f);for(let c=0;c<e;c++){let a=o[c](f);l=typeof a=="function"?a(l):a;}return l}}function Cn(n,t,s){let i=n.$fn,r=n.args;if(r===void 0)return ()=>{let f=t[i];if(!f)throw new Error(`Function not found in scope: ${i}`);return f};let o=r.map(f=>m(f,t,s)),e=o.length;if(e===0)return f=>{let l=t[i];if(!l)throw new Error(`Function not found in scope: ${i}`);return l()};if(e===1){let[f]=o;return l=>{let c=t[i];if(!c)throw new Error(`Function not found in scope: ${i}`);return c(f(l))}}if(e===2){let[f,l]=o;return c=>{let a=t[i];if(!a)throw new Error(`Function not found in scope: ${i}`);return a(f(c),l(c))}}if(e===3){let[f,l,c]=o;return a=>{let p=t[i];if(!p)throw new Error(`Function not found in scope: ${i}`);return p(f(a),l(a),c(a))}}return f=>{let l=t[i];if(!l)throw new Error(`Function not found in scope: ${i}`);return l(...o.map(c=>c(f)))}}function An(n,t,s){let i=m(n.left,t,s),r=n.right!==void 0?m(n.right,t,s):()=>{};switch(n.op){case "eq":return o=>i(o)===r(o);case "neq":return o=>i(o)!==r(o);case "gt":return o=>i(o)>r(o);case "gte":return o=>i(o)>=r(o);case "lt":return o=>i(o)<r(o);case "lte":return o=>i(o)<=r(o);case "in":return o=>{let e=r(o);return Array.isArray(e)&&e.includes(i(o))};case "notIn":return o=>{let e=r(o);return !Array.isArray(e)||!e.includes(i(o))};case "contains":return o=>{let e=i(o);return Array.isArray(e)&&e.includes(r(o))};case "notContains":return o=>{let e=i(o);return !Array.isArray(e)||!e.includes(r(o))};case "exists":return o=>i(o)!==void 0;case "notExists":return o=>i(o)===void 0;case "matches":return o=>{let e=i(o),f=r(o);return typeof e!="string"||typeof f!="string"?false:new RegExp(f).test(e)};case "notMatches":return o=>{let e=i(o),f=r(o);return typeof e!="string"||typeof f!="string"?true:!new RegExp(f).test(e)};case "startsWith":return o=>{let e=i(o),f=r(o);return typeof e=="string"&&typeof f=="string"&&e.startsWith(f)};case "endsWith":return o=>{let e=i(o),f=r(o);return typeof e=="string"&&typeof f=="string"&&e.endsWith(f)}}}function $n(n,t,s){let i=n.conditions.map(o=>m(o,t,s)),r=i.length;if(r===1)return o=>!!i[0](o);if(r===2){let[o,e]=i;return n.logic==="AND"?f=>!!o(f)&&!!e(f):f=>!!o(f)||!!e(f)}if(r===3){let[o,e,f]=i;return n.logic==="AND"?l=>!!o(l)&&!!e(l)&&!!f(l):l=>!!o(l)||!!e(l)||!!f(l)}return n.logic==="AND"?o=>{for(let e=0;e<r;e++)if(!i[e](o))return false;return true}:o=>{for(let e=0;e<r;e++)if(i[e](o))return true;return false}}function Sn(n,t,s={}){return N(n,s).fn(t)}var j=class{constructor(t=1e3){this.cache=new Map,this._maxSize=t;}get(t,s={}){let i=JSON.stringify(t),r=this.cache.get(i);if(r)return this.cache.delete(i),this.cache.set(i,r),r;let o=N(t,s);if(this.cache.size>=this._maxSize){let e=this.cache.keys().next().value;e&&this.cache.delete(e);}return this.cache.set(i,o),o}has(t){return this.cache.has(JSON.stringify(t))}delete(t){return this.cache.delete(JSON.stringify(t))}clear(){this.cache.clear();}get size(){return this.cache.size}get maxSize(){return this._maxSize}set maxSize(t){for(this._maxSize=t;this.cache.size>this._maxSize;){let s=this.cache.keys().next().value;s&&this.cache.delete(s);}}},P=new j;function wn(n,t={}){return P.get(n,t)}function M(n,t="root",s={}){let i=[];return $(n,t,i,s),{valid:i.length===0,errors:i}}function $(n,t,s,i){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let e=0;e<n.length;e++)$(n[e],`${t}[${e}]`,s,i);return}if(y(n)){(!n.$||typeof n.$!="string")&&s.push(`${t}: invalid reference, $ must be non-empty string`);return}if(T(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||s.push(`${t}.$if: empty path in string shorthand`):$(n.$if,`${t}.$if`,s,i),$(n.then,`${t}.then`,s,i),n.else!==void 0&&$(n.else,`${t}.else`,s,i);return}if(C(n)){if(!Array.isArray(n.$pipe)){s.push(`${t}.$pipe: must be an array`);return}if(n.$pipe.length===0){s.push(`${t}.$pipe: must have at least one element`);return}for(let e=0;e<n.$pipe.length;e++)$(n.$pipe[e],`${t}.$pipe[${e}]`,s,i);return}if(b(n)){if(!n.$fn||typeof n.$fn!="string"){s.push(`${t}: invalid function, $fn must be non-empty string`);return}if(i.scope&&!(n.$fn in i.scope)&&s.push(`${t}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))s.push(`${t}.args: must be an array`);else for(let e=0;e<n.args.length;e++)$(n.args[e],`${t}.args[${e}]`,s,i);return}if(E(n)){x.has(n.op)||s.push(`${t}: invalid operator "${n.op}"`),$(n.left,`${t}.left`,s,i),n.right!==void 0&&$(n.right,`${t}.right`,s,i);return}if(h(n)){if(n.logic!=="AND"&&n.logic!=="OR"&&s.push(`${t}: invalid logic "${n.logic}", must be "AND" or "OR"`),!Array.isArray(n.conditions)){s.push(`${t}.conditions: must be an array`);return}for(let e=0;e<n.conditions.length;e++)$(n.conditions[e],`${t}.conditions[${e}]`,s,i);return}let r=n,o=Object.keys(r);for(let e=0;e<o.length;e++){let f=o[e];$(r[f],`${t}.${f}`,s,i);}}function kn(n,t={}){let s=M(n,"root",t);if(!s.valid)throw new Error(`Invalid expression: ${s.errors.join("; ")}`)}function xn(n,t={}){return M(n,"root",t).valid}var X={};sn(X,{$:()=>Y,$cond:()=>U,$fn:()=>H,$if:()=>Fn,$pipe:()=>Q,cond:()=>jn,fn:()=>On,pipe:()=>Nn,ref:()=>Rn});function Y(n){return {$:n}}var Rn=Y;function H(n,t){return t===void 0||t.length===0?{$fn:n}:{$fn:n,args:t}}var On=H;function Fn(n,t,s){return s===void 0?{$if:n,then:t}:{$if:n,then:t,else:s}}function Q(...n){return {$pipe:n}}var Nn=Q;function U(n,t,s){return s===void 0?{left:n,op:t}:{left:n,op:t,right:s}}var jn=U;var V="data",nn="scope",vn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function G(n,t={}){let{dataParam:s=V,scopeParam:i=nn,noPrefixes:r=false,useAccessor:o=false,lexicalPrefix:e}=t;return g(n,s,i,r,o,e)}function g(n,t,s,i,r,o){if(n===null)return builders.literal(null);if(typeof n=="string")return builders.literal(n);if(typeof n=="number")return builders.literal(n);if(typeof n=="boolean")return builders.literal(n);if(Array.isArray(n))return builders.arrayExpression(n.map(e=>g(e,t,s,i,r,o)));if(y(n))return Gn(n.$,t,i,r,o);if(T(n))return Dn(n,t,s,i,r,o);if(C(n))return In(n.$pipe,t,s,i,r,o);if(b(n))return zn(n,t,s,i,r,o);if(E(n))return Mn(n,t,s,i,r,o);if(h(n))return Vn(n,t,s,i,r,o);if(typeof n=="object"){let f=Object.entries(n).map(([l,c])=>builders.property(builders.identifier(l),g(c,t,s,i,r,o)));return builders.objectExpression(f)}return builders.literal(null)}var _="accessor";function L(n,t){return t?n===t||n.startsWith(t+"."):false}function Gn(n,t,s,i,r){return i?L(n,r)?k(n,t,true):builders.callExpression(builders.identifier(_),[builders.literal(n),builders.identifier(t)]):n.includes("[*]")?Wn(n,t,s):k(n,t,s)}function k(n,t,s){let i=v(n);if(i.length===0)return s?builders.identifier("undefined"):builders.identifier(t);let r;if(s){let o=i[0];r=builders.identifier(o.value);for(let e=1;e<i.length;e++){let f=i[e];f.type==="key"?r=builders.memberExpression(r,builders.identifier(f.value),false,true):r=builders.memberExpression(r,builders.literal(f.value),true,true);}}else {r=builders.identifier(t);for(let o of i)o.type==="key"?r=builders.memberExpression(r,builders.identifier(o.value),false,true):r=builders.memberExpression(r,builders.literal(o.value),true,true);}return r}function Wn(n,t,s){let i=n.indexOf("[*]"),r=n.slice(0,i),o=n.slice(i+3),e;if(r?e=k(r,t,s):e=s?builders.identifier("undefined"):builders.identifier(t),!o||o==="")return e;if(o.includes("[*]"))return tn(e,o);let f="_i",l=o.startsWith(".")?o.slice(1):o,c=builders.identifier(f);if(l){let a=v(l);for(let p of a)p.type==="key"?c=builders.memberExpression(c,builders.identifier(p.value),false,true):c=builders.memberExpression(c,builders.literal(p.value),true,true);}return builders.callExpression(builders.memberExpression(e,builders.identifier("map"),false,true),[builders.arrowFunctionExpression([builders.identifier(f)],c)])}function tn(n,t){let s=t.indexOf("[*]"),i=t.slice(0,s),r=t.slice(s+3),o="_i",e=i.startsWith(".")?i.slice(1):i,f=builders.identifier(o);if(e){let c=v(e);for(let a of c)a.type==="key"&&(f=builders.memberExpression(f,builders.identifier(a.value),false,true));}if(r.includes("[*]")){let c=tn(f,r);return builders.callExpression(builders.memberExpression(n,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([builders.identifier(o)],c)])}let l=r.startsWith(".")?r.slice(1):r;if(l){let c=v(l);for(let a of c)a.type==="key"&&(f=builders.memberExpression(f,builders.identifier(a.value),false,true));}return builders.callExpression(builders.memberExpression(n,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([builders.identifier(o)],f)])}function Dn(n,t,s,i,r,o){let e;if(typeof n.$if=="string"){let c=n.$if.startsWith("!"),a=c?n.$if.slice(1):n.$if,p;r?L(a,o)?p=k(a,t,true):p=builders.callExpression(builders.identifier(_),[builders.literal(a),builders.identifier(t)]):p=k(a,t,i),e=c?builders.unaryExpression("!",p):p;}else e=g(n.$if,t,s,i,r,o);let f=g(n.then,t,s,i,r,o),l=n.else!==void 0?g(n.else,t,s,i,r,o):builders.identifier("undefined");return builders.conditionalExpression(e,f,l)}function zn(n,t,s,i,r,o){let e=i?builders.identifier(n.$fn):builders.memberExpression(builders.identifier(s),builders.identifier(n.$fn),false,false);if(n.args===void 0)return e;let f=n.args.map(l=>g(l,t,s,i,r,o));return builders.callExpression(e,f)}function In(n,t,s,i,r,o){if(n.length===0)return builders.identifier("undefined");if(n.length===1)return g(n[0],t,s,i,r,o);let e=g(n[0],t,s,i,r,o);for(let f=1;f<n.length;f++){let l=g(n[f],t,s,i,r,o);e=builders.callExpression(l,[e]);}return e}function Z(n,t,s,i,r,o){if(y(n)){let e=n.$;return r?L(e,o)?k(e,t,true):builders.callExpression(builders.identifier(_),[builders.literal(e),builders.identifier(t)]):k(e,t,i)}return g(n,t,s,i,r,o)}function Mn(n,t,s,i,r,o){let e=Z(n.left,t,s,i,r,o),f=n.right!==void 0?Z(n.right,t,s,i,r,o):builders.literal(null),l=vn[n.op];if(l)return builders.binaryExpression(l,e,f);switch(n.op){case "in":return builders.callExpression(builders.memberExpression(f,builders.identifier("includes")),[e]);case "notIn":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(f,builders.identifier("includes")),[e]));case "contains":return builders.callExpression(builders.memberExpression(e,builders.identifier("includes"),false,true),[f]);case "notContains":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(e,builders.identifier("includes"),false,true),[f]));case "exists":return builders.binaryExpression("!=",e,builders.literal(null));case "notExists":return builders.binaryExpression("==",e,builders.literal(null));case "matches":return builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[f]),builders.identifier("test")),[e]);case "notMatches":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[f]),builders.identifier("test")),[e]));case "startsWith":return builders.callExpression(builders.memberExpression(e,builders.identifier("startsWith"),false,true),[f]);case "endsWith":return builders.callExpression(builders.memberExpression(e,builders.identifier("endsWith"),false,true),[f]);default:return builders.binaryExpression("===",e,f)}}function Vn(n,t,s,i,r,o){let{logic:e,conditions:f}=n,l=e==="AND"?"&&":"||";if(f.length===0)return builders.literal(e==="AND");if(f.length===1)return g(f[0],t,s,i,r,o);let c=g(f[0],t,s,i,r,o);for(let a=1;a<f.length;a++){let p=g(f[a],t,s,i,r,o);c=builders.logicalExpression(l,c,p);}return c}function v(n){let t=[],s=n.length,i=0,r="";for(;i<s;){let o=n[i];if(o===".")r&&(t.push({type:"key",value:r}),r=""),i++;else if(o==="["){r&&(t.push({type:"key",value:r}),r=""),i++;let e=i;for(;i<s&&n[i]!=="]";)i++;let f=n.slice(e,i);if(i++,f!=="*"){let l=parseInt(f,10);t.push({type:"index",value:isNaN(l)?f:l});}}else r+=o,i++;}return r&&t.push({type:"key",value:r}),t}function en(n,t=[V]){return builders.arrowFunctionExpression(t.map(s=>builders.identifier(s)),n)}function W(n){let t=new Set;return S(n,t),t}function S(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let i of n)S(i,t);return}if(y(n))return;if(T(n)){S(n.$if,t),S(n.then,t),n.else!==void 0&&S(n.else,t);return}if(C(n)){for(let i of n.$pipe)S(i,t);return}if(b(n)){if(t.add(n.$fn),n.args)for(let i of n.args)S(i,t);return}if(E(n)){n.left!==void 0&&typeof n.left=="object"&&S(n.left,t),n.right!==void 0&&typeof n.right=="object"&&S(n.right,t);return}if(h(n)){for(let i of n.conditions)S(i,t);return}let s=n;for(let i of Object.keys(s))S(s[i],t);}function D(n){let t=new Set;for(let s of n){let i=s.indexOf("."),r=s.indexOf("["),o=s.length;i!==-1&&(o=Math.min(o,i)),r!==-1&&(o=Math.min(o,r));let e=s.slice(0,o);e&&t.add(e);}return t}function Ln(n){return JSON.stringify(n)}function qn(n,t,s,i,r){let o=G(n,{noPrefixes:true,useAccessor:i,lexicalPrefix:r}),e=generate(o),f="";i?r&&(f=`const{${r}}=data??{};`):t.size>0&&(f=`const{${[...t].join(",")}}=data??{};`);let l=i?new Set([...s,"accessor"]):s,c=l.size>0?`const{${[...l].join(",")}}=scope;`:"";return c?`(function(scope){${c}return function(data){${f}return ${e}}})`:`(function(){return function(data){${f}return ${e}}})`}function q(n,t={}){let{scope:s={},returnCode:i=false,useAccessor:r=false,lexicalPrefix:o}=t,e=w(n),f=D(e),l=W(n),c=Ln(n),a=qn(n,f,l,r,o);if(i)return {code:a,deps:e,hash:c,dataRoots:[...f],scopeFns:[...l]};let p;try{p=new Function(`return ${a}`)()(s);}catch(d){throw new Error(`AST compilation failed. If this is due to CSP, use the standard compile() function instead. Error: ${d instanceof Error?d.message:String(d)}`)}return {fn:p,deps:e,hash:c}}function on(n,t,s={}){let{fn:i}=q(n,s);return i(t)}function Jn(n,t){return z(n,t)}function z(n,t){if(n===null)return null;if(typeof n!="object")return n;if(Array.isArray(n))return n.map(o=>z(o,t));let s=n,i=Object.keys(s);for(let o of i)if(o in t){let e=t[o](s);if(typeof e=="object"&&e!==null&&o in e)throw new Error(`Transform "${o}" returned object with same key \u2014 infinite loop`);return z(e,t)}let r={};for(let o of i)r[o]=z(s[o],t);return r}var bt="2.0.0";export{j as ExpressionCache,bt as VERSION,kn as assertValid,X as builders,P as cache,wn as cached,dn as clearPathCache,N as compile,q as compileAST,O as compilePath,G as dslToAST,Sn as evaluate,on as evaluateAST,D as extractDataRoots,w as extractDeps,W as extractScopeFns,pn as get,gn as getPathCacheSize,mn as hasDeps,B as hasWildcard,E as isCondition,fn as isConditionExpr,h as isConditionGroup,T as isConditional,b as isFn,I as isLiteral,C as isPipe,yn as isPure,y as isRef,xn as isValid,Jn as normalize,F as normalizePath,M as validate,en as wrapInFunction};
|
|
1
|
+
import {builders,generate}from'omni-ast';var mn=Object.defineProperty;var En=(n,t)=>{for(var o in t)mn(n,o,{get:t[o],enumerable:true});};var E=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,S=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,k=n=>n!==null&&typeof n=="object"&&"$fn"in n&&typeof n.$fn=="string",x=n=>n!==null&&typeof n=="object"&&"$pipe"in n&&Array.isArray(n.$pipe),R=n=>n!==null&&typeof n=="object"&&"$cb"in n&&typeof n.$cb=="string"&&"body"in n,G=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&&G.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),b=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,hn=n=>h(n)||b(n),q=n=>{if(n===null)return true;let t=typeof n;if(t==="string"||t==="number"||t==="boolean"||Array.isArray(n))return true;if(t==="object"&&n!==null){let o=n,r="left"in o&&"op"in o&&G.has(o.op);return !("$"in o)&&!("$if"in o)&&!("$fn"in o)&&!("$pipe"in o)&&!("$cb"in o)&&!r&&!("logic"in o)}return false};var I=new Map;function Q(n){let t=[],o=n.length,r=0,i="";for(;r<o;){let s=n[r];if(s===".")i&&(t.push({type:"key",value:i}),i=""),r++;else if(s==="["){i&&(t.push({type:"key",value:i}),i=""),r++;let e=r;for(;r<o&&n[r]!=="]";)r++;let f=n.slice(e,r);if(r++,f==="*")t.push({type:"wildcard",value:"*"});else {let u=parseInt(f,10);t.push({type:"index",value:isNaN(u)?f:u});}}else i+=s,r++;}return i&&t.push({type:"key",value:i}),t}function U(n){return n.includes("[*]")}function N(n){let t=I.get(n);return t||(t=U(n)?Cn(n):bn(n),I.set(n,t),t)}function bn(n){if(!n.includes(".")&&!n.includes("["))return i=>i?.[n];let t=Q(n),o=t.length;if(o===2){let[i,s]=t,e=i.value,f=s.value;return u=>u?.[e]?.[f]}if(o===3){let[i,s,e]=t,f=i.value,u=s.value,l=e.value;return a=>a?.[f]?.[u]?.[l]}let r=t.map(i=>i.value);return i=>{let s=i;for(let e=0;e<o&&s!=null;e++)s=s[r[e]];return s}}function Cn(n){let t=Q(n),o=[];for(let r=0;r<t.length;r++)t[r].type==="wildcard"&&o.push(r);return o.length===1?Tn(t,o[0]):$n(t,o)}function Tn(n,t){let o=n.slice(0,t).map(e=>e.value),r=n.slice(t+1).map(e=>e.value),i=o.length,s=r.length;if(s===0){if(i===1){let e=o[0];return f=>f?.[e]}return e=>{let f=e;for(let u=0;u<i&&f!=null;u++)f=f[o[u]];return f}}if(s===1){let e=r[0];if(i===1){let f=o[0];return u=>{let l=u?.[f];if(Array.isArray(l))return l.map(a=>a?.[e])}}return f=>{let u=f;for(let l=0;l<i&&u!=null;l++)u=u[o[l]];if(Array.isArray(u))return u.map(l=>l?.[e])}}return e=>{let f=e;for(let u=0;u<i&&f!=null;u++)f=f[o[u]];if(Array.isArray(f))return f.map(u=>{let l=u;for(let a=0;a<s&&l!=null;a++)l=l[r[a]];return l})}}function $n(n,t){let o=[],r=0;for(let s=0;s<t.length;s++){let e=t[s],f=s===t.length-1,u=n.slice(r,e).map(l=>l.value);u.length>0&&o.push({type:"access",keys:u}),o.push({type:f?"map":"flatMap",keys:[]}),r=e+1;}let i=n.slice(r).map(s=>s.value);return s=>{let e=s;for(let f of o){if(e==null)return;if(f.type==="access")for(let u of f.keys){if(e==null)return;e=e[u];}else if(f.type==="flatMap"){if(!Array.isArray(e))return;e=e.flatMap(u=>{let l=u;return Array.isArray(l)?l:[l]});}else if(f.type==="map"){if(!Array.isArray(e))return;i.length>0&&(e=e.map(u=>{let l=u;for(let a of i){if(l==null)return;l=l[a];}return l}));}}return e}}function An(n,t){return N(t)(n)}function W(n){let t=n.indexOf("[*]");return t===-1?n:n.slice(0,t)}function Sn(){I.clear();}function kn(){return I.size}function F(n){let t=new Set;return C(n,t),Array.from(t)}function C(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let i=0;i<n.length;i++)C(n[i],t);return}if(E(n)){t.add(W(n.$));return}if(S(n)){if(typeof n.$if=="string"){let i=n.$if.startsWith("!")?n.$if.slice(1):n.$if;t.add(W(i));}else C(n.$if,t);C(n.then,t),n.else!==void 0&&C(n.else,t);return}if(x(n)){for(let i=0;i<n.$pipe.length;i++)C(n.$pipe[i],t);return}if(k(n)){if(n.args)for(let i=0;i<n.args.length;i++)C(n.args[i],t);return}if(R(n)){C(n.body,t),n.params!==void 0&&C(n.params,t);return}if(h(n)){C(n.left,t),n.right!==void 0&&C(n.right,t);return}if(b(n)){for(let i=0;i<n.conditions.length;i++)C(n.conditions[i],t);return}let o=n,r=Object.keys(o);for(let i=0;i<r.length;i++)C(o[r[i]],t);}function xn(n){return F(n).length>0}function Rn(n){return F(n).length===0}function wn(n){return JSON.stringify(n)}function j(n,t={}){let o=t.scope??{},r=t.accessor,i=t.context??{},s=m(n,o,r,i),e=F(n),f=wn(n);return {fn:s,deps:e,hash:f}}function m(n,t,o,r){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let i=n.map(s=>m(s,t,o,r));return s=>i.map(e=>e(s))}if(E(n))return Fn(n,o);if(S(n))return On(n,t,o,r);if(x(n))return vn(n,t,o,r);if(k(n))return jn(n,t,o,r);if(R(n))return Nn(n,t,o,r);if(h(n))return Gn(n,t,o,r);if(b(n))return In(n,t,o,r);if(q(n)){let i=n,s=Object.keys(i),e=s.map(f=>m(i[f],t,o,r));return f=>{let u={};for(let l=0;l<s.length;l++)u[s[l]]=e[l](f);return u}}return ()=>n}function Z(n,t){return t?o=>t(n,o):N(n)}function Fn(n,t){return Z(n.$,t)}function On(n,t,o,r){let i;if(typeof n.$if=="string"){let f=n.$if.startsWith("!")?n.$if.slice(1):n.$if,u=Z(f,o);i=n.$if.startsWith("!")?a=>!u(a):a=>!!u(a);}else {let f=m(n.$if,t,o,r);i=u=>!!f(u);}let s=m(n.then,t,o,r),e=n.else!==void 0?m(n.else,t,o,r):()=>{};return f=>i(f)?s(f):e(f)}function vn(n,t,o,r){let i=n.$pipe;if(i.length===0)return ()=>{};if(i.length===1)return m(i[0],t,o,r);let s=m(i[0],t,o,r),e=i.slice(1).map(u=>m(u,t,o,r)),f=e.length;if(f===1){let[u]=e;return l=>{let a=s(l),p=u(l);return typeof p=="function"?p(a):p}}if(f===2){let[u,l]=e;return a=>{let p=s(a),d=u(a);return p=typeof d=="function"?d(p):d,d=l(a),typeof d=="function"?d(p):d}}if(f===3){let[u,l,a]=e;return p=>{let d=s(p),g=u(p);return d=typeof g=="function"?g(d):g,g=l(p),d=typeof g=="function"?g(d):g,g=a(p),typeof g=="function"?g(d):g}}return u=>{let l=s(u);for(let a=0;a<f;a++){let p=e[a](u);l=typeof p=="function"?p(l):p;}return l}}function jn(n,t,o,r){let i=n.$fn,s=n.args;if(s===void 0)return ()=>{let u=t[i];if(!u)throw new Error(`Function not found in scope: ${i}`);return u};let e=s.map(u=>m(u,t,o,r)),f=e.length;if(f===0)return ()=>{let u=t[i];if(!u)throw new Error(`Function not found in scope: ${i}`);return u()};if(f===1){let[u]=e;return l=>{let a=t[i];if(!a)throw new Error(`Function not found in scope: ${i}`);return a(u(l))}}if(f===2){let[u,l]=e;return a=>{let p=t[i];if(!p)throw new Error(`Function not found in scope: ${i}`);return p(u(a),l(a))}}if(f===3){let[u,l,a]=e;return p=>{let d=t[i];if(!d)throw new Error(`Function not found in scope: ${i}`);return d(u(p),l(p),a(p))}}return u=>{let l=t[i];if(!l)throw new Error(`Function not found in scope: ${i}`);return l(...e.map(a=>a(u)))}}function Nn(n,t,o,r){let i=n.$cb,s=m(n.body,t,o,r),e=n.params?m(n.params,t,o,r):void 0,f=u=>o?l=>o(l,u):l=>N(l)(u);return u=>{let l=r?.[i];if(!l)throw new Error(`Context function not found: ${i}`);let a=(g,w)=>s(g),p=f(u),d=e?e(u):void 0;return l(a,u,p,d)}}function Gn(n,t,o,r){let i=m(n.left,t,o,r),s=n.right!==void 0?m(n.right,t,o,r):()=>{};switch(n.op){case "eq":return e=>i(e)===s(e);case "neq":return e=>i(e)!==s(e);case "gt":return e=>i(e)>s(e);case "gte":return e=>i(e)>=s(e);case "lt":return e=>i(e)<s(e);case "lte":return e=>i(e)<=s(e);case "in":return e=>{let f=s(e);return Array.isArray(f)&&f.includes(i(e))};case "notIn":return e=>{let f=s(e);return !Array.isArray(f)||!f.includes(i(e))};case "contains":return e=>{let f=i(e);return Array.isArray(f)&&f.includes(s(e))};case "notContains":return e=>{let f=i(e);return !Array.isArray(f)||!f.includes(s(e))};case "exists":return e=>i(e)!==void 0;case "notExists":return e=>i(e)===void 0;case "matches":return e=>{let f=i(e),u=s(e);return typeof f!="string"||typeof u!="string"?false:new RegExp(u).test(f)};case "notMatches":return e=>{let f=i(e),u=s(e);return typeof f!="string"||typeof u!="string"?true:!new RegExp(u).test(f)};case "startsWith":return e=>{let f=i(e),u=s(e);return typeof f=="string"&&typeof u=="string"&&f.startsWith(u)};case "endsWith":return e=>{let f=i(e),u=s(e);return typeof f=="string"&&typeof u=="string"&&f.endsWith(u)}}}function In(n,t,o,r){let i=n.conditions.map(e=>m(e,t,o,r)),s=i.length;if(s===1)return e=>!!i[0](e);if(s===2){let[e,f]=i;return n.logic==="AND"?u=>!!e(u)&&!!f(u):u=>!!e(u)||!!f(u)}if(s===3){let[e,f,u]=i;return n.logic==="AND"?l=>!!e(l)&&!!f(l)&&!!u(l):l=>!!e(l)||!!f(l)||!!u(l)}return n.logic==="AND"?e=>{for(let f=0;f<s;f++)if(!i[f](e))return false;return true}:e=>{for(let f=0;f<s;f++)if(i[f](e))return true;return false}}function Wn(n,t,o={}){return j(n,o).fn(t)}var z=class{constructor(t=1e3){this.cache=new Map,this._maxSize=t;}get(t,o={}){let r=JSON.stringify(t),i=this.cache.get(r);if(i)return this.cache.delete(r),this.cache.set(r,i),i;let s=j(t,o);if(this.cache.size>=this._maxSize){let e=this.cache.keys().next().value;e&&this.cache.delete(e);}return this.cache.set(r,s),s}has(t){return this.cache.has(JSON.stringify(t))}delete(t){return this.cache.delete(JSON.stringify(t))}clear(){this.cache.clear();}get size(){return this.cache.size}get maxSize(){return this._maxSize}set maxSize(t){for(this._maxSize=t;this.cache.size>this._maxSize;){let o=this.cache.keys().next().value;o&&this.cache.delete(o);}}},nn=new z;function zn(n,t={}){return nn.get(n,t)}function J(n,t="root",o={}){let r=[];return T(n,t,r,o),{valid:r.length===0,errors:r}}function T(n,t,o,r){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let e=0;e<n.length;e++)T(n[e],`${t}[${e}]`,o,r);return}if(E(n)){(!n.$||typeof n.$!="string")&&o.push(`${t}: invalid reference, $ must be non-empty string`);return}if(S(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||o.push(`${t}.$if: empty path in string shorthand`):T(n.$if,`${t}.$if`,o,r),T(n.then,`${t}.then`,o,r),n.else!==void 0&&T(n.else,`${t}.else`,o,r);return}if(x(n)){if(!Array.isArray(n.$pipe)){o.push(`${t}.$pipe: must be an array`);return}if(n.$pipe.length===0){o.push(`${t}.$pipe: must have at least one element`);return}for(let e=0;e<n.$pipe.length;e++)T(n.$pipe[e],`${t}.$pipe[${e}]`,o,r);return}if(k(n)){if(!n.$fn||typeof n.$fn!="string"){o.push(`${t}: invalid function, $fn must be non-empty string`);return}if(r.scope&&!(n.$fn in r.scope)&&o.push(`${t}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))o.push(`${t}.args: must be an array`);else for(let e=0;e<n.args.length;e++)T(n.args[e],`${t}.args[${e}]`,o,r);return}if(R(n)){if(!n.$cb||typeof n.$cb!="string"){o.push(`${t}: invalid callback, $cb must be non-empty string`);return}r.context&&!(n.$cb in r.context)&&o.push(`${t}: context function "${n.$cb}" not found`),T(n.body,`${t}.body`,o,r),n.params!==void 0&&T(n.params,`${t}.params`,o,r);return}if(h(n)){G.has(n.op)||o.push(`${t}: invalid operator "${n.op}"`),T(n.left,`${t}.left`,o,r),n.right!==void 0&&T(n.right,`${t}.right`,o,r);return}if(b(n)){if(n.logic!=="AND"&&n.logic!=="OR"&&o.push(`${t}: invalid logic "${n.logic}", must be "AND" or "OR"`),!Array.isArray(n.conditions)){o.push(`${t}.conditions: must be an array`);return}for(let e=0;e<n.conditions.length;e++)T(n.conditions[e],`${t}.conditions[${e}]`,o,r);return}let i=n,s=Object.keys(i);for(let e=0;e<s.length;e++){let f=s[e];T(i[f],`${t}.${f}`,o,r);}}function Dn(n,t={}){let o=J(n,"root",t);if(!o.valid)throw new Error(`Invalid expression: ${o.errors.join("; ")}`)}function Mn(n,t={}){return J(n,"root",t).valid}var un={};En(un,{$:()=>tn,$call:()=>fn,$cb:()=>sn,$cond:()=>rn,$fn:()=>en,$if:()=>Vn,$pipe:()=>on,call:()=>Kn,cb:()=>Jn,cond:()=>qn,fn:()=>_n,pipe:()=>Ln,ref:()=>Bn});function tn(n){return {$:n}}var Bn=tn;function en(n,t){return t===void 0||t.length===0?{$fn:n}:{$fn:n,args:t}}var _n=en;function Vn(n,t,o){return o===void 0?{$if:n,then:t}:{$if:n,then:t,else:o}}function on(...n){return {$pipe:n}}var Ln=on;function rn(n,t,o){return o===void 0?{left:n,op:t}:{left:n,op:t,right:o}}var qn=rn;function sn(n,t,o){return o===void 0?{$cb:n,body:t}:{$cb:n,body:t,params:o}}var Jn=sn;function fn(n,t=[]){return {$fn:n,args:t}}var Kn=fn;var K="data",ln="scope",Xn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function M(n,t={}){let{dataParam:o=K,scopeParam:r=ln,noPrefixes:i=false,useAccessor:s=false,lexicalPrefix:e}=t;return y(n,o,r,i,s,e)}function y(n,t,o,r,i,s){if(n===null)return builders.literal(null);if(typeof n=="string")return builders.literal(n);if(typeof n=="number")return builders.literal(n);if(typeof n=="boolean")return builders.literal(n);if(Array.isArray(n))return builders.arrayExpression(n.map(e=>y(e,t,o,r,i,s)));if(E(n))return Yn(n.$,t,r,i,s);if(S(n))return Pn(n,t,o,r,i,s);if(x(n))return nt(n.$pipe,t,o,r,i,s);if(k(n))return Qn(n,t,o,r,i,s);if(R(n))return Zn(n,t,o,r,i,s);if(h(n))return tt(n,t,o,r,i,s);if(b(n))return et(n,t,o,r,i,s);if(typeof n=="object"){let f=Object.entries(n).map(([u,l])=>builders.property(builders.identifier(u),y(l,t,o,r,i,s)));return builders.objectExpression(f)}return builders.literal(null)}var X="accessor";function Y(n,t){return t?n===t||n.startsWith(t+"."):false}function Yn(n,t,o,r,i){return r?Y(n,i)?O(n,t,true):builders.callExpression(builders.identifier(X),[builders.literal(n),builders.identifier(t)]):n.includes("[*]")?Hn(n,t,o):O(n,t,o)}function O(n,t,o){let r=D(n);if(r.length===0)return o?builders.identifier("undefined"):builders.identifier(t);let i;if(o){let s=r[0];i=builders.identifier(s.value);for(let e=1;e<r.length;e++){let f=r[e];f.type==="key"?i=builders.memberExpression(i,builders.identifier(f.value),false,true):i=builders.memberExpression(i,builders.literal(f.value),true,true);}}else {i=builders.identifier(t);for(let s of r)s.type==="key"?i=builders.memberExpression(i,builders.identifier(s.value),false,true):i=builders.memberExpression(i,builders.literal(s.value),true,true);}return i}function Hn(n,t,o){let r=n.indexOf("[*]"),i=n.slice(0,r),s=n.slice(r+3),e;if(i?e=O(i,t,o):e=o?builders.identifier("undefined"):builders.identifier(t),!s||s==="")return e;if(s.includes("[*]"))return an(e,s);let f="_i",u=s.startsWith(".")?s.slice(1):s,l=builders.identifier(f);if(u){let a=D(u);for(let p of a)p.type==="key"?l=builders.memberExpression(l,builders.identifier(p.value),false,true):l=builders.memberExpression(l,builders.literal(p.value),true,true);}return builders.callExpression(builders.memberExpression(e,builders.identifier("map"),false,true),[builders.arrowFunctionExpression([builders.identifier(f)],l)])}function an(n,t){let o=t.indexOf("[*]"),r=t.slice(0,o),i=t.slice(o+3),s="_i",e=r.startsWith(".")?r.slice(1):r,f=builders.identifier(s);if(e){let l=D(e);for(let a of l)a.type==="key"&&(f=builders.memberExpression(f,builders.identifier(a.value),false,true));}if(i.includes("[*]")){let l=an(f,i);return builders.callExpression(builders.memberExpression(n,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([builders.identifier(s)],l)])}let u=i.startsWith(".")?i.slice(1):i;if(u){let l=D(u);for(let a of l)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(s)],f)])}function Pn(n,t,o,r,i,s){let e;if(typeof n.$if=="string"){let l=n.$if.startsWith("!"),a=l?n.$if.slice(1):n.$if,p;i?Y(a,s)?p=O(a,t,true):p=builders.callExpression(builders.identifier(X),[builders.literal(a),builders.identifier(t)]):p=O(a,t,r),e=l?builders.unaryExpression("!",p):p;}else e=y(n.$if,t,o,r,i,s);let f=y(n.then,t,o,r,i,s),u=n.else!==void 0?y(n.else,t,o,r,i,s):builders.identifier("undefined");return builders.conditionalExpression(e,f,u)}function Qn(n,t,o,r,i,s){let e=r?builders.identifier(n.$fn):builders.memberExpression(builders.identifier(o),builders.identifier(n.$fn),false,false);if(n.args===void 0)return e;let f=n.args.map(u=>y(u,t,o,r,i,s));return builders.callExpression(e,f)}var Un="context";function Zn(n,t,o,r,i,s){let e=r?builders.identifier(n.$cb):builders.memberExpression(builders.identifier(Un),builders.identifier(n.$cb),false,false),f=y(n.body,t,o,r,i,s),l=[builders.arrowFunctionExpression([builders.identifier(t),builders.identifier("get")],f),builders.identifier(t),builders.identifier("get")];if(n.params!==void 0){let a=y(n.params,t,o,r,i,s);l.push(a);}return builders.callExpression(e,l)}function nt(n,t,o,r,i,s){if(n.length===0)return builders.identifier("undefined");if(n.length===1)return y(n[0],t,o,r,i,s);let e=y(n[0],t,o,r,i,s);for(let f=1;f<n.length;f++){let u=y(n[f],t,o,r,i,s);e=builders.callExpression(u,[e]);}return e}function cn(n,t,o,r,i,s){if(E(n)){let e=n.$;return i?Y(e,s)?O(e,t,true):builders.callExpression(builders.identifier(X),[builders.literal(e),builders.identifier(t)]):O(e,t,r)}return y(n,t,o,r,i,s)}function tt(n,t,o,r,i,s){let e=cn(n.left,t,o,r,i,s),f=n.right!==void 0?cn(n.right,t,o,r,i,s):builders.literal(null),u=Xn[n.op];if(u)return builders.binaryExpression(u,e,f);switch(n.op){case "in":return builders.callExpression(builders.memberExpression(f,builders.identifier("includes")),[e]);case "notIn":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(f,builders.identifier("includes")),[e]));case "contains":return builders.callExpression(builders.memberExpression(e,builders.identifier("includes"),false,true),[f]);case "notContains":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(e,builders.identifier("includes"),false,true),[f]));case "exists":return builders.binaryExpression("!=",e,builders.literal(null));case "notExists":return builders.binaryExpression("==",e,builders.literal(null));case "matches":return builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[f]),builders.identifier("test")),[e]);case "notMatches":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[f]),builders.identifier("test")),[e]));case "startsWith":return builders.callExpression(builders.memberExpression(e,builders.identifier("startsWith"),false,true),[f]);case "endsWith":return builders.callExpression(builders.memberExpression(e,builders.identifier("endsWith"),false,true),[f]);default:return builders.binaryExpression("===",e,f)}}function et(n,t,o,r,i,s){let{logic:e,conditions:f}=n,u=e==="AND"?"&&":"||";if(f.length===0)return builders.literal(e==="AND");if(f.length===1)return y(f[0],t,o,r,i,s);let l=y(f[0],t,o,r,i,s);for(let a=1;a<f.length;a++){let p=y(f[a],t,o,r,i,s);l=builders.logicalExpression(u,l,p);}return l}function D(n){let t=[],o=n.length,r=0,i="";for(;r<o;){let s=n[r];if(s===".")i&&(t.push({type:"key",value:i}),i=""),r++;else if(s==="["){i&&(t.push({type:"key",value:i}),i=""),r++;let e=r;for(;r<o&&n[r]!=="]";)r++;let f=n.slice(e,r);if(r++,f!=="*"){let u=parseInt(f,10);t.push({type:"index",value:isNaN(u)?f:u});}}else i+=s,r++;}return i&&t.push({type:"key",value:i}),t}function pn(n,t=[K]){return builders.arrowFunctionExpression(t.map(o=>builders.identifier(o)),n)}function B(n){let t=new Set;return $(n,t),t}function $(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r of n)$(r,t);return}if(E(n))return;if(S(n)){$(n.$if,t),$(n.then,t),n.else!==void 0&&$(n.else,t);return}if(x(n)){for(let r of n.$pipe)$(r,t);return}if(k(n)){if(t.add(n.$fn),n.args)for(let r of n.args)$(r,t);return}if(R(n)){$(n.body,t),n.params!==void 0&&$(n.params,t);return}if(h(n)){n.left!==void 0&&typeof n.left=="object"&&$(n.left,t),n.right!==void 0&&typeof n.right=="object"&&$(n.right,t);return}if(b(n)){for(let r of n.conditions)$(r,t);return}let o=n;for(let r of Object.keys(o))$(o[r],t);}function _(n){let t=new Set;return A(n,t),t}function A(n,t){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r of n)A(r,t);return}if(E(n))return;if(S(n)){A(n.$if,t),A(n.then,t),n.else!==void 0&&A(n.else,t);return}if(x(n)){for(let r of n.$pipe)A(r,t);return}if(k(n)){if(n.args)for(let r of n.args)A(r,t);return}if(R(n)){t.add(n.$cb),A(n.body,t),n.params!==void 0&&A(n.params,t);return}if(h(n)){n.left!==void 0&&typeof n.left=="object"&&A(n.left,t),n.right!==void 0&&typeof n.right=="object"&&A(n.right,t);return}if(b(n)){for(let r of n.conditions)A(r,t);return}let o=n;for(let r of Object.keys(o))A(o[r],t);}function V(n){let t=new Set;for(let o of n){let r=o.indexOf("."),i=o.indexOf("["),s=o.length;r!==-1&&(s=Math.min(s,r)),i!==-1&&(s=Math.min(s,i));let e=o.slice(0,s);e&&t.add(e);}return t}function ot(n){return JSON.stringify(n)}function rt(n,t,o,r,i,s){let e=M(n,{noPrefixes:true,useAccessor:i,lexicalPrefix:s}),f=generate(e),u="";i?s&&(u=`const{${s}}=data??{};`):t.size>0&&(u=`const{${[...t].join(",")}}=data??{};`);let l=i?new Set([...o,"accessor"]):o,a=l.size>0?`const{${[...l].join(",")}}=scope;`:"",p=r.size>0?`const{${[...r].join(",")}}=context;`:"",d=r.size>0,g="";d&&(i?g="const get=(path)=>accessor(path,data);":g="const get=(path)=>path.split('.').reduce((o,k)=>o?.[k],data);");let w=l.size>0,v;if(w||d){let gn=d?"scope,context":"scope",yn=`${u}${g}return ${f}`;v=`(function(${gn}){${a}${p}return function(data){${yn}}})`;}else v=`(function(){return function(data){${u}return ${f}}})`;return v}function H(n,t={}){let{scope:o={},context:r={},returnCode:i=false,useAccessor:s=false,lexicalPrefix:e}=t,f=F(n),u=V(f),l=B(n),a=_(n),p=ot(n),d=rt(n,u,l,a,s,e);if(i)return {code:d,deps:f,hash:p,dataRoots:[...u],scopeFns:[...l],contextFns:[...a]};let g;try{let w=a.size>0,v=new Function(`return ${d}`)();g=w?v(o,r):v(o);}catch(w){throw new Error(`AST compilation failed. If this is due to CSP, use the standard compile() function instead. Error: ${w instanceof Error?w.message:String(w)}`)}return {fn:g,deps:f,hash:p}}function dn(n,t,o={}){let{fn:r}=H(n,o);return r(t)}function st(n,t){return L(n,t)}function L(n,t){if(n===null)return null;if(typeof n!="object")return n;if(Array.isArray(n))return n.map(s=>L(s,t));let o=n,r=Object.keys(o);for(let s of r)if(s in t){let e=t[s](o);if(typeof e=="object"&&e!==null&&s in e)throw new Error(`Transform "${s}" returned object with same key \u2014 infinite loop`);return L(e,t)}let i={};for(let s of r)i[s]=L(o[s],t);return i}var ft=new Set(["$","$if","$fn","$pipe","$cb"]);function ut(){let n=0;return ()=>String(n++)}function ct(n,t){let{resolvers:o,scope:r={},genId:i,...s}=t,e=Object.keys(o);if(e.length===0)return {expr:n,scope:r};let f=new Set(e),u=[],l={compile:j,genId:i??ut(),scope:r,options:s},a=P(n,f,o,l,u),p={...r};for(let d=0;d<u.length;d++){let[g,w]=u[d];p[g]=w;}return {expr:a,scope:p}}function P(n,t,o,r,i){if(n===null)return null;if(typeof n!="object")return n;if(Array.isArray(n)){let l=n.length,a=new Array(l);for(let p=0;p<l;p++)a[p]=P(n[p],t,o,r,i);return a}let s=n,e=Object.keys(s),f=e.length;for(let l=0;l<f;l++){let a=e[l];if(a[0]==="$"&&!ft.has(a)&&t.has(a)){let p=o[a],d=p(s,r);return d.scopeEntry&&i.push(d.scopeEntry),d.expr}}let u={};for(let l=0;l<f;l++){let a=e[l];u[a]=P(s[a],t,o,r,i);}return u}var _t="2.0.0";export{z as ExpressionCache,_t as VERSION,Dn as assertValid,un as builders,nn as cache,zn as cached,Sn as clearPathCache,j as compile,H as compileAST,N as compilePath,M as dslToAST,Wn as evaluate,dn as evaluateAST,_ as extractContextFns,V as extractDataRoots,F as extractDeps,B as extractScopeFns,An as get,kn as getPathCacheSize,xn as hasDeps,U as hasWildcard,R as isCb,h as isCondition,hn as isConditionExpr,b as isConditionGroup,S as isConditional,k as isFn,q as isLiteral,x as isPipe,Rn as isPure,E as isRef,Mn as isValid,st as normalize,W as normalizePath,ct as resolveBoundaries,J as validate,pn as wrapInFunction};
|