@statedelta-libs/expressions 3.0.0 → 3.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 +152 -8
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +312 -25
- package/dist/index.d.ts +312 -25
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -91,29 +91,85 @@ type Expression = Literal | RefExpr | ConditionalExpr | FnExpr | PipeExpr | Arro
|
|
|
91
91
|
*/
|
|
92
92
|
type CompiledFn<T = unknown, R = unknown> = (data: T) => R;
|
|
93
93
|
/**
|
|
94
|
-
*
|
|
94
|
+
* Callable function bound to a context, with metadata as properties.
|
|
95
|
+
* Call directly — no `.fn` needed.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* const fn = artifact.bind({ scope, accessor });
|
|
99
|
+
* fn(data); // callable direct
|
|
100
|
+
* fn.deps; // ["hp", "armor"]
|
|
101
|
+
* fn.hash; // "a1b2c3"
|
|
102
|
+
* items.map(fn); // works as first-class function
|
|
103
|
+
*/
|
|
104
|
+
interface BoundFn<T = unknown, R = unknown> {
|
|
105
|
+
/** Execute the expression with the given data */
|
|
106
|
+
(data: T): R;
|
|
107
|
+
/** Paths this expression depends on */
|
|
108
|
+
readonly deps: string[];
|
|
109
|
+
/** Unique hash for caching */
|
|
110
|
+
readonly hash: string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create a BoundFn from a compiled function + metadata.
|
|
114
|
+
* Attaches deps and hash as readonly props.
|
|
95
115
|
*/
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
116
|
+
declare function createBoundFn<T = unknown, R = unknown>(fn: CompiledFn<T, R>, deps: string[], hash: string): BoundFn<T, R>;
|
|
117
|
+
/**
|
|
118
|
+
* Context-free compile artifact — result of compilation without pre-prepared fn.
|
|
119
|
+
* Stored in shared compile caches. Use bind() to attach context and get fn.
|
|
120
|
+
*/
|
|
121
|
+
interface CompileArtifact<T = unknown, R = unknown> {
|
|
99
122
|
/** Paths this expression depends on */
|
|
100
123
|
deps: string[];
|
|
101
124
|
/** Unique hash for caching */
|
|
102
125
|
hash: string;
|
|
126
|
+
/**
|
|
127
|
+
* Bind to a context and get a callable BoundFn.
|
|
128
|
+
* @param ctx - Runtime context (scope, accessor, handlers). Uses defaults if omitted.
|
|
129
|
+
*/
|
|
130
|
+
bind(ctx?: BindContext): BoundFn<T, R>;
|
|
103
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Context for bind() — runtime dependencies injected after compilation.
|
|
134
|
+
*/
|
|
135
|
+
interface BindContext {
|
|
136
|
+
scope?: Scope;
|
|
137
|
+
accessor?: AccessorFn;
|
|
138
|
+
handlers?: WrappedHandlers;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Alias for CompileArtifact — the public name going forward.
|
|
142
|
+
*/
|
|
143
|
+
type Artifact<T = unknown, R = unknown> = CompileArtifact<T, R>;
|
|
144
|
+
/**
|
|
145
|
+
* Describes what each flat parameter of the compiled factory expects.
|
|
146
|
+
* Order matches the factory's parameter order.
|
|
147
|
+
*/
|
|
148
|
+
type ParamSlot = {
|
|
149
|
+
kind: "scope";
|
|
150
|
+
name: string;
|
|
151
|
+
} | {
|
|
152
|
+
kind: "accessor";
|
|
153
|
+
} | {
|
|
154
|
+
kind: "handler";
|
|
155
|
+
ns: string;
|
|
156
|
+
m: string;
|
|
157
|
+
} | {
|
|
158
|
+
kind: "boundary";
|
|
159
|
+
index: number;
|
|
160
|
+
};
|
|
104
161
|
/**
|
|
105
162
|
* Path getter function
|
|
106
163
|
*/
|
|
107
164
|
type PathGetter<T = unknown> = (data: T) => unknown;
|
|
108
165
|
/**
|
|
109
|
-
* Accessor customizado para resolver paths
|
|
110
|
-
*
|
|
166
|
+
* Accessor customizado para resolver paths.
|
|
167
|
+
* Closure auto-suficiente — já sabe de onde ler.
|
|
111
168
|
*
|
|
112
169
|
* @example
|
|
113
|
-
*
|
|
114
|
-
* const accessor: AccessorFn<TickContext> = (path, ctx) => ctx.get(path);
|
|
170
|
+
* const accessor: AccessorFn = (path) => tickContext.get(path);
|
|
115
171
|
*/
|
|
116
|
-
type AccessorFn
|
|
172
|
+
type AccessorFn = (path: string) => unknown;
|
|
117
173
|
/**
|
|
118
174
|
* Validation result
|
|
119
175
|
*/
|
|
@@ -143,13 +199,46 @@ interface CompileOptions<T = unknown> {
|
|
|
143
199
|
* Quando fornecido, substitui o acesso direto por propriedade.
|
|
144
200
|
*
|
|
145
201
|
* @example
|
|
146
|
-
*
|
|
147
|
-
* compile(expr, { accessor: (path, ctx) => ctx.get(path) })
|
|
202
|
+
* compile(expr, { accessor: (path) => ctx.get(path) })
|
|
148
203
|
*/
|
|
149
|
-
accessor?: AccessorFn
|
|
204
|
+
accessor?: AccessorFn;
|
|
150
205
|
/** Boundary definitions for compile-time interception */
|
|
151
206
|
boundaries?: BoundaryDef<T>[];
|
|
207
|
+
/** Wrapped handlers (ctx already bound) for $fn "namespace:method" calls */
|
|
208
|
+
handlers?: WrappedHandlers;
|
|
152
209
|
}
|
|
210
|
+
/**
|
|
211
|
+
* Handler function — receives HandlerContext via `this` (bound at compile time).
|
|
212
|
+
* Must be a regular function or method shorthand (NOT arrow function).
|
|
213
|
+
* HandlerContext is defined in compiler.ts.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* {
|
|
217
|
+
* query: {
|
|
218
|
+
* find(key: string) { return this.scope.add(key, 1); }
|
|
219
|
+
* }
|
|
220
|
+
* }
|
|
221
|
+
*/
|
|
222
|
+
type HandlerFn = (...args: any[]) => any;
|
|
223
|
+
/**
|
|
224
|
+
* Handlers map — namespaces of handler methods.
|
|
225
|
+
* Provided by consumer in ExpressionCompiler constructor.
|
|
226
|
+
* Handlers access context via `this` (bound automatically via .bind()).
|
|
227
|
+
*
|
|
228
|
+
* @example
|
|
229
|
+
* {
|
|
230
|
+
* query: {
|
|
231
|
+
* find(filter: string) { return this.scope.transform(filter); },
|
|
232
|
+
* findAll() { return this.handlers.other.list(); },
|
|
233
|
+
* },
|
|
234
|
+
* }
|
|
235
|
+
*/
|
|
236
|
+
type HandlersMap = Record<string, Record<string, HandlerFn>>;
|
|
237
|
+
/**
|
|
238
|
+
* Wrapped handlers (ctx already bound via .bind()).
|
|
239
|
+
* Used internally by both pipelines.
|
|
240
|
+
*/
|
|
241
|
+
type WrappedHandlers = Record<string, Record<string, (...args: any[]) => any>>;
|
|
153
242
|
/**
|
|
154
243
|
* Boundary definition for compile-time interception.
|
|
155
244
|
* Allows foreign DSLs and compilers to plug into the expression walk.
|
|
@@ -214,22 +303,77 @@ type TransformFn = (node: Record<string, unknown>) => Expression;
|
|
|
214
303
|
*/
|
|
215
304
|
type Transforms = Record<string, TransformFn>;
|
|
216
305
|
|
|
306
|
+
/**
|
|
307
|
+
* @statedelta-libs/expressions - JIT Compiler
|
|
308
|
+
*
|
|
309
|
+
* IR-based pipeline: receives IR from analyze(), emits optimized JS via AST.
|
|
310
|
+
* Factory with flat parameters — zero destructuring, zero property chains.
|
|
311
|
+
* No DSL knowledge — no guards, no type detection.
|
|
312
|
+
*/
|
|
313
|
+
|
|
314
|
+
/** Result when returnCode is true */
|
|
315
|
+
interface JITCodeResult {
|
|
316
|
+
code: string;
|
|
317
|
+
deps: string[];
|
|
318
|
+
hash: string;
|
|
319
|
+
dataRoots: string[];
|
|
320
|
+
scopeFns: string[];
|
|
321
|
+
paramNames: string[];
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* @statedelta-libs/expressions - Cache
|
|
326
|
+
*
|
|
327
|
+
* LRU cache for compiled expressions and compile artifacts.
|
|
328
|
+
* Performance: cache hit ~10M ops/sec
|
|
329
|
+
*/
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Shared compile cache — stores context-free CompileArtifacts.
|
|
333
|
+
* Can be shared between ExpressionCompiler instances for multi-tenant scenarios.
|
|
334
|
+
* Dual mode: separate closures and JIT caches.
|
|
335
|
+
*/
|
|
336
|
+
declare class CompileCache {
|
|
337
|
+
private closures;
|
|
338
|
+
private jit;
|
|
339
|
+
constructor(maxSize?: number);
|
|
340
|
+
/**
|
|
341
|
+
* Get or compile artifact by key and mode.
|
|
342
|
+
*/
|
|
343
|
+
getOrCompile<V>(key: string, mode: "closures" | "jit", factory: () => V): V;
|
|
344
|
+
/**
|
|
345
|
+
* Cache size per mode
|
|
346
|
+
*/
|
|
347
|
+
get size(): {
|
|
348
|
+
closures: number;
|
|
349
|
+
jit: number;
|
|
350
|
+
};
|
|
351
|
+
/**
|
|
352
|
+
* Clear both caches
|
|
353
|
+
*/
|
|
354
|
+
clear(): void;
|
|
355
|
+
}
|
|
356
|
+
|
|
217
357
|
/**
|
|
218
358
|
* @statedelta-libs/expressions - ExpressionCompiler
|
|
219
359
|
*
|
|
220
360
|
* Unified public API for expression compilation.
|
|
221
|
-
*
|
|
361
|
+
* Phase 4: two-level cache (instance + shared compile), DI-first pattern.
|
|
222
362
|
*/
|
|
223
363
|
|
|
224
364
|
interface ExpressionCompilerOptions<T = unknown> {
|
|
225
365
|
/** Functions available to $fn expressions */
|
|
226
366
|
scope?: Scope;
|
|
227
367
|
/** Custom accessor for resolving paths */
|
|
228
|
-
accessor?: AccessorFn
|
|
368
|
+
accessor?: AccessorFn;
|
|
229
369
|
/** Max LRU cache size per mode (default: 1000) */
|
|
230
370
|
cacheSize?: number;
|
|
231
371
|
/** Boundary definitions for compile-time interception */
|
|
232
372
|
boundaries?: BoundaryDef<T>[];
|
|
373
|
+
/** Handler namespaces — services with injected context */
|
|
374
|
+
handlers?: HandlersMap;
|
|
375
|
+
/** Shared compile cache — enables cross-instance cache sharing */
|
|
376
|
+
compileCache?: CompileCache;
|
|
233
377
|
}
|
|
234
378
|
interface JITOptions {
|
|
235
379
|
/** Use accessor to resolve paths instead of direct access */
|
|
@@ -237,34 +381,84 @@ interface JITOptions {
|
|
|
237
381
|
/** Prefix for paths that bypass accessor (direct access) */
|
|
238
382
|
lexicalPrefix?: string;
|
|
239
383
|
}
|
|
384
|
+
interface CompileConfig {
|
|
385
|
+
/** Use accessor to resolve paths instead of direct access */
|
|
386
|
+
useAccessor?: boolean;
|
|
387
|
+
}
|
|
388
|
+
interface EvalOptions {
|
|
389
|
+
/** Pipeline: "closures" (default) or "jit" */
|
|
390
|
+
mode?: "closures" | "jit";
|
|
391
|
+
/** Use accessor to resolve paths instead of direct access */
|
|
392
|
+
useAccessor?: boolean;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Context available via `this` inside every handler (bound via .bind()).
|
|
396
|
+
* Created once per ExpressionCompiler instance — zero per-call overhead.
|
|
397
|
+
*/
|
|
398
|
+
interface HandlerContext<T = unknown> {
|
|
399
|
+
/** Custom accessor for resolving paths */
|
|
400
|
+
accessor?: AccessorFn;
|
|
401
|
+
/** All wrapped handlers — handlers can call other handlers */
|
|
402
|
+
handlers: WrappedHandlers;
|
|
403
|
+
/** Compiler instance — can compile sub-expressions */
|
|
404
|
+
compiler: ExpressionCompiler<T>;
|
|
405
|
+
/** Pure scope functions */
|
|
406
|
+
scope: Scope;
|
|
407
|
+
}
|
|
240
408
|
declare class ExpressionCompiler<T = unknown> {
|
|
241
409
|
private readonly scope;
|
|
242
410
|
private readonly accessor?;
|
|
243
411
|
private readonly boundaries?;
|
|
412
|
+
private readonly wrappedHandlers?;
|
|
413
|
+
private readonly compileCache?;
|
|
244
414
|
private readonly cacheClosures;
|
|
245
415
|
private readonly cacheJIT;
|
|
246
416
|
constructor(options?: ExpressionCompilerOptions<T>);
|
|
247
|
-
/** Compile via closure composition
|
|
248
|
-
compile<R = unknown>(expr: Expression):
|
|
249
|
-
/** Compile via JS code generation (JIT) */
|
|
250
|
-
jit<R = unknown>(expr: Expression, opts?: JITOptions):
|
|
251
|
-
/**
|
|
252
|
-
|
|
253
|
-
/** Compile
|
|
254
|
-
|
|
417
|
+
/** Compile via closure composition — DSL → IR → closures */
|
|
418
|
+
compile<R = unknown>(expr: Expression, opts?: CompileConfig): CompileArtifact<T, R>;
|
|
419
|
+
/** Compile via JS code generation (JIT) — DSL → IR → AST → JS */
|
|
420
|
+
jit<R = unknown>(expr: Expression, opts?: JITOptions): CompileArtifact<T, R>;
|
|
421
|
+
/** Return generated JS code without creating function — for inspection/testing */
|
|
422
|
+
jitCode(expr: Expression, opts?: JITOptions): JITCodeResult;
|
|
423
|
+
/** Compile, bind with default context, and execute in one step */
|
|
424
|
+
eval<R = unknown>(expr: Expression, data: T, opts?: EvalOptions): R;
|
|
425
|
+
/**
|
|
426
|
+
* Wrap raw handlers with ctx via .bind().
|
|
427
|
+
* Creates ctx once, binds each handler method once.
|
|
428
|
+
* Resolves circular reference: ctx.handlers = wrappedHandlers.
|
|
429
|
+
* Handlers access ctx via `this`.
|
|
430
|
+
*/
|
|
431
|
+
private wrapHandlers;
|
|
255
432
|
/** Normalize custom expression to pure DSL */
|
|
256
433
|
normalize(expr: Expression, transforms: Transforms): Expression;
|
|
257
434
|
/** Extract dependencies without compiling */
|
|
258
435
|
extractDeps(expr: Expression): string[];
|
|
259
|
-
/**
|
|
436
|
+
/** Instance cache size per mode */
|
|
260
437
|
get cacheSize(): {
|
|
261
438
|
closures: number;
|
|
262
439
|
jit: number;
|
|
263
440
|
};
|
|
264
|
-
/** Clear
|
|
441
|
+
/** Clear instance caches */
|
|
265
442
|
clearCache(): void;
|
|
266
443
|
/** Read-only access to scope */
|
|
267
444
|
getScope(): Readonly<Scope>;
|
|
445
|
+
/**
|
|
446
|
+
* Get or create compile artifact.
|
|
447
|
+
* Two-level: compile cache (shared, optional) → fresh compile.
|
|
448
|
+
*/
|
|
449
|
+
private getArtifact;
|
|
450
|
+
/**
|
|
451
|
+
* Full compile: analyze → backend → CompileArtifact.
|
|
452
|
+
*/
|
|
453
|
+
private doCompile;
|
|
454
|
+
/**
|
|
455
|
+
* Default BindContext from constructor options.
|
|
456
|
+
*/
|
|
457
|
+
private defaultCtx;
|
|
458
|
+
/**
|
|
459
|
+
* Build compile cache key including compile-time flags.
|
|
460
|
+
*/
|
|
461
|
+
private compileCacheKey;
|
|
268
462
|
}
|
|
269
463
|
|
|
270
464
|
/**
|
|
@@ -465,6 +659,10 @@ declare const isConditionGroup: (v: unknown) => v is ConditionGroup;
|
|
|
465
659
|
* Check if value is any condition expression
|
|
466
660
|
*/
|
|
467
661
|
declare const isConditionExpr: (v: unknown) => v is ConditionExpr;
|
|
662
|
+
/**
|
|
663
|
+
* Check if value is any Expression DSL node
|
|
664
|
+
*/
|
|
665
|
+
declare const isExpression: (v: unknown) => boolean;
|
|
468
666
|
/**
|
|
469
667
|
* Check if value is a literal (not an expression object)
|
|
470
668
|
*/
|
|
@@ -484,6 +682,8 @@ interface ValidateOptions {
|
|
|
484
682
|
scope?: Scope;
|
|
485
683
|
/** Boundary definitions — matched nodes skip validation */
|
|
486
684
|
boundaries?: BoundaryDef[];
|
|
685
|
+
/** Handlers map to validate handler names against (optional) */
|
|
686
|
+
handlers?: HandlersMap;
|
|
487
687
|
}
|
|
488
688
|
/**
|
|
489
689
|
* Validate expression structure
|
|
@@ -550,6 +750,93 @@ declare function hasDeps(expr: Expression): boolean;
|
|
|
550
750
|
*/
|
|
551
751
|
declare function isPure(expr: Expression): boolean;
|
|
552
752
|
|
|
753
|
+
/**
|
|
754
|
+
* Template Compiler — Types
|
|
755
|
+
*
|
|
756
|
+
* Declarative template system for compiling arbitrary JSON structures
|
|
757
|
+
* using ExpressionCompiler as the engine.
|
|
758
|
+
*/
|
|
759
|
+
|
|
760
|
+
type SchemaType = "string" | "number" | "boolean" | "string[]" | "number[]" | "enum" | "schema" | "object" | "any";
|
|
761
|
+
interface SchemaFieldDef {
|
|
762
|
+
type: SchemaType;
|
|
763
|
+
required?: boolean;
|
|
764
|
+
default?: unknown;
|
|
765
|
+
values?: string[];
|
|
766
|
+
}
|
|
767
|
+
interface FieldHandlerOptions {
|
|
768
|
+
allow?: string[];
|
|
769
|
+
deny?: string[];
|
|
770
|
+
transforms?: Transforms;
|
|
771
|
+
mode?: "closures" | "jit";
|
|
772
|
+
}
|
|
773
|
+
type FieldHandler = (value: unknown, compiler: ExpressionCompiler, options: FieldHandlerOptions) => unknown;
|
|
774
|
+
type CompileFieldDef = {
|
|
775
|
+
compile: "condition";
|
|
776
|
+
} | {
|
|
777
|
+
compile: "expression";
|
|
778
|
+
} | {
|
|
779
|
+
compile: string;
|
|
780
|
+
allow?: string[];
|
|
781
|
+
deny?: string[];
|
|
782
|
+
} | {
|
|
783
|
+
compile: FieldHandler;
|
|
784
|
+
allow?: string[];
|
|
785
|
+
deny?: string[];
|
|
786
|
+
[key: string]: unknown;
|
|
787
|
+
};
|
|
788
|
+
type FieldDef = CompileFieldDef | SchemaFieldDef;
|
|
789
|
+
type DefinitionTemplate = Record<string, FieldDef>;
|
|
790
|
+
interface CompileDefinitionOptions {
|
|
791
|
+
transforms?: Transforms;
|
|
792
|
+
mode?: "closures" | "jit";
|
|
793
|
+
validate?: boolean;
|
|
794
|
+
handlers?: Record<string, FieldHandler>;
|
|
795
|
+
}
|
|
796
|
+
interface CompiledDefinition<T = unknown> {
|
|
797
|
+
[field: string]: unknown;
|
|
798
|
+
/** Bind to a context — re-binds all compiled fields */
|
|
799
|
+
bind(ctx: BindContext): CompiledDefinition<T>;
|
|
800
|
+
}
|
|
801
|
+
type DefinitionValidationErrorType = "unknown_field" | "missing_required" | "type_mismatch" | "invalid_enum";
|
|
802
|
+
interface DefinitionValidationError {
|
|
803
|
+
field: string;
|
|
804
|
+
message: string;
|
|
805
|
+
type: DefinitionValidationErrorType;
|
|
806
|
+
}
|
|
807
|
+
interface DefinitionValidationResult {
|
|
808
|
+
valid: boolean;
|
|
809
|
+
errors: DefinitionValidationError[];
|
|
810
|
+
}
|
|
811
|
+
declare function isCompileField(def: FieldDef): def is CompileFieldDef;
|
|
812
|
+
declare function isSchemaField(def: FieldDef): def is SchemaFieldDef;
|
|
813
|
+
declare function isNativeCompile(def: CompileFieldDef): def is {
|
|
814
|
+
compile: "condition";
|
|
815
|
+
} | {
|
|
816
|
+
compile: "expression";
|
|
817
|
+
};
|
|
818
|
+
declare function isHandlerCompile(def: CompileFieldDef): def is {
|
|
819
|
+
compile: FieldHandler;
|
|
820
|
+
[key: string]: unknown;
|
|
821
|
+
};
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Template Compiler — Core Compilation
|
|
825
|
+
*
|
|
826
|
+
* compileDefinition(): validates, normalizes, compiles, and assembles
|
|
827
|
+
* a JSON structure using a template + ExpressionCompiler.
|
|
828
|
+
*/
|
|
829
|
+
|
|
830
|
+
declare function compileDefinition<T = unknown>(dsl: Record<string, unknown>, template: DefinitionTemplate, compiler: ExpressionCompiler, options?: CompileDefinitionOptions): CompiledDefinition<T>;
|
|
831
|
+
|
|
832
|
+
/**
|
|
833
|
+
* Template Compiler — Validation
|
|
834
|
+
*
|
|
835
|
+
* Validates a DSL object against a DefinitionTemplate.
|
|
836
|
+
*/
|
|
837
|
+
|
|
838
|
+
declare function validateDefinition(dsl: Record<string, unknown>, template: DefinitionTemplate): DefinitionValidationResult;
|
|
839
|
+
|
|
553
840
|
/**
|
|
554
841
|
* @statedelta-libs/expressions
|
|
555
842
|
*
|
|
@@ -558,4 +845,4 @@ declare function isPure(expr: Expression): boolean;
|
|
|
558
845
|
*/
|
|
559
846
|
declare const VERSION = "3.0.0";
|
|
560
847
|
|
|
561
|
-
export { type AccessorFn, type ArrowExpr, type BoundaryDef, type CompileOptions, type
|
|
848
|
+
export { type AccessorFn, type ArrowExpr, type Artifact, type BindContext, type BoundFn, type BoundaryDef, type CompileArtifact, CompileCache, type CompileConfig, type CompileDefinitionOptions, type CompileFieldDef, type CompileOptions, type CompiledDefinition, type CompiledFn, type Condition, type ConditionExpr, type ConditionGroup, type ConditionOp, type ConditionalExpr, type DefinitionTemplate, type DefinitionValidationError, type DefinitionValidationErrorType, type DefinitionValidationResult, type EvalOptions, type Expression, ExpressionCompiler, type ExpressionCompilerOptions, type FieldDef, type FieldHandler, type FieldHandlerOptions, type FnExpr, type HandlerContext, type HandlerFn, type HandlersMap, type JITCodeResult, type JITOptions, type Literal, type ParamSlot, type PipeExpr, type RefExpr, type SchemaFieldDef, type SchemaType, type Scope, type TransformFn, type Transforms, VERSION, type ValidateOptions, type ValidationResult, type WrappedHandlers, assertValid, builders, compileDefinition, compilePath, createBoundFn, extractDeps, get, hasDeps, hasWildcard, isArrow, isCompileField, isCondition, isConditionExpr, isConditionGroup, isConditional, isExpression, isFn, isHandlerCompile, isLiteral, isNativeCompile, isPipe, isPure, isRef, isSchemaField, isValid, normalizePath, validate, validateDefinition };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {generate,builders}from'omni-ast';var xn=Object.defineProperty;var Fn=(n,e)=>{for(var i in e)xn(n,i,{get:e[i],enumerable:true});};var _=new Set(["eq","neq","gt","gte","lt","lte","in","notIn","contains","notContains","exists","notExists","matches","notMatches","startsWith","endsWith"]),y=n=>n!==null&&typeof n=="object"&&"$"in n&&typeof n.$=="string"&&Object.keys(n).length===1,T=n=>n!==null&&typeof n=="object"&&"$if"in n&&"then"in n,C=n=>n!==null&&typeof n=="object"&&"$fn"in n&&typeof n.$fn=="string",b=n=>n!==null&&typeof n=="object"&&"$pipe"in n&&Array.isArray(n.$pipe),$=n=>n!==null&&typeof n=="object"&&"$arrow"in n,E=n=>n!==null&&typeof n=="object"&&"left"in n&&"op"in n&&_.has(n.op)&&!("$"in n)&&!("$if"in n)&&!("$fn"in n),h=n=>n!==null&&typeof n=="object"&&"logic"in n&&"conditions"in n,Rn=n=>E(n)||h(n),J=n=>{if(n===null)return true;let e=typeof n;if(e==="string"||e==="number"||e==="boolean"||Array.isArray(n))return true;if(e==="object"&&n!==null){let i=n,r="left"in i&&"op"in i&&_.has(i.op);return !("$"in i)&&!("$if"in i)&&!("$fn"in i)&&!("$pipe"in i)&&!("$arrow"in i)&&!r&&!("logic"in i)}return false};var U=new Map;function N(n){let e=[],i=n.length,r=0,o="";for(;r<i;){let s=n[r];if(s===".")o&&(e.push({type:"key",value:o}),o=""),r++;else if(s==="["){o&&(e.push({type:"key",value:o}),o=""),r++;let t=r;for(;r<i&&n[r]!=="]";)r++;let f=n.slice(t,r);if(r++,f==="*")e.push({type:"wildcard",value:"*"});else {let c=parseInt(f,10);e.push({type:"index",value:isNaN(c)?f:c});}}else o+=s,r++;}return o&&e.push({type:"key",value:o}),e}function X(n){return n.includes("[*]")}function G(n){let e=U.get(n);return e||(e=X(n)?jn(n):On(n),U.set(n,e),e)}function On(n){if(!n.includes(".")&&!n.includes("["))return o=>o?.[n];let e=N(n),i=e.length;if(i===2){let[o,s]=e,t=o.value,f=s.value;return c=>c?.[t]?.[f]}if(i===3){let[o,s,t]=e,f=o.value,c=s.value,l=t.value;return a=>a?.[f]?.[c]?.[l]}let r=e.map(o=>o.value);return o=>{let s=o;for(let t=0;t<i&&s!=null;t++)s=s[r[t]];return s}}function jn(n){let e=N(n),i=[];for(let r=0;r<e.length;r++)e[r].type==="wildcard"&&i.push(r);return i.length===1?Nn(e,i[0]):vn(e,i)}function Nn(n,e){let i=n.slice(0,e).map(t=>t.value),r=n.slice(e+1).map(t=>t.value),o=i.length,s=r.length;if(s===0){if(o===1){let t=i[0];return f=>f?.[t]}return t=>{let f=t;for(let c=0;c<o&&f!=null;c++)f=f[i[c]];return f}}if(s===1){let t=r[0];if(o===1){let f=i[0];return c=>{let l=c?.[f];if(Array.isArray(l))return l.map(a=>a?.[t])}}return f=>{let c=f;for(let l=0;l<o&&c!=null;l++)c=c[i[l]];if(Array.isArray(c))return c.map(l=>l?.[t])}}return t=>{let f=t;for(let c=0;c<o&&f!=null;c++)f=f[i[c]];if(Array.isArray(f))return f.map(c=>{let l=c;for(let a=0;a<s&&l!=null;a++)l=l[r[a]];return l})}}function vn(n,e){let i=[],r=0;for(let s=0;s<e.length;s++){let t=e[s],f=s===e.length-1,c=n.slice(r,t).map(l=>l.value);c.length>0&&i.push({type:"access",keys:c}),i.push({type:f?"map":"flatMap",keys:[]}),r=t+1;}let o=n.slice(r).map(s=>s.value);return s=>{let t=s;for(let f of i){if(t==null)return;if(f.type==="access")for(let c of f.keys){if(t==null)return;t=t[c];}else if(f.type==="flatMap"){if(!Array.isArray(t))return;t=t.flatMap(c=>{let l=c;return Array.isArray(l)?l:[l]});}else if(f.type==="map"){if(!Array.isArray(t))return;o.length>0&&(t=t.map(c=>{let l=c;for(let a of o){if(l==null)return;l=l[a];}return l}));}}return t}}function Dn(n,e){return G(e)(n)}function W(n){let e=n.indexOf("[*]");return e===-1?n:n.slice(0,e)}function R(n){let e=new Set;return A(n,e),Array.from(e)}function A(n,e){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let o=0;o<n.length;o++)A(n[o],e);return}if(y(n)){e.add(W(n.$));return}if(T(n)){if(typeof n.$if=="string"){let o=n.$if.startsWith("!")?n.$if.slice(1):n.$if;e.add(W(o));}else A(n.$if,e);A(n.then,e),n.else!==void 0&&A(n.else,e);return}if(b(n)){for(let o=0;o<n.$pipe.length;o++)A(n.$pipe[o],e);return}if(C(n)){if(n.args)for(let o=0;o<n.args.length;o++)A(n.args[o],e);return}if($(n)){let o=new Set;A(n.$arrow,o);let s=new Set(n.args??[]);for(let t of o){let f=t.split(".")[0].split("[")[0];s.has(f)||e.add(t);}return}if(E(n)){A(n.left,e),n.right!==void 0&&A(n.right,e);return}if(h(n)){for(let o=0;o<n.conditions.length;o++)A(n.conditions[o],e);return}let i=n,r=Object.keys(i);for(let o=0;o<r.length;o++)A(i[r[o]],e);}function In(n){return R(n).length>0}function Bn(n){return R(n).length===0}var Z;function P(n){Z=n;}function O(n,e,i,r){return Z(n,e,i,r)}function nn(n,e){return e?i=>e(n,i):G(n)}function en(n,e){return nn(n.$,e)}function tn(n,e,i,r){let o;if(typeof n.$if=="string"){let f=n.$if.startsWith("!")?n.$if.slice(1):n.$if,c=nn(f,i);o=n.$if.startsWith("!")?a=>!c(a):a=>!!c(a);}else {let f=O(n.$if,e,i,r);o=c=>!!f(c);}let s=O(n.then,e,i,r),t=n.else!==void 0?O(n.else,e,i,r):()=>{};return f=>o(f)?s(f):t(f)}function on(n,e,i,r){let o=n.$pipe;if(o.length===0)return ()=>{};if(o.length===1)return O(o[0],e,i,r);let s=O(o[0],e,i,r),t=o.slice(1).map(c=>O(c,e,i,r)),f=t.length;if(f===1){let[c]=t;return l=>{let a=s(l),p=c(l);return typeof p=="function"?p(a):p}}if(f===2){let[c,l]=t;return a=>{let p=s(a),d=c(a);return p=typeof d=="function"?d(p):d,d=l(a),typeof d=="function"?d(p):d}}if(f===3){let[c,l,a]=t;return p=>{let d=s(p),m=c(p);return d=typeof m=="function"?m(d):m,m=l(p),d=typeof m=="function"?m(d):m,m=a(p),typeof m=="function"?m(d):m}}return c=>{let l=s(c);for(let a=0;a<f;a++){let p=t[a](c);l=typeof p=="function"?p(l):p;}return l}}function rn(n,e,i,r){let o=n.$fn,s=n.args;if(s===void 0)return ()=>{let c=e[o];if(!c)throw new Error(`Function not found in scope: ${o}`);return c};let t=s.map(c=>O(c,e,i,r)),f=t.length;if(f===0)return ()=>{let c=e[o];if(!c)throw new Error(`Function not found in scope: ${o}`);return c()};if(f===1){let[c]=t;return l=>{let a=e[o];if(!a)throw new Error(`Function not found in scope: ${o}`);return a(c(l))}}if(f===2){let[c,l]=t;return a=>{let p=e[o];if(!p)throw new Error(`Function not found in scope: ${o}`);return p(c(a),l(a))}}if(f===3){let[c,l,a]=t;return p=>{let d=e[o];if(!d)throw new Error(`Function not found in scope: ${o}`);return d(c(p),l(p),a(p))}}return c=>{let l=e[o];if(!l)throw new Error(`Function not found in scope: ${o}`);return l(...t.map(a=>a(c)))}}function sn(n,e,i,r){let o=n.args??[];if(o.length===0){let t=O(n.$arrow,e,i,r);return f=>()=>t(f)}let s=O(n.$arrow,e,i,r);return t=>(...f)=>{let c={};for(let a=0;a<o.length;a++)c[o[a]]=f[a];let l={...t,...c};return s(l)}}var fn;function cn(n){fn=n;}function L(n,e,i,r){return fn(n,e,i,r)}function un(n,e,i,r){let o=L(n.left,e,i,r),s=n.right!==void 0?L(n.right,e,i,r):()=>{};switch(n.op){case "eq":return t=>o(t)===s(t);case "neq":return t=>o(t)!==s(t);case "gt":return t=>o(t)>s(t);case "gte":return t=>o(t)>=s(t);case "lt":return t=>o(t)<s(t);case "lte":return t=>o(t)<=s(t);case "in":return t=>{let f=s(t);return Array.isArray(f)&&f.includes(o(t))};case "notIn":return t=>{let f=s(t);return !Array.isArray(f)||!f.includes(o(t))};case "contains":return t=>{let f=o(t);return Array.isArray(f)&&f.includes(s(t))};case "notContains":return t=>{let f=o(t);return !Array.isArray(f)||!f.includes(s(t))};case "exists":return t=>o(t)!==void 0;case "notExists":return t=>o(t)===void 0;case "matches":return t=>{let f=o(t),c=s(t);return typeof f!="string"||typeof c!="string"?false:new RegExp(c).test(f)};case "notMatches":return t=>{let f=o(t),c=s(t);return typeof f!="string"||typeof c!="string"?true:!new RegExp(c).test(f)};case "startsWith":return t=>{let f=o(t),c=s(t);return typeof f=="string"&&typeof c=="string"&&f.startsWith(c)};case "endsWith":return t=>{let f=o(t),c=s(t);return typeof f=="string"&&typeof c=="string"&&f.endsWith(c)}}}function ln(n,e,i,r){let o=n.conditions.map(t=>L(t,e,i,r)),s=o.length;if(s===1)return t=>!!o[0](t);if(s===2){let[t,f]=o;return n.logic==="AND"?c=>!!t(c)&&!!f(c):c=>!!t(c)||!!f(c)}if(s===3){let[t,f,c]=o;return n.logic==="AND"?l=>!!t(l)&&!!f(l)&&!!c(l):l=>!!t(l)||!!f(l)||!!c(l)}return n.logic==="AND"?t=>{for(let f=0;f<s;f++)if(!o[f](t))return false;return true}:t=>{for(let f=0;f<s;f++)if(o[f](t))return true;return false}}function zn(n){return JSON.stringify(n)}function an(n,e={}){let i=e.scope??{},r=e.accessor,o=e.boundaries,s=I(n,i,r,o),t=R(n),f=zn(n);return {fn:s,deps:t,hash:f}}function I(n,e,i,r){if(n===null)return ()=>null;if(typeof n!="object")return ()=>n;if(Array.isArray(n)){let o=n.map(s=>I(s,e,i,r));return s=>o.map(t=>t(s))}if(y(n))return en(n,i);if(T(n))return tn(n,e,i,r);if(b(n))return on(n,e,i,r);if(C(n))return rn(n,e,i,r);if($(n))return sn(n,e,i,r);if(E(n))return un(n,e,i,r);if(h(n))return ln(n,e,i,r);if(r?.length){let o=n;for(let s of r)if(s.check(o))return s.handle(o)}if(J(n)){let o=n,s=Object.keys(o),t=s.map(f=>I(o[f],e,i,r));return f=>{let c={};for(let l=0;l<s.length;l++)c[s[l]]=t[l](f);return c}}return ()=>n}P(I);cn(I);function pn(n){let e=new Set;return w(n,e),e}function w(n,e){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let r of n)w(r,e);return}if(y(n))return;if(T(n)){w(n.$if,e),w(n.then,e),n.else!==void 0&&w(n.else,e);return}if(b(n)){for(let r of n.$pipe)w(r,e);return}if(C(n)){if(e.add(n.$fn),n.args)for(let r of n.args)w(r,e);return}if($(n)){w(n.$arrow,e);return}if(E(n)){n.left!==void 0&&typeof n.left=="object"&&w(n.left,e),n.right!==void 0&&typeof n.right=="object"&&w(n.right,e);return}if(h(n)){for(let r of n.conditions)w(r,e);return}let i=n;for(let r of Object.keys(i))w(i[r],e);}function dn(n){let e=new Set;for(let i of n){let r=i.indexOf("."),o=i.indexOf("["),s=i.length;r!==-1&&(s=Math.min(s,r)),o!==-1&&(s=Math.min(s,o));let t=i.slice(0,s);t&&e.add(t);}return e}var _n="data",Gn="scope",B="__",Wn={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function gn(n,e={}){let{dataParam:i=_n,scopeParam:r=Gn,noPrefixes:o=false,useAccessor:s=false,lexicalPrefix:t}=e;return g(n,i,r,o,s,t)}function g(n,e,i,r,o,s,t){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(f=>g(f,e,i,r,o,s,t)));if(y(n))return Mn(n.$,e,r,o,s,t);if(T(n))return Vn(n,e,i,r,o,s,t);if(b(n))return Kn(n.$pipe,e,i,r,o,s,t);if(C(n))return qn(n,e,i,r,o,s,t);if($(n))return Ln(n,e,i,r,o,s,t);if(E(n))return Yn(n,e,i,r,o,s,t);if(h(n))return Hn(n,e,i,r,o,s,t);if(typeof n=="object"&&"$__b"in n){let f=n.$__b;return builders.callExpression(builders.memberExpression(builders.memberExpression(builders.identifier(B),builders.identifier("b")),builders.literal(f),true,false),[builders.identifier(e)])}if(typeof n=="object"){let c=Object.entries(n).map(([l,a])=>builders.property(builders.identifier(l),g(a,e,i,r,o,s,t)));return builders.objectExpression(c)}return builders.literal(null)}var V="accessor";function q(n,e){return e?n===e||n.startsWith(e+"."):false}function K(n){let e=n.indexOf("."),i=n.indexOf("["),r=n.length;return e!==-1&&(r=Math.min(r,e)),i!==-1&&(r=Math.min(r,i)),n.slice(0,r)}function Mn(n,e,i,r,o,s){return s&&s.has(K(n))?x(n,e,true):r?q(n,o)?x(n,e,true):builders.callExpression(builders.identifier(V),[builders.literal(n),builders.identifier(e)]):n.includes("[*]")?Jn(n,e,i):x(n,e,i)}function x(n,e,i){let r=N(n);if(r.length===0)return i?builders.identifier("undefined"):builders.identifier(e);let o;if(i){let s=r[0];o=builders.identifier(s.value);for(let t=1;t<r.length;t++){let f=r[t];f.type==="key"?o=builders.memberExpression(o,builders.identifier(f.value),false,true):o=builders.memberExpression(o,builders.literal(f.value),true,true);}}else {o=builders.identifier(e);for(let s of r)s.type==="key"?o=builders.memberExpression(o,builders.identifier(s.value),false,true):o=builders.memberExpression(o,builders.literal(s.value),true,true);}return o}function Jn(n,e,i){let r=n.indexOf("[*]"),o=n.slice(0,r),s=n.slice(r+3),t;if(o?t=x(o,e,i):t=i?builders.identifier("undefined"):builders.identifier(e),!s||s==="")return t;if(s.includes("[*]"))return yn(t,s);let f="_i",c=s.startsWith(".")?s.slice(1):s,l=builders.identifier(f);if(c){let a=N(c);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(t,builders.identifier("map"),false,true),[builders.arrowFunctionExpression([builders.identifier(f)],l)])}function yn(n,e){let i=e.indexOf("[*]"),r=e.slice(0,i),o=e.slice(i+3),s="_i",t=r.startsWith(".")?r.slice(1):r,f=builders.identifier(s);if(t){let l=N(t);for(let a of l)a.type==="key"&&(f=builders.memberExpression(f,builders.identifier(a.value),false,true));}if(o.includes("[*]")){let l=yn(f,o);return builders.callExpression(builders.memberExpression(n,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([builders.identifier(s)],l)])}let c=o.startsWith(".")?o.slice(1):o;if(c){let l=N(c);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 Ln(n,e,i,r,o,s,t){let f=n.args??[],c=new Set(t);for(let p of f)c.add(p);let l=g(n.$arrow,e,i,r,o,s,c),a=f.map(p=>builders.identifier(p));return builders.arrowFunctionExpression(a,l)}function Vn(n,e,i,r,o,s,t){let f;if(typeof n.$if=="string"){let a=n.$if.startsWith("!"),p=a?n.$if.slice(1):n.$if,d;t&&t.has(K(p))?d=x(p,e,true):o?q(p,s)?d=x(p,e,true):d=builders.callExpression(builders.identifier(V),[builders.literal(p),builders.identifier(e)]):d=x(p,e,r),f=a?builders.unaryExpression("!",d):d;}else f=g(n.$if,e,i,r,o,s,t);let c=g(n.then,e,i,r,o,s,t),l=n.else!==void 0?g(n.else,e,i,r,o,s,t):builders.identifier("undefined");return builders.conditionalExpression(f,c,l)}function qn(n,e,i,r,o,s,t){let f=r?builders.identifier(n.$fn):builders.memberExpression(builders.identifier(i),builders.identifier(n.$fn),false,false);if(n.args===void 0)return f;let c=n.args.map(l=>g(l,e,i,r,o,s,t));return builders.callExpression(f,c)}function Kn(n,e,i,r,o,s,t){if(n.length===0)return builders.identifier("undefined");if(n.length===1)return g(n[0],e,i,r,o,s,t);let f=g(n[0],e,i,r,o,s,t);for(let c=1;c<n.length;c++){let l=g(n[c],e,i,r,o,s,t);f=builders.callExpression(l,[f]);}return f}function mn(n,e,i,r,o,s,t){if(y(n)){let f=n.$;return t&&t.has(K(f))?x(f,e,true):o?q(f,s)?x(f,e,true):builders.callExpression(builders.identifier(V),[builders.literal(f),builders.identifier(e)]):x(f,e,r)}return g(n,e,i,r,o,s,t)}function Yn(n,e,i,r,o,s,t){let f=mn(n.left,e,i,r,o,s,t),c=n.right!==void 0?mn(n.right,e,i,r,o,s,t):builders.literal(null),l=Wn[n.op];if(l)return builders.binaryExpression(l,f,c);switch(n.op){case "in":return builders.callExpression(builders.memberExpression(c,builders.identifier("includes")),[f]);case "notIn":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(c,builders.identifier("includes")),[f]));case "contains":return builders.callExpression(builders.memberExpression(f,builders.identifier("includes"),false,true),[c]);case "notContains":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(f,builders.identifier("includes"),false,true),[c]));case "exists":return builders.binaryExpression("!=",f,builders.literal(null));case "notExists":return builders.binaryExpression("==",f,builders.literal(null));case "matches":return builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[c]),builders.identifier("test")),[f]);case "notMatches":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[c]),builders.identifier("test")),[f]));case "startsWith":return builders.callExpression(builders.memberExpression(f,builders.identifier("startsWith"),false,true),[c]);case "endsWith":return builders.callExpression(builders.memberExpression(f,builders.identifier("endsWith"),false,true),[c]);default:return builders.binaryExpression("===",f,c)}}function Hn(n,e,i,r,o,s,t){let{logic:f,conditions:c}=n,l=f==="AND"?"&&":"||";if(c.length===0)return builders.literal(f==="AND");if(c.length===1)return g(c[0],e,i,r,o,s,t);let a=g(c[0],e,i,r,o,s,t);for(let p=1;p<c.length;p++){let d=g(c[p],e,i,r,o,s,t);a=builders.logicalExpression(l,a,d);}return a}function En(n,e,i,r,o,s=0){let t=gn(n,{noPrefixes:true,useAccessor:r,lexicalPrefix:o}),f=generate(t),c="";r?o&&(c=`const{${o}}=data??{};`):e.size>0&&(c=`const{${[...e].join(",")}}=data??{};`);let l=i.size>0?`const{${[...i].join(",")}}=scope;`:"",a=r||s>0,p="";if(a){let D=[];r&&D.push("accessor"),s>0&&D.push("b"),p=`const{${D.join(",")}}=${B};`;}let d=i.size>0,m;d&&a?m=`scope,${B}`:d?m="scope":a?m=`_,${B}`:m="";let v=`${c}return ${f}`,j;return m?j=`(function(${m}){${l}${p}return function(data){${v}}})`:j=`(function(){return function(data){${v}}})`,j}function Un(n){return JSON.stringify(n)}function S(n,e,i){if(n===null||typeof n!="object")return n;if(Array.isArray(n))return n.map(s=>S(s,e,i));if(y(n))return n;if(T(n))return {$if:typeof n.$if=="string"?n.$if:S(n.$if,e,i),then:S(n.then,e,i),...n.else!==void 0?{else:S(n.else,e,i)}:{}};if(b(n))return {$pipe:n.$pipe.map(s=>S(s,e,i))};if(C(n))return {$fn:n.$fn,...n.args!==void 0?{args:n.args.map(s=>S(s,e,i))}:{}};if($(n))return {$arrow:S(n.$arrow,e,i),...n.args?{args:n.args}:{},...n.schema?{schema:n.schema}:{}};if(E(n))return {left:S(n.left,e,i),op:n.op,...n.right!==void 0?{right:S(n.right,e,i)}:{}};if(h(n))return {logic:n.logic,conditions:n.conditions.map(s=>S(s,e,i))};let r=n;for(let s of e)if(s.check(r)){let t=i.length;return i.push(s.handle(r)),{$__b:t}}let o={};for(let s of Object.keys(r))o[s]=S(r[s],e,i);return o}function hn(n,e={}){let{scope:i={},accessor:r,returnCode:o=false,useAccessor:s=false,lexicalPrefix:t,boundaries:f}=e,c=n,l=[];if(f?.length){let F=[];c=S(n,f,F),l=F;}let a=R(c),p=dn(a),d=pn(c),m=Un(n),v=En(c,p,d,s,t,l.length);if(o)return {code:v,deps:a,hash:m,dataRoots:[...p],scopeFns:[...d]};let j={};s&&r&&(j.accessor=r),l.length>0&&(j.b=l);let D=Object.keys(j).length>0,Q;try{let F=new Function(`return ${v}`)();Q=D?F(i,j):F(i);}catch(F){throw new Error(`AST compilation failed. If this is due to CSP, use the standard compile() function instead. Error: ${F instanceof Error?F.message:String(F)}`)}return {fn:Q,deps:a,hash:m}}function Tn(n,e){return M(n,e)}function M(n,e){if(n===null)return null;if(typeof n!="object")return n;if(Array.isArray(n))return n.map(s=>M(s,e));let i=n,r=Object.keys(i);for(let s of r)if(s in e){let t=e[s](i);if(typeof t=="object"&&t!==null&&s in t)throw new Error(`Transform "${s}" returned object with same key \u2014 infinite loop`);return M(t,e)}let o={};for(let s of r)o[s]=M(i[s],e);return o}var z=class{constructor(e=1e3){this.cache=new Map,this._maxSize=e;}getOrCompile(e,i){let r=JSON.stringify(e),o=this.cache.get(r);if(o)return this.cache.delete(r),this.cache.set(r,o),o;let s=i();if(this.cache.size>=this._maxSize){let t=this.cache.keys().next().value;t&&this.cache.delete(t);}return this.cache.set(r,s),s}has(e){return this.cache.has(JSON.stringify(e))}delete(e){return this.cache.delete(JSON.stringify(e))}clear(){this.cache.clear();}get size(){return this.cache.size}get maxSize(){return this._maxSize}set maxSize(e){for(this._maxSize=e;this.cache.size>this._maxSize;){let i=this.cache.keys().next().value;i&&this.cache.delete(i);}}};var Y=class{constructor(e={}){this.scope=e.scope??{},this.accessor=e.accessor,this.boundaries=e.boundaries,this.cacheClosures=new z(e.cacheSize??1e3),this.cacheJIT=new z(e.cacheSize??1e3);}compile(e){return this.cacheClosures.getOrCompile(e,()=>an(e,{scope:this.scope,accessor:this.accessor,boundaries:this.boundaries}))}jit(e,i){return this.cacheJIT.getOrCompile(e,()=>hn(e,{scope:this.scope,accessor:this.accessor,useAccessor:i?.useAccessor,lexicalPrefix:i?.lexicalPrefix,boundaries:this.boundaries}))}evaluate(e,i){return this.compile(e).fn(i)}evaluateJIT(e,i,r){return this.jit(e,r).fn(i)}normalize(e,i){return Tn(e,i)}extractDeps(e){return R(e)}get cacheSize(){return {closures:this.cacheClosures.size,jit:this.cacheJIT.size}}clearCache(){this.cacheClosures.clear(),this.cacheJIT.clear();}getScope(){return this.scope}};var kn={};Fn(kn,{$:()=>Cn,$arrow:()=>wn,$call:()=>Sn,$cond:()=>An,$fn:()=>bn,$if:()=>Pn,$pipe:()=>$n,arrow:()=>te,call:()=>ie,cond:()=>ee,fn:()=>Zn,pipe:()=>ne,ref:()=>Xn});function Cn(n){return {$:n}}var Xn=Cn;function bn(n,e){return e===void 0?{$fn:n}:{$fn:n,args:e}}var Zn=bn;function Pn(n,e,i){return i===void 0?{$if:n,then:e}:{$if:n,then:e,else:i}}function $n(...n){return {$pipe:n}}var ne=$n;function An(n,e,i){return i===void 0?{left:n,op:e}:{left:n,op:e,right:i}}var ee=An;function wn(n,e){return e===void 0||e.length===0?{$arrow:n}:{$arrow:n,args:e}}var te=wn;function Sn(n,e=[]){return {$fn:n,args:e}}var ie=Sn;function H(n,e="root",i={}){let r=[];return k(n,e,r,i),{valid:r.length===0,errors:r}}function k(n,e,i,r){if(n===null||typeof n!="object")return;if(Array.isArray(n)){for(let t=0;t<n.length;t++)k(n[t],`${e}[${t}]`,i,r);return}if(y(n)){(!n.$||typeof n.$!="string")&&i.push(`${e}: invalid reference, $ must be non-empty string`);return}if(T(n)){typeof n.$if=="string"?(n.$if.startsWith("!")?n.$if.slice(1):n.$if)||i.push(`${e}.$if: empty path in string shorthand`):k(n.$if,`${e}.$if`,i,r),k(n.then,`${e}.then`,i,r),n.else!==void 0&&k(n.else,`${e}.else`,i,r);return}if(b(n)){if(!Array.isArray(n.$pipe)){i.push(`${e}.$pipe: must be an array`);return}if(n.$pipe.length===0){i.push(`${e}.$pipe: must have at least one element`);return}for(let t=0;t<n.$pipe.length;t++)k(n.$pipe[t],`${e}.$pipe[${t}]`,i,r);return}if(C(n)){if(!n.$fn||typeof n.$fn!="string"){i.push(`${e}: invalid function, $fn must be non-empty string`);return}if(r.scope&&!(n.$fn in r.scope)&&i.push(`${e}: function "${n.$fn}" not found in scope`),n.args!==void 0)if(!Array.isArray(n.args))i.push(`${e}.args: must be an array`);else for(let t=0;t<n.args.length;t++)k(n.args[t],`${e}.args[${t}]`,i,r);return}if($(n)){if(k(n.$arrow,`${e}.$arrow`,i,r),n.args!==void 0)if(!Array.isArray(n.args))i.push(`${e}.args: must be an array of strings`);else for(let t of n.args)(typeof t!="string"||!t)&&i.push(`${e}.args: each arg must be a non-empty string`);return}if(E(n)){_.has(n.op)||i.push(`${e}: invalid operator "${n.op}"`),k(n.left,`${e}.left`,i,r),n.right!==void 0&&k(n.right,`${e}.right`,i,r);return}if(h(n)){if(n.logic!=="AND"&&n.logic!=="OR"&&i.push(`${e}: invalid logic "${n.logic}", must be "AND" or "OR"`),!Array.isArray(n.conditions)){i.push(`${e}.conditions: must be an array`);return}for(let t=0;t<n.conditions.length;t++)k(n.conditions[t],`${e}.conditions[${t}]`,i,r);return}if(r.boundaries?.length){let t=n;for(let f of r.boundaries)if(f.check(t))return}let o=n,s=Object.keys(o);for(let t=0;t<s.length;t++){let f=s[t];k(o[f],`${e}.${f}`,i,r);}}function oe(n,e={}){let i=H(n,"root",e);if(!i.valid)throw new Error(`Invalid expression: ${i.errors.join("; ")}`)}function re(n,e={}){return H(n,"root",e).valid}var Ve="3.0.0";export{Y as ExpressionCompiler,Ve as VERSION,oe as assertValid,kn as builders,G as compilePath,R as extractDeps,Dn as get,In as hasDeps,X as hasWildcard,$ as isArrow,E as isCondition,Rn as isConditionExpr,h as isConditionGroup,T as isConditional,C as isFn,J as isLiteral,b as isPipe,Bn as isPure,y as isRef,re as isValid,W as normalizePath,H as validate};
|
|
1
|
+
import {generate,builders}from'omni-ast';var be=Object.defineProperty;var Te=(e,n)=>{for(var t in n)be(e,t,{get:n[t],enumerable:true});};function j(e,n,t){let i=e;return Object.defineProperty(i,"deps",{value:n,enumerable:true,configurable:true}),Object.defineProperty(i,"hash",{value:t,enumerable:true,configurable:true}),i}var K=Symbol("$");function P(e){return e!==null&&typeof e=="object"&&e[K]===true}function y(e,n){if(e===null||typeof e!="object")return n.rawPrimitive(e);if(P(e))return Ae(e,n);if(Array.isArray(e)){let o=e.map(r=>y(r,n));return n.rawArray(e,o)}let t=e,i=Object.keys(t),s=new Array(i.length);for(let o=0;o<i.length;o++){let r=i[o];s[o]=[r,y(t[r],n)];}return n.rawObject(t,s)}function Ae(e,n){switch(e.t){case "d":return n.data(e);case "a":return n.arg(e);case "x":return n.accessor(e);case "c":{let t=e,i=t.a.map(s=>y(s,n));return n.call(t,i)}case "r":return n.ref(e);case "ch":{let t=e,i=t.a.map(s=>y(s,n));return n.callH(t,i)}case "rh":return n.refH(e);case "?":{let t=e;return n.cond(t,y(t.test,n),y(t.then,n),y(t.else,n))}case "|":{let t=e;return n.pipe(t,y(t.head,n),t.steps.map(i=>y(i,n)))}case "=>":{let t=e;return n.arrow(t,y(t.body,n))}case "!":{let t=e;return n.not(t,y(t.v,n))}case "cmp":{let t=e;return n.compare(t,y(t.l,n),y(t.r,n))}case "lg":{let t=e;return n.logic(t,t.c.map(i=>y(i,n)))}case "v":return n.literal(e);case "s":return n.static_(e);case "b":return n.boundary(e);default:throw new Error(`Unknown IR node type: ${e.t}`)}}function ne(e,n){return {data:()=>e,arg:()=>e,accessor:()=>e,call:()=>e,ref:()=>e,callH:()=>e,refH:()=>e,cond:()=>e,pipe:()=>e,arrow:()=>e,not:()=>e,compare:()=>e,logic:()=>e,literal:()=>e,static_:()=>e,boundary:()=>e,rawPrimitive:()=>e,rawObject:()=>e,rawArray:()=>e,...n}}var te=new Map;function S(e){let n=[],t=e.length,i=0,s="";for(;i<t;){let o=e[i];if(o===".")s&&(n.push({type:"key",value:s}),s=""),i++;else if(o==="["){s&&(n.push({type:"key",value:s}),s=""),i++;let r=i;for(;i<t&&e[i]!=="]";)i++;let a=e.slice(r,i);if(i++,a==="*")n.push({type:"wildcard",value:"*"});else {let l=parseInt(a,10);n.push({type:"index",value:isNaN(l)?a:l});}}else s+=o,i++;}return s&&n.push({type:"key",value:s}),n}function N(e){return e.includes("[*]")}function H(e){let n=te.get(e);return n||(n=N(e)?Ie(e):we(e),te.set(e,n),n)}function we(e){if(!e.includes(".")&&!e.includes("["))return s=>s?.[e];let n=S(e),t=n.length;if(t===2){let[s,o]=n,r=s.value,a=o.value;return l=>l?.[r]?.[a]}if(t===3){let[s,o,r]=n,a=s.value,l=o.value,c=r.value;return u=>u?.[a]?.[l]?.[c]}let i=n.map(s=>s.value);return s=>{let o=s;for(let r=0;r<t&&o!=null;r++)o=o[i[r]];return o}}function Ie(e){let n=S(e),t=[];for(let i=0;i<n.length;i++)n[i].type==="wildcard"&&t.push(i);return t.length===1?Ee(n,t[0]):$e(n,t)}function Ee(e,n){let t=e.slice(0,n).map(r=>r.value),i=e.slice(n+1).map(r=>r.value),s=t.length,o=i.length;if(o===0){if(s===1){let r=t[0];return a=>a?.[r]}return r=>{let a=r;for(let l=0;l<s&&a!=null;l++)a=a[t[l]];return a}}if(o===1){let r=i[0];if(s===1){let a=t[0];return l=>{let c=l?.[a];if(Array.isArray(c))return c.map(u=>u?.[r])}}return a=>{let l=a;for(let c=0;c<s&&l!=null;c++)l=l[t[c]];if(Array.isArray(l))return l.map(c=>c?.[r])}}return r=>{let a=r;for(let l=0;l<s&&a!=null;l++)a=a[t[l]];if(Array.isArray(a))return a.map(l=>{let c=l;for(let u=0;u<o&&c!=null;u++)c=c[i[u]];return c})}}function $e(e,n){let t=[],i=0;for(let o=0;o<n.length;o++){let r=n[o],a=o===n.length-1,l=e.slice(i,r).map(c=>c.value);l.length>0&&t.push({type:"access",keys:l}),t.push({type:a?"map":"flatMap",keys:[]}),i=r+1;}let s=e.slice(i).map(o=>o.value);return o=>{let r=o;for(let a of t){if(r==null)return;if(a.type==="access")for(let l of a.keys){if(r==null)return;r=r[l];}else if(a.type==="flatMap"){if(!Array.isArray(r))return;r=r.flatMap(l=>{let c=l;return Array.isArray(c)?c:[c]});}else if(a.type==="map"){if(!Array.isArray(r))return;s.length>0&&(r=r.map(l=>{let c=l;for(let u of s){if(c==null)return;c=c[u];}return c}));}}return r}}function Fe(e,n){return H(n)(e)}function A(e){let n=e.indexOf("[*]");return n===-1?e:e.slice(0,n)}function re(e){let{scope:n,accessor:t,handlers:i,boundaryFns:s}=e;return {data(o){return H(o.p)},arg(o){return H(o.p)},accessor(o){let r=t,a=o.p;return ()=>r(a)},call(o,r){let a=n[o.n];if(!a){let c=o.n;return ()=>{throw new Error(`Function not found in scope: ${c}`)}}let l=r.length;if(l===0)return ()=>a();if(l===1){let[c]=r;return u=>a(c(u))}if(l===2){let[c,u]=r;return f=>a(c(f),u(f))}if(l===3){let[c,u,f]=r;return d=>a(c(d),u(d),f(d))}return c=>a(...r.map(u=>u(c)))},ref(o){let r=n[o.n];if(!r){let a=o.n;return ()=>{throw new Error(`Function not found in scope: ${a}`)}}return ()=>r},callH(o,r){let a=i?.[o.ns]?.[o.m];if(!a)throw new Error(`Handler not found: ${o.ns}:${o.m}`);let l=r.length;if(l===0)return ()=>a();if(l===1){let[c]=r;return u=>a(c(u))}if(l===2){let[c,u]=r;return f=>a(c(f),u(f))}if(l===3){let[c,u,f]=r;return d=>a(c(d),u(d),f(d))}return c=>a(...r.map(u=>u(c)))},refH(o){let r=i?.[o.ns]?.[o.m];if(!r)throw new Error(`Handler not found: ${o.ns}:${o.m}`);return ()=>r},cond(o,r,a,l){return c=>r(c)?a(c):l(c)},pipe(o,r,a){let l=a.length;if(l===1){let[c]=a;return u=>{let f=r(u),d=c(u);return typeof d=="function"?d(f):d}}if(l===2){let[c,u]=a;return f=>{let d=r(f),m=c(f);return d=typeof m=="function"?m(d):m,m=u(f),typeof m=="function"?m(d):m}}if(l===3){let[c,u,f]=a;return d=>{let m=r(d),h=c(d);return m=typeof h=="function"?h(m):h,h=u(d),m=typeof h=="function"?h(m):h,h=f(d),typeof h=="function"?h(m):h}}return c=>{let u=r(c);for(let f=0;f<l;f++){let d=a[f](c);u=typeof d=="function"?d(u):d;}return u}},arrow(o,r){let a=o.params;if(a.length===0)return c=>()=>r(c);let l=a.length;return c=>(...u)=>{let f={...c};for(let d=0;d<l;d++)f[a[d]]=u[d];return r(f)}},not(o,r){return a=>!r(a)},compare(o,r,a){switch(o.op){case "eq":return l=>r(l)===a(l);case "neq":return l=>r(l)!==a(l);case "gt":return l=>r(l)>a(l);case "gte":return l=>r(l)>=a(l);case "lt":return l=>r(l)<a(l);case "lte":return l=>r(l)<=a(l);case "in":return l=>{let c=a(l);return Array.isArray(c)&&c.includes(r(l))};case "notIn":return l=>{let c=a(l);return !Array.isArray(c)||!c.includes(r(l))};case "contains":return l=>{let c=r(l);return Array.isArray(c)&&c.includes(a(l))};case "notContains":return l=>{let c=r(l);return !Array.isArray(c)||!c.includes(a(l))};case "exists":return l=>r(l)!==void 0;case "notExists":return l=>r(l)===void 0;case "matches":return l=>{let c=r(l),u=a(l);return typeof c!="string"||typeof u!="string"?false:new RegExp(u).test(c)};case "notMatches":return l=>{let c=r(l),u=a(l);return typeof c!="string"||typeof u!="string"?true:!new RegExp(u).test(c)};case "startsWith":return l=>{let c=r(l),u=a(l);return typeof c=="string"&&typeof u=="string"&&c.startsWith(u)};case "endsWith":return l=>{let c=r(l),u=a(l);return typeof c=="string"&&typeof u=="string"&&c.endsWith(u)};default:return l=>r(l)===a(l)}},logic(o,r){let a=r.length;if(a===0)return ()=>o.op==="AND";if(a===1)return l=>!!r[0](l);if(a===2){let[l,c]=r;return o.op==="AND"?u=>!!l(u)&&!!c(u):u=>!!l(u)||!!c(u)}if(a===3){let[l,c,u]=r;return o.op==="AND"?f=>!!l(f)&&!!c(f)&&!!u(f):f=>!!l(f)||!!c(f)||!!u(f)}return o.op==="AND"?l=>{for(let c=0;c<a;c++)if(!r[c](l))return false;return true}:l=>{for(let c=0;c<a;c++)if(r[c](l))return true;return false}},literal(o){let r=o.v;return ()=>r},static_(o){let r=o.v;return ()=>r},boundary(o){return s[o.i]},rawPrimitive(o){return ()=>o},rawObject(o,r){let a=r.length;return l=>{let c={};for(let u=0;u<a;u++)c[r[u][0]]=r[u][1](l);return c}},rawArray(o,r){return a=>r.map(l=>l(a))}}}function ie(e,n,t,i){return {deps:n,hash:i,bind:o=>{let r=re({scope:o?.scope??{},accessor:o?.accessor,handlers:o?.handlers,boundaryFns:t}),a=y(e,r);return j(a,n,i)}}}var Se="data",ke="accessor",Oe={eq:"===",neq:"!==",gt:">",gte:">=",lt:"<",lte:"<="};function q(e){let n=S(e);if(n.length===0)return builders.identifier("undefined");let t=n[0],i=builders.identifier(t.value);for(let s=1;s<n.length;s++){let o=n[s];o.type==="key"?i=builders.memberExpression(i,builders.identifier(o.value),false,true):i=builders.memberExpression(i,builders.literal(o.value),true,true);}return i}function De(e){let n=e.indexOf("[*]"),t=e.slice(0,n),i=e.slice(n+3),s;if(t)s=q(t);else return builders.identifier("undefined");if(!i||i==="")return s;if(i.includes("[*]"))return oe(s,i);let o="_i",r=i.startsWith(".")?i.slice(1):i,a=builders.identifier(o);if(r){let l=S(r);for(let c of l)c.type==="key"?a=builders.memberExpression(a,builders.identifier(c.value),false,true):a=builders.memberExpression(a,builders.literal(c.value),true,true);}return builders.callExpression(builders.memberExpression(s,builders.identifier("map"),false,true),[builders.arrowFunctionExpression([builders.identifier(o)],a)])}function oe(e,n){let t=n.indexOf("[*]"),i=n.slice(0,t),s=n.slice(t+3),o="_i",r=i.startsWith(".")?i.slice(1):i,a=builders.identifier(o);if(r){let c=S(r);for(let u of c)u.type==="key"&&(a=builders.memberExpression(a,builders.identifier(u.value),false,true));}if(s.includes("[*]")){let c=oe(a,s);return builders.callExpression(builders.memberExpression(e,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([builders.identifier(o)],c)])}let l=s.startsWith(".")?s.slice(1):s;if(l){let c=S(l);for(let u of c)u.type==="key"&&(a=builders.memberExpression(a,builders.identifier(u.value),false,true));}return builders.callExpression(builders.memberExpression(e,builders.identifier("flatMap"),false,true),[builders.arrowFunctionExpression([builders.identifier(o)],a)])}function z(e){if(e===void 0)return builders.identifier("undefined");if(e===null)return builders.literal(null);if(typeof e!="object")return builders.literal(e);if(Array.isArray(e))return builders.arrayExpression(e.map(z));let t=Object.entries(e).map(([i,s])=>builders.property(builders.identifier(i),z(s)));return builders.objectExpression(t)}function se(){return {data(e){return e.w?De(e.p):q(e.p)},arg(e){return q(e.p)},accessor(e){return builders.callExpression(builders.identifier(ke),[builders.literal(e.p)])},call(e,n){let t=builders.identifier(e.n);return builders.callExpression(t,n)},ref(e){return builders.identifier(e.n)},callH(e,n){return builders.callExpression(builders.identifier(`h_${e.ns}_${e.m}`),n)},refH(e){return builders.identifier(`h_${e.ns}_${e.m}`)},cond(e,n,t,i){return builders.conditionalExpression(n,t,i)},pipe(e,n,t){let i=n;for(let s of t)i=builders.callExpression(s,[i]);return i},arrow(e,n){let t=e.params.map(i=>builders.identifier(i));return builders.arrowFunctionExpression(t,n)},not(e,n){return builders.unaryExpression("!",n)},compare(e,n,t){let i=Oe[e.op];if(i)return builders.binaryExpression(i,n,t);switch(e.op){case "in":return builders.callExpression(builders.memberExpression(t,builders.identifier("includes")),[n]);case "notIn":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(t,builders.identifier("includes")),[n]));case "contains":return builders.callExpression(builders.memberExpression(n,builders.identifier("includes"),false,true),[t]);case "notContains":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(n,builders.identifier("includes"),false,true),[t]));case "exists":return builders.binaryExpression("!=",n,builders.literal(null));case "notExists":return builders.binaryExpression("==",n,builders.literal(null));case "matches":return builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[t]),builders.identifier("test")),[n]);case "notMatches":return builders.unaryExpression("!",builders.callExpression(builders.memberExpression(builders.newExpression(builders.identifier("RegExp"),[t]),builders.identifier("test")),[n]));case "startsWith":return builders.callExpression(builders.memberExpression(n,builders.identifier("startsWith"),false,true),[t]);case "endsWith":return builders.callExpression(builders.memberExpression(n,builders.identifier("endsWith"),false,true),[t]);default:return builders.binaryExpression("===",n,t)}},logic(e,n){let t=e.op==="AND"?"&&":"||";if(n.length===0)return builders.literal(e.op==="AND");if(n.length===1)return n[0];let i=n[0];for(let s=1;s<n.length;s++)i=builders.logicalExpression(t,i,n[s]);return i},literal(e){return z(e.v)},static_(e){return z(e.v)},boundary(e){return builders.callExpression(builders.identifier(`b${e.i}`),[builders.identifier(Se)])},rawPrimitive(e){return e===void 0?builders.identifier("undefined"):e===null?builders.literal(null):builders.literal(e)},rawObject(e,n){let t=n.map(([i,s])=>builders.property(builders.identifier(i),s));return builders.objectExpression(t)},rawArray(e,n){return builders.arrayExpression(n)}}}function je(e){let n=e.indexOf("."),t=e.indexOf("["),i=e.length;return n!==-1&&(i=Math.min(i,n)),t!==-1&&(i=Math.min(i,t)),e.slice(0,i)}function ae(e,n){let t=new Set,i=new Set,s=new Set,o=false;return y(e,ne(void 0,{data(r){let a=je(r.p);a&&i.add(a);},accessor(){o=true;},call(r){t.add(r.n);},ref(r){t.add(r.n);},callH(r){s.add(`${r.ns}:${r.m}`);},refH(r){s.add(`${r.ns}:${r.m}`);}})),{scopeFns:t,dataRoots:i,hasAccessor:o,handlerRefs:s,boundaryCount:n}}function le(e){let n=[],t=[];for(let i of e.scopeFns)n.push({kind:"scope",name:i}),t.push(i);e.hasAccessor&&(n.push({kind:"accessor"}),t.push("accessor"));for(let i of e.handlerRefs){let[s,o]=i.split(":");n.push({kind:"handler",ns:s,m:o}),t.push(`h_${s}_${o}`);}for(let i=0;i<e.boundaryCount;i++)n.push({kind:"boundary",index:i}),t.push(`b${i}`);return {params:n,paramNames:t}}function ce(e,n,t){let i=generate(e),s="";n.dataRoots.size>0&&(s=`const{${[...n.dataRoots].join(",")}}=data??{};`);let o=`${s}return ${i}`;return t.length>0?`(function(${t.join(",")}){return function(data){${o}}})`:`(function(){return function(data){${o}}})`}function Ne(e,n,t){let i=new Array(e.length);for(let s=0;s<e.length;s++){let o=e[s];switch(o.kind){case "scope":i[s]=n.scope?.[o.name];break;case "accessor":i[s]=n.accessor;break;case "handler":i[s]=n.handlers?.[o.ns]?.[o.m];break;case "boundary":i[s]=t[o.index];break}}return i}function U(e,n,t,i){let{hash:s,returnCode:o=false}=i,r=ae(e,t.length),a=y(e,se()),{params:l,paramNames:c}=le(r),u=ce(a,r,c);if(o)return {code:u,deps:n,hash:s,dataRoots:[...r.dataRoots],scopeFns:[...r.scopeFns],paramNames:c};let f;try{f=new Function(`return ${u}`)();}catch(m){throw new Error(`JIT compilation failed. If this is due to CSP, use the standard compile() function instead. Error: ${m instanceof Error?m.message:String(m)}`)}return {deps:n,hash:s,bind:m=>{let h=Ne(l,m??{},t),J=f(...h);return j(J,n,s)}}}var V=new Set(["eq","neq","gt","gte","lt","lte","in","notIn","contains","notContains","exists","notExists","matches","notMatches","startsWith","endsWith"]),w=e=>e!==null&&typeof e=="object"&&"$"in e&&typeof e.$=="string"&&Object.keys(e).length===1,I=e=>e!==null&&typeof e=="object"&&"$if"in e&&"then"in e,E=e=>e!==null&&typeof e=="object"&&"$fn"in e&&typeof e.$fn=="string",$=e=>e!==null&&typeof e=="object"&&"$pipe"in e&&Array.isArray(e.$pipe),F=e=>e!==null&&typeof e=="object"&&"$arrow"in e,b=e=>e!==null&&typeof e=="object"&&"left"in e&&"op"in e&&V.has(e.op)&&!("$"in e)&&!("$if"in e)&&!("$fn"in e),T=e=>e!==null&&typeof e=="object"&&"logic"in e&&"conditions"in e,He=e=>b(e)||T(e),Be=e=>e!==null&&typeof e=="object"&&(w(e)||E(e)||I(e)||$(e)||F(e)||b(e)||T(e)),ze=e=>{if(e===null)return true;let n=typeof e;if(n==="string"||n==="number"||n==="boolean"||Array.isArray(e))return true;if(n==="object"&&e!==null){let t=e,i="left"in t&&"op"in t&&V.has(t.op);return !("$"in t)&&!("$if"in t)&&!("$fn"in t)&&!("$pipe"in t)&&!("$arrow"in t)&&!i&&!("logic"in t)}return false};function v(e,n){return _(e,n)}function _(e,n){if(e===null)return null;if(typeof e!="object")return e;if(Array.isArray(e))return e.map(o=>_(o,n));let t=e,i=Object.keys(t);for(let o of i)if(o in n){let r=n[o](t);if(typeof r=="object"&&r!==null&&o in r)throw new Error(`Transform "${o}" returned object with same key \u2014 infinite loop`);return _(r,n)}let s={};for(let o of i)s[o]=_(t[o],n);return s}function Ve(e){let n=e.indexOf("."),t=e.indexOf("["),i=e.length;return n!==-1&&(i=Math.min(i,n)),t!==-1&&(i=Math.min(i,t)),e.slice(0,i)}function g(e,n,t){return e[K]=true,t&&n&&(e.loc=n),e}function Q(e,n={}){let t=n.transforms?v(e,n.transforms):e,i=new Set,s=[],o=n.trackLocations===true;return {ir:C(t,n,new Set,i,s,o,o?"root":void 0),deps:Array.from(i),boundaryFns:s}}function C(e,n,t,i,s,o,r){if(e===null||typeof e!="object")return e;if(Array.isArray(e))return Ue(e,n,t,i,s,o,r);let a=e;if(n.boundaries){for(let l of n.boundaries)if(l.check(a)){let c=l.handle(a),u=s.length;return s.push(c),g({t:"b",i:u},r,o)}}return w(e)?pe(e.$,n,t,i,o,r):I(e)?ve(e,n,t,i,s,o,r):$(e)?We(e,n,t,i,s,o,r):E(e)?Me(e,n,t,i,s,o,r):F(e)?Ge(e,n,t,i,s,o,r):b(e)?Je(e,n,t,i,s,o,r):T(e)?Ke(e,n,t,i,s,o,r):qe(a,n,t,i,s,o,r)}function _e(e,n){return n?e===n||e.startsWith(n+"."):false}function pe(e,n,t,i,s,o){let r=Ve(e);if(t.has(r))return g({t:"a",n:r,p:e},o,s);if(n.accessor){if(_e(e,n.lexicalPrefix)){i.add(A(e));let l={t:"d",p:e};return N(e)&&(l.w=true),g(l,o,s)}return i.add(A(e)),g({t:"x",p:e},o,s)}i.add(A(e));let a={t:"d",p:e};return N(e)&&(a.w=true),g(a,o,s)}function ve(e,n,t,i,s,o,r){let a;if(typeof e.$if=="string"){let u=e.$if.startsWith("!"),f=u?e.$if.slice(1):e.$if,d=pe(f,n,t,i,o,o?`${r}.$if`:void 0);a=u?g({t:"!",v:d},r,o):d;}else a=C(e.$if,n,t,i,s,o,o?`${r}.$if`:void 0);let l=C(e.then,n,t,i,s,o,o?`${r}.then`:void 0),c=e.else!==void 0?C(e.else,n,t,i,s,o,o?`${r}.else`:void 0):void 0;return g({t:"?",test:a,then:l,else:c},r,o)}function We(e,n,t,i,s,o,r){let a=e.$pipe;if(a.length===0)return;if(a.length===1)return C(a[0],n,t,i,s,o,o?`${r}.$pipe[0]`:void 0);let l=C(a[0],n,t,i,s,o,o?`${r}.$pipe[0]`:void 0),c=[];for(let u=1;u<a.length;u++)c.push(C(a[u],n,t,i,s,o,o?`${r}.$pipe[${u}]`:void 0));return g({t:"|",head:l,steps:c},r,o)}function Me(e,n,t,i,s,o,r){let a=e.$fn,l=a.indexOf(":"),c=e.args!==void 0;if(l!==-1){let f=a.slice(0,l),d=a.slice(l+1);if(!c)return g({t:"rh",ns:f,m:d},r,o);let m=e.args.map((h,J)=>C(h,n,t,i,s,o,o?`${r}.$fn.args[${J}]`:void 0));return g({t:"ch",ns:f,m:d,a:m},r,o)}if(!c)return g({t:"r",n:a},r,o);let u=e.args.map((f,d)=>C(f,n,t,i,s,o,o?`${r}.$fn.args[${d}]`:void 0));return g({t:"c",n:a,a:u},r,o)}function Ge(e,n,t,i,s,o,r){let a=e.args??[],l;if(a.length===0)l=t;else {l=new Set(t);for(let u of a)l.add(u);}let c=C(e.$arrow,n,l,i,s,o,o?`${r}.$arrow`:void 0);return g({t:"=>",params:a,body:c},r,o)}function Je(e,n,t,i,s,o,r){let a=C(e.left,n,t,i,s,o,o?`${r}.left`:void 0),l=e.right!==void 0?C(e.right,n,t,i,s,o,o?`${r}.right`:void 0):void 0;return g({t:"cmp",op:e.op,l:a,r:l},r,o)}function Ke(e,n,t,i,s,o,r){let a=e.conditions.map((l,c)=>C(l,n,t,i,s,o,o?`${r}.conditions[${c}]`:void 0));return g({t:"lg",op:e.logic,c:a},r,o)}function qe(e,n,t,i,s,o,r){let a=Object.keys(e);if(a.length===0)return g({t:"s",v:e},r,o);let l=false,c={};for(let u of a){let f=C(e[u],n,t,i,s,o,o?`${r}.${u}`:void 0);c[u]=f,l||(l=ue(f));}return l?c:g({t:"s",v:e},r,o)}function Ue(e,n,t,i,s,o,r){if(e.length===0)return g({t:"s",v:e},r,o);let a=false,l=[];for(let c=0;c<e.length;c++){let u=C(e[c],n,t,i,s,o,o?`${r}[${c}]`:void 0);l[c]=u,a||(a=ue(u));}return a?l:g({t:"s",v:e},r,o)}function ue(e){return e===null||typeof e!="object"?false:P(e)?true:Y(e)}function Y(e){if(P(e))return true;if(Array.isArray(e)){for(let n=0;n<e.length;n++)if(Y(e[n]))return true;return false}if(typeof e=="object"&&e!==null){let n=Object.keys(e);for(let t=0;t<n.length;t++)if(Y(e[n[t]]))return true}return false}function B(e){let n=new Set;return R(e,n),Array.from(n)}function R(e,n){if(e===null||typeof e!="object")return;if(Array.isArray(e)){for(let s=0;s<e.length;s++)R(e[s],n);return}if(w(e)){n.add(A(e.$));return}if(I(e)){if(typeof e.$if=="string"){let s=e.$if.startsWith("!")?e.$if.slice(1):e.$if;n.add(A(s));}else R(e.$if,n);R(e.then,n),e.else!==void 0&&R(e.else,n);return}if($(e)){for(let s=0;s<e.$pipe.length;s++)R(e.$pipe[s],n);return}if(E(e)){if(e.args)for(let s=0;s<e.args.length;s++)R(e.args[s],n);return}if(F(e)){let s=new Set;R(e.$arrow,s);let o=new Set(e.args??[]);for(let r of s){let a=r.split(".")[0].split("[")[0];o.has(a)||n.add(r);}return}if(b(e)){R(e.left,n),e.right!==void 0&&R(e.right,n);return}if(T(e)){for(let s=0;s<e.conditions.length;s++)R(e.conditions[s],n);return}let t=e,i=Object.keys(t);for(let s=0;s<i.length;s++)R(t[i[s]],n);}function Ye(e){return B(e).length>0}function Qe(e){return B(e).length===0}var k=class{constructor(n=1e3){this.cache=new Map,this._maxSize=n;}getOrCompile(n,t){let i=this.cache.get(n);if(i!==void 0)return this.cache.delete(n),this.cache.set(n,i),i;let s=t();if(this.cache.size>=this._maxSize){let o=this.cache.keys().next().value;o&&this.cache.delete(o);}return this.cache.set(n,s),s}has(n){return this.cache.has(n)}delete(n){return this.cache.delete(n)}clear(){this.cache.clear();}get size(){return this.cache.size}get maxSize(){return this._maxSize}set maxSize(n){for(this._maxSize=n;this.cache.size>this._maxSize;){let t=this.cache.keys().next().value;t&&this.cache.delete(t);}}},X=class{constructor(n=1e3){this.closures=new k(n),this.jit=new k(n);}getOrCompile(n,t,i){return (t==="closures"?this.closures:this.jit).getOrCompile(n,i)}get size(){return {closures:this.closures.size,jit:this.jit.size}}clear(){this.closures.clear(),this.jit.clear();}};function Z(e){return JSON.stringify(e)}var L=class{constructor(n={}){this.scope=n.scope??{},this.accessor=n.accessor,this.boundaries=n.boundaries,this.compileCache=n.compileCache,this.cacheClosures=new k(n.cacheSize??1e3),this.cacheJIT=new k(n.cacheSize??1e3),n.handlers&&(this.wrappedHandlers=this.wrapHandlers(n.handlers));}compile(n,t){let i=Z(n),s=t?.useAccessor??!!this.accessor,o=this.compileCacheKey(i,s);return this.cacheClosures.getOrCompile(o,()=>{let r=this.getArtifact(n,i,s,"closures"),a=this.defaultCtx(s);return {deps:r.deps,hash:r.hash,bind:l=>r.bind(l??a)}})}jit(n,t){let i=Z(n),s=t?.useAccessor??false,o=this.compileCacheKey(i,s,t?.lexicalPrefix);return this.cacheJIT.getOrCompile(o,()=>{let r=this.getArtifact(n,i,s,"jit",t?.lexicalPrefix),a=this.defaultCtx(s);return {deps:r.deps,hash:r.hash,bind:l=>r.bind(l??a)}})}jitCode(n,t){let s=t?.useAccessor??false?this.accessor??(()=>{}):void 0,{ir:o,deps:r,boundaryFns:a}=Q(n,{accessor:s,boundaries:this.boundaries,handlers:this.wrappedHandlers,lexicalPrefix:t?.lexicalPrefix});return U(o,r,a,{hash:JSON.stringify(n),returnCode:true})}eval(n,t,i){return i?.mode==="jit"?this.jit(n,{useAccessor:i?.useAccessor}).bind()(t):this.compile(n,{useAccessor:i?.useAccessor}).bind()(t)}wrapHandlers(n){let t={},i={};for(let s of Object.keys(n)){i[s]={};for(let o of Object.keys(n[s]))i[s][o]=n[s][o].bind(t);}return t.accessor=this.accessor,t.handlers=i,t.compiler=this,t.scope=this.scope,i}normalize(n,t){return v(n,t)}extractDeps(n){return B(n)}get cacheSize(){return {closures:this.cacheClosures.size,jit:this.cacheJIT.size}}clearCache(){this.cacheClosures.clear(),this.cacheJIT.clear();}getScope(){return this.scope}getArtifact(n,t,i,s,o){let r=this.compileCacheKey(t,i,o);return this.compileCache?this.compileCache.getOrCompile(r,s,()=>this.doCompile(n,i,s,o)):this.doCompile(n,i,s,o)}doCompile(n,t,i,s){let o=t?this.accessor??(()=>{}):void 0,{ir:r,deps:a,boundaryFns:l}=Q(n,{accessor:o,boundaries:this.boundaries,handlers:this.wrappedHandlers,lexicalPrefix:s}),c=JSON.stringify(n);return i==="jit"?U(r,a,l,{hash:c}):ie(r,a,l,c)}defaultCtx(n){return {scope:this.scope,accessor:n?this.accessor:void 0,handlers:this.wrappedHandlers}}compileCacheKey(n,t,i){return i?`${t?"a":"n"}:${i}:${n}`:t?`a:${n}`:n}};var Ce={};Te(Ce,{$:()=>fe,$arrow:()=>ge,$call:()=>he,$cond:()=>ye,$fn:()=>de,$if:()=>Le,$pipe:()=>me,arrow:()=>tn,call:()=>rn,cond:()=>nn,fn:()=>Ze,pipe:()=>en,ref:()=>Xe});function fe(e){return {$:e}}var Xe=fe;function de(e,n){return n===void 0?{$fn:e}:{$fn:e,args:n}}var Ze=de;function Le(e,n,t){return t===void 0?{$if:e,then:n}:{$if:e,then:n,else:t}}function me(...e){return {$pipe:e}}var en=me;function ye(e,n,t){return t===void 0?{left:e,op:n}:{left:e,op:n,right:t}}var nn=ye;function ge(e,n){return n===void 0||n.length===0?{$arrow:e}:{$arrow:e,args:n}}var tn=ge;function he(e,n=[]){return {$fn:e,args:n}}var rn=he;function ee(e,n="root",t={}){let i=[];return x(e,n,i,t),{valid:i.length===0,errors:i}}function x(e,n,t,i){if(e===null||typeof e!="object")return;if(Array.isArray(e)){for(let r=0;r<e.length;r++)x(e[r],`${n}[${r}]`,t,i);return}if(w(e)){(!e.$||typeof e.$!="string")&&t.push(`${n}: invalid reference, $ must be non-empty string`);return}if(I(e)){typeof e.$if=="string"?(e.$if.startsWith("!")?e.$if.slice(1):e.$if)||t.push(`${n}.$if: empty path in string shorthand`):x(e.$if,`${n}.$if`,t,i),x(e.then,`${n}.then`,t,i),e.else!==void 0&&x(e.else,`${n}.else`,t,i);return}if($(e)){if(!Array.isArray(e.$pipe)){t.push(`${n}.$pipe: must be an array`);return}if(e.$pipe.length===0){t.push(`${n}.$pipe: must have at least one element`);return}for(let r=0;r<e.$pipe.length;r++)x(e.$pipe[r],`${n}.$pipe[${r}]`,t,i);return}if(E(e)){if(!e.$fn||typeof e.$fn!="string"){t.push(`${n}: invalid function, $fn must be non-empty string`);return}let r=e.$fn.indexOf(":");if(r!==-1){let a=e.$fn.slice(0,r),l=e.$fn.slice(r+1);!a||!l||l.includes(":")?t.push(`${n}: invalid handler format "${e.$fn}", expected "namespace:method"`):i.handlers&&!i.handlers[a]?.[l]&&t.push(`${n}: handler "${e.$fn}" not found`);}else i.scope&&!(e.$fn in i.scope)&&t.push(`${n}: function "${e.$fn}" not found in scope`);if(e.args!==void 0)if(!Array.isArray(e.args))t.push(`${n}.args: must be an array`);else for(let a=0;a<e.args.length;a++)x(e.args[a],`${n}.args[${a}]`,t,i);return}if(F(e)){if(x(e.$arrow,`${n}.$arrow`,t,i),e.args!==void 0)if(!Array.isArray(e.args))t.push(`${n}.args: must be an array of strings`);else for(let r of e.args)(typeof r!="string"||!r)&&t.push(`${n}.args: each arg must be a non-empty string`);return}if(b(e)){V.has(e.op)||t.push(`${n}: invalid operator "${e.op}"`),x(e.left,`${n}.left`,t,i),e.right!==void 0&&x(e.right,`${n}.right`,t,i);return}if(T(e)){if(e.logic!=="AND"&&e.logic!=="OR"&&t.push(`${n}: invalid logic "${e.logic}", must be "AND" or "OR"`),!Array.isArray(e.conditions)){t.push(`${n}.conditions: must be an array`);return}for(let r=0;r<e.conditions.length;r++)x(e.conditions[r],`${n}.conditions[${r}]`,t,i);return}if(i.boundaries?.length){let r=e;for(let a of i.boundaries)if(a.check(r))return}let s=e,o=Object.keys(s);for(let r=0;r<o.length;r++){let a=o[r];x(s[a],`${n}.${a}`,t,i);}}function on(e,n={}){let t=ee(e,"root",n);if(!t.valid)throw new Error(`Invalid expression: ${t.errors.join("; ")}`)}function sn(e,n={}){return ee(e,"root",n).valid}function D(e){return "compile"in e}function O(e){return "type"in e&&!("compile"in e)}function Re(e){return typeof e.compile=="string"}function W(e){return typeof e.compile=="function"}function G(e,n){let t=[];for(let i of Object.keys(e))i in n||t.push({field:i,message:`Unknown field "${i}"`,type:"unknown_field"});for(let[i,s]of Object.entries(n)){let o=e[i],r=i in e&&o!==void 0;if(O(s)){if(s.required&&!r&&s.default===void 0){t.push({field:i,message:`Missing required field "${i}"`,type:"missing_required"});continue}if(r){let a=an(i,o,s);a&&t.push(a);}}}return {valid:t.length===0,errors:t}}function an(e,n,t){switch(t.type){case "string":if(typeof n!="string")return {field:e,message:`Field "${e}" expected string, got ${typeof n}`,type:"type_mismatch"};break;case "number":if(typeof n!="number")return {field:e,message:`Field "${e}" expected number, got ${typeof n}`,type:"type_mismatch"};break;case "boolean":if(typeof n!="boolean")return {field:e,message:`Field "${e}" expected boolean, got ${typeof n}`,type:"type_mismatch"};break;case "string[]":if(!Array.isArray(n)||!n.every(i=>typeof i=="string"))return {field:e,message:`Field "${e}" expected string[], got ${M(n)}`,type:"type_mismatch"};break;case "number[]":if(!Array.isArray(n)||!n.every(i=>typeof i=="number"))return {field:e,message:`Field "${e}" expected number[], got ${M(n)}`,type:"type_mismatch"};break;case "enum":if(!t.values||!t.values.includes(n))return {field:e,message:`Field "${e}" expected one of [${t.values?.join(", ")}], got "${String(n)}"`,type:"invalid_enum"};break;case "object":if(typeof n!="object"||n===null||Array.isArray(n))return {field:e,message:`Field "${e}" expected object, got ${M(n)}`,type:"type_mismatch"};break;case "schema":if(typeof n!="object"||n===null||Array.isArray(n))return {field:e,message:`Field "${e}" expected schema object, got ${M(n)}`,type:"type_mismatch"};break;}return null}function M(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function xe(e,n,t,i){if(i?.validate!==false){let l=G(e,n);if(!l.valid){let c=l.errors.map(u=>u.message).join("; ");throw new Error(`Template validation failed: ${c}`)}}let s=ln(e,n),o={},r={},a=new Set;for(let[l,c]of Object.entries(n)){let u=s[l];if(D(c)){if(u===void 0)continue;let f=cn(l,u,c,t,i);o[l]=f.value,f.artifact&&(r[l]=f.artifact),f.isCondition&&a.add(l);}else O(c)&&u!==void 0&&(o[l]=u);}return pn(o,r,a)}function ln(e,n){let t={...e};for(let[i,s]of Object.entries(n))O(s)&&!(i in t)&&s.default!==void 0&&(t[i]=s.default);return t}function cn(e,n,t,i,s){if(W(t)){let a={allow:t.allow,deny:t.deny,transforms:s?.transforms,mode:s?.mode};return {value:t.compile(n,i,a),artifact:null,isCondition:false}}let o=s?.mode??"closures";if(t.compile==="condition"){let l={$arrow:typeof n=="string"?{$if:n,then:true,else:false}:n},c=o==="jit"?i.jit(l,{useAccessor:true}):i.compile(l,{useAccessor:true});return {value:c.bind()({}),artifact:c,isCondition:true}}if(t.compile==="expression"){let a=o==="jit"?i.jit(n,{useAccessor:true}):i.compile(n,{useAccessor:true});return {value:a.bind(),artifact:a,isCondition:false}}let r=s?.handlers?.[t.compile];if(r){let a={allow:t.allow,deny:t.deny,transforms:s?.transforms,mode:s?.mode};return {value:r(n,i,a),artifact:null,isCondition:false}}throw new Error(`Unknown compile type: ${String(t.compile)}`)}function pn(e,n,t){let i={...e},s=o=>{let r={...e};for(let[a,l]of Object.entries(n)){let c=l.bind(o);r[a]=t.has(a)?c({}):c;}for(let[a,l]of Object.entries(e))a in n||l!=null&&typeof l.bind=="function"&&(r[a]=l.bind(o));return r.bind=s,r};return i.bind=s,i}var dt="3.0.0";export{X as CompileCache,L as ExpressionCompiler,dt as VERSION,on as assertValid,Ce as builders,xe as compileDefinition,H as compilePath,j as createBoundFn,B as extractDeps,Fe as get,Ye as hasDeps,N as hasWildcard,F as isArrow,D as isCompileField,b as isCondition,He as isConditionExpr,T as isConditionGroup,I as isConditional,Be as isExpression,E as isFn,W as isHandlerCompile,ze as isLiteral,Re as isNativeCompile,$ as isPipe,Qe as isPure,w as isRef,O as isSchemaField,sn as isValid,A as normalizePath,ee as validate,G as validateDefinition};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@statedelta-libs/expressions",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "JSON DSL compiler for optimized functions - StateDelta expression engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"test": "vitest run",
|
|
53
53
|
"test:watch": "vitest",
|
|
54
54
|
"test:coverage": "vitest run --coverage",
|
|
55
|
-
"typecheck": "tsc --noEmit",
|
|
55
|
+
"typecheck": "tsc --noEmit && eslint src/ tests/",
|
|
56
56
|
"clean": "rm -rf dist",
|
|
57
57
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
58
58
|
"format:check": "prettier --check \"src/**/*.ts\""
|