UNPKG

@bufbuild/cel

Version:

A CEL evaluator for ECMAScript

161 lines (160 loc) 5.02 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.toCel = toCel; exports.unwrapAny = unwrapAny; exports.reflectMsgToCel = reflectMsgToCel; const uint_js_1 = require("./uint.js"); const map_js_1 = require("./map.js"); const list_js_1 = require("./list.js"); const reflect_1 = require("@bufbuild/protobuf/reflect"); const protobuf_1 = require("@bufbuild/protobuf"); const eval_js_1 = require("./eval.js"); const wkt_1 = require("@bufbuild/protobuf/wkt"); const type_js_1 = require("./type.js"); /** * Converts a CelInput to a CelValue. */ function toCel(v) { switch (typeof v) { case "bigint": case "boolean": case "number": case "string": return v; case "object": break; default: throw new Error(`unsupported input ${typeof v}`); } switch (true) { case v === null: case v instanceof Uint8Array: case (0, list_js_1.isCelList)(v): case (0, map_js_1.isCelMap)(v): case (0, uint_js_1.isCelUint)(v): case (0, type_js_1.isCelType)(v): return v; } if (isArray(v) || (0, reflect_1.isReflectList)(v)) { return (0, list_js_1.celList)(v); } if (isMap(v) || (0, reflect_1.isReflectMap)(v)) { return (0, map_js_1.celMap)(v); } if ((0, protobuf_1.isMessage)(v)) { const value = wktToCel(v); if (value !== undefined) { return value; } return (0, reflect_1.reflect)((0, eval_js_1.getMsgDesc)(v.$typeName), v); } if ((0, reflect_1.isReflectMessage)(v)) { return reflectMsgToCel(v); } if (v.constructor.name === "Object") { return (0, map_js_1.celMap)(new Map(Object.entries(v))); } throw new Error(`Unsupported input ${v}`); } /** * Unwraps the given value if it is an Any. * * If the Any represents a Wrapper type or google.protobuf.Value/Struct/ListValue, it also converts them * to their corresponding CelValue. */ function unwrapAny(v) { if (!isReflectAny(v)) { return v; } const unpacked = (0, wkt_1.anyUnpack)(v.message, (0, eval_js_1.getEvalContext)().registry); if (unpacked === undefined) { throw new Error(`invalid Any or ${v.message.typeUrl} not found in registry`); } const value = wktToCel(unpacked); if (value !== undefined) { return value; } return (0, reflect_1.reflect)((0, eval_js_1.getMsgDesc)(unpacked.$typeName), unpacked); } function reflectMsgToCel(v) { const value = wktToCel(v.message); if (value !== undefined) { return value; } return v; } function isReflectAny(v) { return (0, reflect_1.isReflectMessage)(v, wkt_1.AnySchema); } function isArray(v) { return Array.isArray(v); } function isMap(v) { return v instanceof Map; } function wktToCel(msg) { if ((0, wkt_1.isWrapper)(msg)) { return unwrapWrapper(msg); } return jsonWrapperToCel(msg); } function unwrapWrapper(v) { switch (v.$typeName) { case wkt_1.Int32ValueSchema.typeName: return BigInt(v.value); case wkt_1.UInt32ValueSchema.typeName: return (0, uint_js_1.celUint)(BigInt(v.value)); case wkt_1.UInt64ValueSchema.typeName: return (0, uint_js_1.celUint)(v.value); } return v.value; } function jsonWrapperToCel(msg) { switch (true) { case (0, protobuf_1.isMessage)(msg, wkt_1.StructSchema): return structToCel(msg); case (0, protobuf_1.isMessage)(msg, wkt_1.ValueSchema): return valueToCel(msg); case (0, protobuf_1.isMessage)(msg, wkt_1.ListValueSchema): return listValueToCel(msg); } return undefined; } function structToCel(s) { const map = new Map(); for (const [k, v] of Object.entries(s.fields)) { map.set(k, valueToCel(v)); } return (0, map_js_1.celMap)(map); } function valueToCel(v) { switch (v.kind.case) { case "boolValue": case "numberValue": case "stringValue": return v.kind.value; case "nullValue": case undefined: return null; case "structValue": return structToCel(v.kind.value); case "listValue": return listValueToCel(v.kind.value); } } function listValueToCel(l) { return (0, list_js_1.celList)(l.values); }