UNPKG

@bufbuild/cel

Version:

A CEL evaluator for ECMAScript

69 lines (68 loc) 2.81 kB
"use strict"; // Copyright 2024-2025 Buf Technologies, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. Object.defineProperty(exports, "__esModule", { value: true }); exports.plan = plan; const checked_pb_js_1 = require("@bufbuild/cel-spec/cel/expr/checked_pb.js"); const syntax_pb_js_1 = require("@bufbuild/cel-spec/cel/expr/syntax_pb.js"); const planner_js_1 = require("./planner.js"); const protobuf_1 = require("@bufbuild/protobuf"); const error_js_1 = require("./error.js"); const eval_js_1 = require("./eval.js"); const value_js_1 = require("./value.js"); const activation_js_1 = require("./activation.js"); const cache = new WeakMap(); /** * Creates an execution plan for a CEL expression and returns a reusable evaluation function. * * Planning analyzes the expression structure once, independent of runtime variable values. * The returned function can be called multiple times with different variable bindings. */ function plan(env, expr) { // TODO(srikrsna): This can be avoided, if we refactor Planner into functions that use CelEnv directly. let planner = cache.get(env); if (planner === undefined) { planner = new planner_js_1.Planner(env.dispatcher, env.registry, env.namespace); cache.set(env, planner); } let maybeExpr; if ((0, protobuf_1.isMessage)(expr, checked_pb_js_1.CheckedExprSchema)) { maybeExpr = expr.expr; } else if ((0, protobuf_1.isMessage)(expr, syntax_pb_js_1.ParsedExprSchema)) { maybeExpr = expr.expr; } else { maybeExpr = expr; } const plan = planner.plan(maybeExpr ?? (0, protobuf_1.create)(syntax_pb_js_1.ExprSchema)); const withContext = (0, eval_js_1.withEvalContext)({ registry: env.registry }, { id: plan.id, eval(ctx) { try { let val = plan.eval(ctx); if ((0, error_js_1.isCelError)(val)) { return val; } return (0, value_js_1.unwrapAny)(val); } catch (ex) { return (0, error_js_1.celError)(ex, plan.id); } }, }); return (ctx) => { return withContext.eval(ctx !== undefined ? new activation_js_1.ObjectActivation(ctx) : activation_js_1.EMPTY_ACTIVATION); }; }