@bufbuild/protovalidate
Version:
Protocol Buffer Validation for ECMAScript
121 lines (120 loc) • 5.79 kB
JavaScript
;
// 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.createCustomFuncions = createCustomFuncions;
const cel_1 = require("@bufbuild/cel");
const lib_js_1 = require("./lib.js");
const reflect_1 = require("@bufbuild/protobuf/reflect");
const wkt_1 = require("@bufbuild/protobuf/wkt");
const protobuf_1 = require("@bufbuild/protobuf");
const isNanFn = (0, cel_1.celFunc)("isNan", [
(0, cel_1.celOverload)([cel_1.CelScalar.DOUBLE], cel_1.CelScalar.BOOL, Number.isNaN),
]);
const isInfFn = (0, cel_1.celFunc)("isInf", [
(0, cel_1.celOverload)([cel_1.CelScalar.DOUBLE], cel_1.CelScalar.BOOL, lib_js_1.isInf),
(0, cel_1.celOverload)([cel_1.CelScalar.DOUBLE, cel_1.CelScalar.INT], cel_1.CelScalar.BOOL, lib_js_1.isInf),
]);
const isHostnameFn = (0, cel_1.celFunc)("isHostname", [
(0, cel_1.celOverload)([cel_1.CelScalar.STRING], cel_1.CelScalar.BOOL, lib_js_1.isHostname),
]);
const isHostAndPortFn = (0, cel_1.celFunc)("isHostAndPort", [
(0, cel_1.celOverload)([cel_1.CelScalar.STRING, cel_1.CelScalar.BOOL], cel_1.CelScalar.BOOL, lib_js_1.isHostAndPort),
]);
const isEmailFn = (0, cel_1.celFunc)("isEmail", [
(0, cel_1.celOverload)([cel_1.CelScalar.STRING], cel_1.CelScalar.BOOL, lib_js_1.isEmail),
]);
const isIpFn = (0, cel_1.celFunc)("isIp", [
(0, cel_1.celOverload)([cel_1.CelScalar.STRING], cel_1.CelScalar.BOOL, lib_js_1.isIp),
(0, cel_1.celOverload)([cel_1.CelScalar.STRING, cel_1.CelScalar.INT], cel_1.CelScalar.BOOL, lib_js_1.isIp),
]);
const isIpPrefixFn = (0, cel_1.celFunc)("isIpPrefix", [
(0, cel_1.celOverload)([cel_1.CelScalar.STRING], cel_1.CelScalar.BOOL, lib_js_1.isIpPrefix),
(0, cel_1.celOverload)([cel_1.CelScalar.STRING, cel_1.CelScalar.INT], cel_1.CelScalar.BOOL, lib_js_1.isIpPrefix),
(0, cel_1.celOverload)([cel_1.CelScalar.STRING, cel_1.CelScalar.BOOL], cel_1.CelScalar.BOOL, (str, strict) => (0, lib_js_1.isIpPrefix)(str, undefined, strict)),
(0, cel_1.celOverload)([cel_1.CelScalar.STRING, cel_1.CelScalar.INT, cel_1.CelScalar.BOOL], cel_1.CelScalar.BOOL, lib_js_1.isIpPrefix),
]);
const isUriFn = (0, cel_1.celFunc)("isUri", [
(0, cel_1.celOverload)([cel_1.CelScalar.STRING], cel_1.CelScalar.BOOL, lib_js_1.isUri),
]);
const isUriRefFn = (0, cel_1.celFunc)("isUriRef", [
(0, cel_1.celOverload)([cel_1.CelScalar.STRING], cel_1.CelScalar.BOOL, lib_js_1.isUriRef),
]);
const uniqueFn = (0, cel_1.celFunc)("unique", [
(0, cel_1.celOverload)([(0, cel_1.listType)(cel_1.CelScalar.DYN)], cel_1.CelScalar.BOOL, lib_js_1.unique),
]);
const getFieldFn = (0, cel_1.celFunc)("getField", [
(0, cel_1.celOverload)([cel_1.CelScalar.DYN, cel_1.CelScalar.STRING], cel_1.CelScalar.DYN, (msg, name) => {
if (!(0, reflect_1.isReflectMessage)(msg)) {
throw new Error("getField can only be applied to messages");
}
const field = msg.fields.find((f) => f.name === name);
if (field === undefined) {
throw new Error(`field ${name} not found on ${msg.desc}`);
}
switch (field.fieldKind) {
case "list":
case "map":
return msg.get(field);
case "enum":
return BigInt(msg.get(field));
case "scalar":
return (0, cel_1.celFromScalar)(field.scalar, msg.get(field));
case "message":
if (msg.isSet(field)) {
return msg.get(field);
}
if ((0, wkt_1.isWrapperDesc)(field.message)) {
return null;
}
return (0, protobuf_1.create)(field.message);
}
}),
]);
const containsFn = (0, cel_1.celFunc)("contains", [
(0, cel_1.celOverload)([cel_1.CelScalar.BYTES, cel_1.CelScalar.BYTES], cel_1.CelScalar.BOOL, lib_js_1.bytesContains),
(0, cel_1.celOverload)([cel_1.CelScalar.STRING, cel_1.CelScalar.STRING], cel_1.CelScalar.BOOL, (l, r) => l.includes(r)),
]);
const endsWithFn = (0, cel_1.celFunc)("endsWith", [
(0, cel_1.celOverload)([cel_1.CelScalar.BYTES, cel_1.CelScalar.BYTES], cel_1.CelScalar.BOOL, lib_js_1.bytesEndsWith),
(0, cel_1.celOverload)([cel_1.CelScalar.STRING, cel_1.CelScalar.STRING], cel_1.CelScalar.BOOL, (l, r) => l.endsWith(r)),
]);
const startsWithFn = (0, cel_1.celFunc)("startsWith", [
(0, cel_1.celOverload)([cel_1.CelScalar.BYTES, cel_1.CelScalar.BYTES], cel_1.CelScalar.BOOL, lib_js_1.bytesStartsWith),
(0, cel_1.celOverload)([cel_1.CelScalar.STRING, cel_1.CelScalar.STRING], cel_1.CelScalar.BOOL, (l, r) => l.startsWith(r)),
]);
function createCustomFuncions(regexMatcher) {
const funcs = [
isNanFn,
isInfFn,
isHostnameFn,
isHostAndPortFn,
isEmailFn,
isIpFn,
isIpPrefixFn,
isUriFn,
isUriRefFn,
uniqueFn,
getFieldFn,
containsFn,
endsWithFn,
startsWithFn,
];
if (regexMatcher) {
funcs.push((0, cel_1.celFunc)("matches", [
(0, cel_1.celOverload)([cel_1.CelScalar.STRING, cel_1.CelScalar.STRING], cel_1.CelScalar.BOOL, (against, pattern) => regexMatcher(pattern, against)),
]));
}
return funcs;
}