Skip to content

Commit e6a7ac6

Browse files
feat: non-static evaluate function
1 parent 683f088 commit e6a7ac6

File tree

2 files changed

+54
-12
lines changed

2 files changed

+54
-12
lines changed

__tests__/cel.test.ts

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
import { beforeEach, describe, expect, it } from "vitest";
2-
import { CelProgram } from "../src/index.js";
2+
import { CelProgram, evaluate } from "../src/index.js";
3+
4+
describe("evaluate", () => {
5+
it("should evaluate a simple expression", async () => {
6+
const result = await evaluate("size(message) > 5", {
7+
message: "Hello World",
8+
});
9+
expect(result).toBe(true);
10+
});
11+
12+
it("should handle errors gracefully", async () => {
13+
await expect(evaluate("invalid expression", {})).rejects.toThrow();
14+
});
15+
16+
it("should handle CEL map return values", async () => {
17+
const result = await evaluate(
18+
'{"name": "test", "items": [1, 2, 3].map(i, {"id": i})}',
19+
{},
20+
);
21+
expect(result).toEqual({
22+
name: "test",
23+
items: [{ id: 1 }, { id: 2 }, { id: 3 }],
24+
});
25+
});
26+
});
327

428
describe("CelProgram", () => {
529
it("should evaluate a simple expression", async () => {
@@ -94,39 +118,44 @@ describe("Performance measurements", () => {
94118

95119
it("should measure compile vs execute time", async () => {
96120
// Complex expression that requires significant parsing
97-
const expr = 'has(items) && items.map(i, i.price).filter(p, p < max_price).size() > 0';
121+
const expr =
122+
"has(items) && items.map(i, i.price).filter(p, p < max_price).size() > 0";
98123
const context = {
99124
items: Array.from({ length: 100 }, (_, i) => ({ id: i, price: i * 10 })),
100-
max_price: 500
125+
max_price: 500,
101126
};
102127

103128
// Measure compilation time
104-
const [program, compileTime] = await measureTime(() =>
105-
CelProgram.compile(expr)
129+
const [program, compileTime] = await measureTime(() =>
130+
CelProgram.compile(expr),
106131
);
107132
console.log(`Compilation took ${compileTime.toFixed(0)} nanoseconds`);
108133

109134
// Measure execution time
110135
const [result, executeTime] = await measureTime(() =>
111-
program.execute(context)
136+
program.execute(context),
112137
);
113138
console.log(`Execution took ${executeTime.toFixed(0)} nanoseconds`);
114139

115140
// Measure one-step evaluation time
116141
const [, evaluateTime] = await measureTime(() =>
117-
CelProgram.evaluate(expr, context)
142+
CelProgram.evaluate(expr, context),
143+
);
144+
console.log(
145+
`One-step evaluation took ${evaluateTime.toFixed(0)} nanoseconds`,
118146
);
119-
console.log(`One-step evaluation took ${evaluateTime.toFixed(0)} nanoseconds`);
120147

121148
// Basic sanity check that the timing data is reasonable
122149
expect(compileTime).toBeGreaterThan(0);
123150
expect(executeTime).toBeGreaterThan(0);
124151
expect(evaluateTime).toBeGreaterThan(0);
125-
152+
126153
// The one-step evaluation should be approximately the sum of compile and execute
127154
const tolerance = 0.5; // Allow 50% variation due to system noise
128155
const expectedEvaluateTime = compileTime + executeTime;
129-
expect(evaluateTime).toBeGreaterThan(expectedEvaluateTime * (1 - tolerance));
156+
expect(evaluateTime).toBeGreaterThan(
157+
expectedEvaluateTime * (1 - tolerance),
158+
);
130159
expect(evaluateTime).toBeLessThan(expectedEvaluateTime * (1 + tolerance));
131160
});
132161
});

src/index.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export interface CelContext {
22
[key: string]: any;
33
}
44

5-
export class CelProgram {
5+
class CelProgram {
66
private static nativeModule: any;
77
private native: any;
88

@@ -56,4 +56,17 @@ export class CelProgram {
5656
}
5757
}
5858

59-
export default CelProgram;
59+
/**
60+
* Convenience function to compile and execute a CEL expression in one step.
61+
* Note: If you plan to evaluate the same expression multiple times with different contexts,
62+
* it's more efficient to use CelProgram.compile() once and then call execute() multiple times.
63+
*
64+
* @param source The CEL expression to evaluate
65+
* @param context The context object containing variables for the expression
66+
* @returns The result of evaluating the expression
67+
*/
68+
async function evaluate(source: string, context: CelContext): Promise<any> {
69+
return CelProgram.evaluate(source, context);
70+
}
71+
72+
export { CelProgram, evaluate };

0 commit comments

Comments
 (0)