UNPKG

@bufbuild/cel

Version:

A CEL evaluator for ECMAScript

186 lines (185 loc) 8.29 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.addCasts = addCasts; const protobuf_1 = require("@bufbuild/protobuf"); const wkt_1 = require("@bufbuild/protobuf/wkt"); const func_js_1 = require("../func.js"); const math_js_1 = require("./math.js"); const type_js_1 = require("../type.js"); const uint_js_1 = require("../uint.js"); const eval_js_1 = require("../eval.js"); const duration_js_1 = require("../duration.js"); const INT = "int"; const UINT = "uint"; const DOUBLE = "double"; const BOOL = "bool"; const STRING = "string"; const BYTES = "bytes"; const TIMESTAMP = "timestamp"; const DURATION = "duration"; const TYPE = "type"; const DYN = "dyn"; const intFunc = (0, func_js_1.celFunc)(INT, [ (0, func_js_1.celOverload)([type_js_1.CelScalar.INT], type_js_1.CelScalar.INT, (x) => x), (0, func_js_1.celOverload)([type_js_1.CelScalar.UINT], type_js_1.CelScalar.INT, (x) => { const val = x.value; if ((0, math_js_1.isOverflowInt)(val)) { throw overflow(INT, type_js_1.CelScalar.INT); } return x.value; }), (0, func_js_1.celOverload)([type_js_1.CelScalar.DOUBLE], type_js_1.CelScalar.INT, (x) => { if ((0, math_js_1.isOverflowIntNum)(x)) { throw overflow(INT, type_js_1.CelScalar.INT); } return BigInt(Math.trunc(x)); }), (0, func_js_1.celOverload)([type_js_1.CelScalar.STRING], type_js_1.CelScalar.INT, (x) => { const val = BigInt(x); if ((0, math_js_1.isOverflowInt)(val)) { throw overflow(INT, type_js_1.CelScalar.INT); } return val; }), (0, func_js_1.celOverload)([type_js_1.TIMESTAMP], type_js_1.CelScalar.INT, (x) => { const val = x.message.seconds; if ((0, math_js_1.isOverflowInt)(val)) { throw overflow(INT, type_js_1.CelScalar.INT); } return BigInt(val); }), (0, func_js_1.celOverload)([type_js_1.DURATION], type_js_1.CelScalar.INT, (x) => { const val = x.message.seconds; if ((0, math_js_1.isOverflowInt)(val)) { throw overflow(INT, type_js_1.CelScalar.INT); } return BigInt(val); }), ]); const uintFunc = (0, func_js_1.celFunc)(UINT, [ (0, func_js_1.celOverload)([type_js_1.CelScalar.UINT], type_js_1.CelScalar.UINT, (x) => x), (0, func_js_1.celOverload)([type_js_1.CelScalar.INT], type_js_1.CelScalar.UINT, (x) => { if ((0, math_js_1.isOverflowUint)(x)) { throw overflow(UINT, type_js_1.CelScalar.UINT); } return (0, uint_js_1.celUint)(x); }), (0, func_js_1.celOverload)([type_js_1.CelScalar.DOUBLE], type_js_1.CelScalar.UINT, (x) => { if ((0, math_js_1.isOverflowUintNum)(x)) { throw overflow(UINT, type_js_1.CelScalar.UINT); } return (0, uint_js_1.celUint)(BigInt(Math.trunc(x))); }), (0, func_js_1.celOverload)([type_js_1.CelScalar.STRING], type_js_1.CelScalar.UINT, (x) => { const val = BigInt(x); if ((0, math_js_1.isOverflowUint)(val)) { throw overflow(UINT, type_js_1.CelScalar.UINT); } return (0, uint_js_1.celUint)(val); }), ]); const doubleFunc = (0, func_js_1.celFunc)(DOUBLE, [ (0, func_js_1.celOverload)([type_js_1.CelScalar.DOUBLE], type_js_1.CelScalar.DOUBLE, (x) => x), (0, func_js_1.celOverload)([type_js_1.CelScalar.INT], type_js_1.CelScalar.DOUBLE, (x) => Number(x)), (0, func_js_1.celOverload)([type_js_1.CelScalar.UINT], type_js_1.CelScalar.DOUBLE, (x) => Number(x.value)), (0, func_js_1.celOverload)([type_js_1.CelScalar.STRING], type_js_1.CelScalar.DOUBLE, (x) => Number(x)), ]); const boolFunc = (0, func_js_1.celFunc)(BOOL, [ (0, func_js_1.celOverload)([type_js_1.CelScalar.BOOL], type_js_1.CelScalar.BOOL, (x) => x), (0, func_js_1.celOverload)([type_js_1.CelScalar.STRING], type_js_1.CelScalar.BOOL, (x) => { switch (x) { case "true": case "True": case "TRUE": case "t": case "1": return true; case "false": case "False": case "FALSE": case "f": case "0": return false; default: throw new Error(`Unable to convert string '${x}' to bool`); } }), ]); const bytesFunc = (0, func_js_1.celFunc)(BYTES, [ (0, func_js_1.celOverload)([type_js_1.CelScalar.BYTES], type_js_1.CelScalar.BYTES, (x) => x), (0, func_js_1.celOverload)([type_js_1.CelScalar.STRING], type_js_1.CelScalar.BYTES, (x) => Buffer.from(x)), ]); const stringFunc = (0, func_js_1.celFunc)(STRING, [ (0, func_js_1.celOverload)([type_js_1.CelScalar.STRING], type_js_1.CelScalar.STRING, (x) => x), (0, func_js_1.celOverload)([type_js_1.CelScalar.BOOL], type_js_1.CelScalar.STRING, (x) => x ? "true" : "false"), (0, func_js_1.celOverload)([type_js_1.CelScalar.INT], type_js_1.CelScalar.STRING, (x) => x.toString()), (0, func_js_1.celOverload)([type_js_1.CelScalar.UINT], type_js_1.CelScalar.STRING, (x) => x.value.toString()), (0, func_js_1.celOverload)([type_js_1.CelScalar.DOUBLE], type_js_1.CelScalar.STRING, (x) => x.toString()), (0, func_js_1.celOverload)([type_js_1.CelScalar.BYTES], type_js_1.CelScalar.STRING, (x) => { const coder = new TextDecoder(undefined, { fatal: true }); try { return coder.decode(x); } catch (e) { throw new Error(`Failed to decode bytes as string: ${e}`); } }), (0, func_js_1.celOverload)([type_js_1.TIMESTAMP], type_js_1.CelScalar.STRING, (x) => (0, protobuf_1.toJson)(wkt_1.TimestampSchema, x.message)), (0, func_js_1.celOverload)([type_js_1.DURATION], type_js_1.CelScalar.STRING, (x) => (0, protobuf_1.toJson)(wkt_1.DurationSchema, x.message)), ]); const timestampFunc = (0, func_js_1.celFunc)(TIMESTAMP, [ (0, func_js_1.celOverload)([type_js_1.TIMESTAMP], type_js_1.TIMESTAMP, (x) => x), (0, func_js_1.celOverload)([type_js_1.CelScalar.STRING], type_js_1.TIMESTAMP, (x) => { try { return (0, protobuf_1.fromJson)(wkt_1.TimestampSchema, x); } catch (e) { throw new Error(`Failed to parse timestamp: ${e}`); } }), (0, func_js_1.celOverload)([type_js_1.CelScalar.INT], type_js_1.TIMESTAMP, (x) => (0, wkt_1.timestampFromMs)(Number(x))), ]); const durationFunc = (0, func_js_1.celFunc)(DURATION, [ (0, func_js_1.celOverload)([type_js_1.DURATION], type_js_1.DURATION, (x) => x), (0, func_js_1.celOverload)([type_js_1.CelScalar.STRING], type_js_1.DURATION, duration_js_1.parseDuration), (0, func_js_1.celOverload)([type_js_1.CelScalar.INT], type_js_1.DURATION, (x) => (0, protobuf_1.create)(wkt_1.DurationSchema, { seconds: x })), ]); const typeFunc = (0, func_js_1.celFunc)(TYPE, [ (0, func_js_1.celOverload)([type_js_1.CelScalar.DYN], type_js_1.CelScalar.TYPE, (v) => { if ((0, protobuf_1.isMessage)(v)) { return (0, type_js_1.objectType)((0, eval_js_1.getMsgDesc)(v.$typeName)); } return (0, type_js_1.celType)(v); }), ]); const dynFunc = (0, func_js_1.celFunc)(DYN, [ (0, func_js_1.celOverload)([type_js_1.CelScalar.DYN], type_js_1.CelScalar.DYN, (x) => x), ]); function addCasts(funcs) { funcs.add(intFunc); funcs.add(uintFunc); funcs.add(doubleFunc); funcs.add(boolFunc); funcs.add(bytesFunc); funcs.add(stringFunc); funcs.add(timestampFunc); funcs.add(durationFunc); funcs.add(typeFunc); funcs.add(dynFunc); } function overflow(op, type) { return new Error(`${type} return error for overflow during ${op}`); }