UNPKG

cloudevent

Version:

JavaScript/Node.js implementation of the CloudEvents standard format

1,177 lines (1,101 loc) 42 kB
/* * Copyright 2018-2026 the original author or authors. * * 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. */ 'use strict' /** * Validators: * this module exports some useful generic functions for the validation of objects. */ /** * Get a reference to Node.js url module. * @private */ const url = require('node:url') /** * Generic Validator implementation. * * Note that all methods here are static, so no need to instance this class; * see it as an Utility/Companion class. */ class Validator { /** * Create a new instance of a Validator object. * Note that instancing is not allowed for this class because all its methods are static. * * @throws {Error} instancing not allowed for this class * @hideconstructor */ constructor () { throw new Error('Instancing not allowed for this class') } /** * Tell if the given argument is undefined. * * @static * @param {?object} arg the object to check * @return {boolean} true if undefined, false otherwise */ static isUndefined (arg) { return (arg === undefined) } /** * Tell if the given argument is null. * * @static * @param {?object} arg the object to check * @return {boolean} true if null, false otherwise */ static isNull (arg) { return (arg === null) } /** * Tell if the given argument is undefined or null. * * @static * @param {?object} arg the object to check * @return {boolean} true if undefined or null, false otherwise */ static isUndefinedOrNull (arg) { return (arg === undefined || arg === null) } /** * Tell if the given argument is defined and not null. * * @static * @param {?object} arg the object to check * @return {boolean} true if defined and not null, false otherwise */ static isDefinedAndNotNull (arg) { return (arg !== undefined && arg !== null) } /** * Tell if the given argument is a string. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a string, false otherwise */ static isString (arg) { // return (Validator.isDefinedAndNotNull(arg) && (typeof arg === 'string')) // rewritten inline and using new ES features for more performances return ((arg?.length >= 0) && (typeof arg === 'string')) } /** * Tell if the given argument is a not empty string. * * See {@link Validator.isString}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a not empty string, false otherwise */ static isStringNotEmpty (arg) { // return (Validator.isString(arg) && (arg.length > 0)) // rewritten inline and using new ES features for more performances return ((arg?.length > 0) && (typeof arg === 'string')) } /** * Tell if the given argument is a date. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a date, false otherwise */ static isDate (arg) { return (Validator.isDefinedAndNotNull(arg) && (typeof arg === 'object' || arg instanceof Date)) } /** * Tell if the given argument is a valid date. * * See {@link Validator.isDate}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a valid date, false otherwise */ static isDateValid (arg) { return (Validator.isDate(arg) && !isNaN(arg)) } /** * Tell if the given argument is a valid date and in the past or now. * * See {@link Validator.isDateValid}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a valid date in the past (or now), false otherwise */ static isDatePast (arg) { return (Validator.isDateValid(arg) && arg.getTime() <= Date.now()) } /** * Tell if the given argument is a valid date and in the future or now. * * See {@link Validator.isDateValid}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a valid date in the future (or now), false otherwise */ static isDateFuture (arg) { return (Validator.isDateValid(arg) && arg.getTime() > Date.now()) } /** * Tell if the given argument is a number. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a number, false otherwise */ static isNumber (arg) { return (Validator.isDefinedAndNotNull(arg) && typeof arg === 'number' && !isNaN(arg)) } /** * Tell if the given argument is an array. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's an array, false otherwise */ static isArray (arg) { return (Validator.isDefinedAndNotNull(arg) && (Array.isArray(arg))) } /** * Tell if the given argument is a normal value * (string or boolean or number). * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a string or boolean or number, false otherwise */ static isValue (arg) { return (Validator.isDefinedAndNotNull(arg) && (Validator.isString(arg) || Validator.isBoolean(arg) || Validator.isNumber(arg)) ) } /** * Tell if the given argument is a boolean. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a boolean, false otherwise */ static isBoolean (arg) { return (typeof arg === 'boolean') } /** * Tell if the given argument is an instance of the given class reference. * * @static * @param {?object} arg the object to check * @param {?object} classReference the class that should be implemented/extended * @return {boolean} true if it's an instance (or extends) that class, false otherwise */ static isClass (arg, classReference) { return (arg instanceof classReference) } /** * Tell if the given argument is an error. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's an error, false otherwise */ static isError (arg) { return (arg instanceof Error && typeof arg.message !== 'undefined') } /** * Tell if the given argument is a function. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a function, false otherwise */ static isFunction (arg) { // return (Validator.isDefinedAndNotNull(arg) && (typeof arg === 'function')) // rewritten (inline same code here) for more performances // return ((arg !== undefined && arg !== null) && (typeof arg === 'function')) // rewritten using new ES features, but same behavior return ((arg ?? false) && (typeof arg === 'function')) } /** * Tell if the given argument is an object * and is defined and not null. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's an object, false otherwise */ static isObject (arg) { return (Validator.isDefinedAndNotNull(arg) && (typeof arg === 'object')) } /** * Tell if the given argument is a plain object * and not: undefined, null, Array, Date, Number, String, * Symbol, Map/WeakMap, Set/WeakSet, etc. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a plain object, false otherwise */ static isObjectPlain (arg) { return (Object.prototype.toString.call(arg) === '[object Object]') } /** * Tell if the given argument is a keyed collection. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a Map|WeakMap or a Set|WeakSet, false otherwise */ static isKeyedCollection (arg) { return (Validator.isDefinedAndNotNull(arg) && ( arg instanceof Map || arg instanceof WeakMap || arg instanceof Set || arg instanceof WeakSet )) } /** * Tell if the given argument is a plain object or a keyed collection. * * See {@link Validator.isObject}, {@link Validator.isKeyedCollection}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a plain object or a keyed collection, false otherwise */ static isObjectOrCollection (arg) { return (Validator.isObjectPlain(arg) || Validator.isKeyedCollection(arg)) } /** * Tell if the given argument is a plain object or a keyed collection, but not an array. * * See {@link Validator.isObjectOrCollection}. * See {@link Validator.isArray}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a plain object or a keyed collection but not an array, false otherwise */ static isObjectOrCollectionNotArray (arg) { return (Validator.isObjectOrCollection(arg) && !Validator.isArray(arg)) } /** * Tell if the given argument is a plain object or a keyed collection or an array. * * See {@link Validator.isObjectOrCollection}. * See {@link Validator.isArray}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a plain object or a keyed collection or an array, false otherwise */ static isObjectOrCollectionOrArray (arg) { return (Validator.isObjectOrCollection(arg) || Validator.isArray(arg)) } /** * Tell if the given argument is a plain object or a keyed collection, but not a string. * * See {@link Validator.isObjectOrCollection}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a plain object or a keyed collection but not a string, false otherwise */ static isObjectOrCollectionNotString (arg) { return (Validator.isObjectOrCollection(arg) && (typeof arg !== 'string')) } /** * Tell if the given argument is a plain object or a keyed collection or an array, * but not a value (string or boolean or number). * * See {@link Validator.isObjectOrCollection}. * See {@link Validator.isArray}. * See {@link Validator.isValue}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a plain object or a keyed collection or an array but not a value (string or boolean or number), false otherwise */ static isObjectOrCollectionOrArrayNotValue (arg) { return ((Validator.isObjectOrCollection(arg) || Validator.isArray(arg)) && !Validator.isValue(arg)) } /** * Tell if the given argument is a plain object or a keyed collection, or a string. * * See {@link Validator.isObjectOrCollection}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a plain object or a keyed collection or a string, false otherwise */ static isObjectOrCollectionOrString (arg) { return (Validator.isObjectOrCollection(arg) || (typeof arg === 'string')) } /** * Tell if the given argument is a plain object or a keyed collection, * or a value (string or boolean or number). * * See {@link Validator.isObjectOrCollection}. * See {@link Validator.isValuey}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a plain object or a keyed collection or a value (string or boolean or number), false otherwise */ static isObjectOrCollectionOrValue (arg) { return (Validator.isObjectOrCollection(arg) || Validator.isValue(arg)) } /** * Tell if the given argument is a plain object or a keyed collection or an array, * or a value (string or boolean or number). * * See {@link Validator.isObjectOrCollection}. * See {@link Validator.isArray}. * See {@link Validator.isValuey}. * * @static * @param {?object} arg the object to check * @return {boolean} true if it's a plain object or a keyed collection or an array or a value (string or boolean or number), false otherwise */ static isObjectOrCollectionOrArrayOrValue (arg) { return (Validator.isObjectOrCollection(arg) || Validator.isArray(arg) || Validator.isValue(arg)) } /** * Tell if the given argument is a string representation of a version number. * * Note that the version string could be something like: * - as minimum a number is needed for an integer version * - at the beginning I can have an optional char 'v' or 'V' * - anything after the third number will be considered as a string * - format updated to handle version output of 'git describe' * * @static * @param {?string} arg the version string to check * @return {boolean} true if it's a version string, false otherwise */ static isVersion (arg) { // quick check if the given string is in the format 'n.n.n' const versionRegex = /^(?:v|V?)((\d+)(?:\.?)){1,3}(?:\W|_?)(.*)$/gm return (Validator.isStringNotEmpty(arg) && versionRegex.test(arg)) } /** * Tell if the given argument is an URI or an URL. * * @static * @param {?string} arg the uri/url to check * @param {?string} base the (optional) base to build the full URL * @return {boolean} true if it's an URI/URL, false otherwise */ static isURI (arg, base) { // quick check if the given string is an URI or an URL if (!Validator.isStringNotEmpty(arg)) { return false } // simple check if it's an URL, trying to instancing it // note that this requires to import related module here (but not in Browsers) ... if (Validator.isStringNotEmpty(base)) { try { const u = new url.URL(arg, base) return (u !== null) } catch (e) { // console.error(e) return false } } else { // simple check if it's an URI (or better: a relative URL, or a full URI with scheme etc) const uriRegex = /^(\w+:|\/)/ // or /^(\w+:|\/)(.*)$/ for full match if (uriRegex.test(arg)) { return true } try { const u = new url.URL(arg) return (u !== null) } catch (e) { // console.error(e) return false } } } /** * Tell if the given object contains the given property. * * @static * @param {?object} obj the object to check * @param {?string} propName the name of the property * @param {boolean} [includeInherited=false] specify if search in nested/inherited properties * @return {boolean} true if the object contains theat property, otherwise false */ static doesObjectContainsProperty (obj, propName, includeInherited = false) { if (!Validator.isObject(obj)) return false if (!Validator.isStringNotEmpty(propName)) return false if (!Validator.isBoolean(includeInherited)) return false let propFound = false if (includeInherited === false) { propFound = Object.prototype.hasOwnProperty.call(obj, propName) } else { propFound = propName in obj } return propFound } /** * Tell if the given object contains at least one property * that has a standard (reserved) property name. * * @static * @param {?object} obj the object to check * @param {?function} isPropStandard the function that tell the given argument (property), if it's standard * @return {boolean} true if at least one property with a standard name is found, otherwise false */ static doesObjectContainsStandardProperty (obj, isPropStandard) { if (!Validator.isObject(obj)) return false if (!Validator.isFunction(isPropStandard)) return false let standardPropFound = false for (const prop in obj) { if (isPropStandard(prop) === true) { standardPropFound = true break } } return standardPropFound } /** * Tell if the given string has a standard (reserved) property name. * * @static * @param {?string} str the string to check * @param {?function} isPropStandard the function that tell the given argument (property), if it's standard * @return {boolean} true if the given string has a standard name, otherwise false */ static doesStringIsStandardProperty (str, isPropStandard) { if (!Validator.isStringNotEmpty(str)) return false if (!Validator.isFunction(isPropStandard)) return false let standardPropFound = false if (isPropStandard(str) === true) { standardPropFound = true } return standardPropFound } /** * Ensure that the given argument is undefined. * * See {@link Validator.isUndefined}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not undefined, nothing otherwise */ static ensureIsUndefined (arg, name = 'arg') { if (!Validator.isUndefined(arg)) { return new TypeError(`The argument '${name}' must be undefined, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is null. * * See {@link Validator.isNull}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not null, nothing otherwise */ static ensureIsNull (arg, name = 'arg') { if (!Validator.isNull(arg)) { return new TypeError(`The argument '${name}' must be null, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is undefined or null. * * See {@link Validator.isUndefinedOrNull}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not undefined or null, nothing otherwise */ static ensureIsUndefinedOrNull (arg, name = 'arg') { if (!Validator.isUndefinedOrNull(arg)) { return new TypeError(`The argument '${name}' must be undefined or null, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is defined and not null. * * See {@link Validator.isDefinedAndNotNull}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not undefined or null, nothing otherwise */ static ensureIsDefinedAndNotNull (arg, name = 'arg') { if (!Validator.isDefinedAndNotNull(arg)) { return new TypeError(`The argument '${name}' must be defined and not null, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is an array. * * See {@link Validator.isArray}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not an array, nothing otherwise */ static ensureIsArray (arg, name = 'arg') { if (!Validator.isArray(arg)) { return new TypeError(`The argument '${name}' must be an array, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a value (string or boolean or number). * * See {@link Validator.isValue}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a string or a boolean or a number, nothing otherwise */ static ensureIsValue (arg, name = 'arg') { if (!Validator.isValue(arg)) { return new TypeError(`The argument '${name}' must be a value (string or boolean or number), instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a boolean. * * See {@link Validator.isBoolean}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a boolean, nothing otherwise */ static ensureIsBoolean (arg, name = 'arg') { if (!Validator.isBoolean(arg)) { return new TypeError(`The argument '${name}' must be a boolean, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is an instance of the given class reference. * * See {@link Validator.isClass}. * * @static * @param {?object} arg the object to check * @param {?object} classReference the class that should be implemented/extended * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not an instance (or extends) that class, nothing otherwise */ static ensureIsClass (arg, classReference, name = 'arg') { if (!Validator.isClass(arg, classReference)) { return new TypeError(`The argument '${name}' must be an instance of the given class reference, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a function. * * See {@link Validator.isFunction}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a function, nothing otherwise */ static ensureIsFunction (arg, name = 'arg') { if (!Validator.isFunction(arg)) { return new TypeError(`The argument '${name}' must be a function, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a string. * * See {@link Validator.isString}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a string, nothing otherwise */ static ensureIsString (arg, name = 'arg') { if (!Validator.isString(arg)) { return new TypeError(`The argument '${name}' must be a string, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a not empty string. * * See {@link Validator.isStringNotEmpty}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {Error} if it's not a string not empty, nothing otherwise */ static ensureIsStringNotEmpty (arg, name = 'arg') { if (!Validator.isStringNotEmpty(arg)) { return new Error(`The string '${name}' must be not empty`) } } /** * Ensure that the given argument is an object. * * See {@link Validator.isObject}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not an object, nothing otherwise */ static ensureIsObject (arg, name = 'arg') { if (!Validator.isObject(arg)) { return new TypeError(`The argument '${name}' must be an object, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a plain object * and not: undefined, null, Array, Date, Number, String, * Symbol, Map/WeakMap, Set/WeakSet, etc. * * See {@link Validator.isObjectPlain}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a plain object, nothing otherwise */ static ensureIsObjectPlain (arg, name = 'arg') { if (!Validator.isObjectPlain(arg)) { return new TypeError(`The argument '${name}' must be a plain object, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a plain object or a collection. * * See {@link Validator.isObjectOrCollection}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a plain object nor a collection, nothing otherwise */ static ensureIsObjectOrCollection (arg, name = 'arg') { if (!Validator.isObjectOrCollection(arg)) { return new TypeError(`The argument '${name}' must be an object or a collection, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a plain object or a collection, not an array. * * See {@link Validator.isObjectOrCollectionNotArray}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a plain object nor a collection or it's an array, nothing otherwise */ static ensureIsObjectOrCollectionNotArray (arg, name = 'arg') { if (!Validator.isObjectOrCollectionNotArray(arg)) { return new TypeError(`The argument '${name}' must be an object or a collection and not an array, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a plain object or a collection or an array. * * See {@link Validator.isObjectOrCollectionOrArray}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a plain object nor a collection nor an array, nothing otherwise */ static ensureIsObjectOrCollectionOrArray (arg, name = 'arg') { if (!Validator.isObjectOrCollectionOrArray(arg)) { return new TypeError(`The argument '${name}' must be an object or a collection and not an array, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a plain object or a collection, not a string. * * See {@link Validator.isObjectOrCollectionNotString}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a plain object nor a collection or it's a string, nothing otherwise */ static ensureIsObjectOrCollectionNotString (arg, name = 'arg') { if (!Validator.isObjectOrCollectionNotString(arg)) { return new TypeError(`The argument '${name}' must be an object or a collection and not a string, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a plain object or a collection or an array, * not a value (string or boolean or number). * * See {@link Validator.isObjectOrCollectionOrArrayNotValue}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a plain object nor a collection or it's a value (string or boolean or number), nothing otherwise */ static ensureIsObjectOrCollectionOrArrayNotValue (arg, name = 'arg') { if (!Validator.isObjectOrCollectionOrArrayNotValue(arg)) { return new TypeError(`The argument '${name}' must be an object or a collection or an array and not a value (string or boolean or number), instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a plain object or a collection, or a string. * * See {@link Validator.isObjectOrCollectionOrString}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a plain object nor a collection nor a string, nothing otherwise */ static ensureIsObjectOrCollectionOrString (arg, name = 'arg') { if (!Validator.isObjectOrCollectionOrString(arg)) { return new TypeError(`The argument '${name}' must be an object or a collection or a string, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a plain object or a collection, * or a value (string or boolean or number). * * See {@link Validator.isObjectOrCollectionOrValue}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a plain object nor a collection nor a value (string or boolean or number), nothing otherwise */ static ensureIsObjectOrCollectionOrValue (arg, name = 'arg') { if (!Validator.isObjectOrCollectionOrValue(arg)) { return new TypeError(`The argument '${name}' must be an object or a collection or a value (string or boolean or number), instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a plain object or a collection or an array, * or a value (string or boolean or number). * * See {@link Validator.isObjectOrCollectionOrArrayOrValue}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {TypeError} if it's not a plain object nor a collection nor a value (string or boolean or number), nothing otherwise */ static ensureIsObjectOrCollectionOrArrayOrValue (arg, name = 'arg') { if (!Validator.isObjectOrCollectionOrArrayOrValue(arg)) { return new TypeError(`The argument '${name}' must be an object or a collection or an array or a value (string or boolean or number), instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a date. * * See {@link Validator.isDate}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {Error} if it's not a date, nothing otherwise */ static ensureIsDate (arg, name = 'arg') { if (!Validator.isDate(arg)) { return new Error(`The argument '${name}' must be a Date, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a date in the past or now. * * See {@link Validator.isDatePast}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {Error} if it's not a date in the past, nothing otherwise */ static ensureIsDatePast (arg, name = 'arg') { if (!Validator.isDatePast(arg)) { return new Error(`The argument '${name}' must be a Date that belongs to the past`) } } /** * Ensure that the given argument is a date in the future or now. * * See {@link Validator.isDateFuture}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {Error} if it's not a date in the future, nothing otherwise */ static ensureIsDateFuture (arg, name = 'arg') { if (!Validator.isDateFuture(arg)) { return new Error(`The argument '${name}' must be a Date that belongs to the future`) } } /** * Ensure that the given argument is a number. * * See {@link Validator.isNumber}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {Error} if it's not a number, nothing otherwise */ static ensureIsNumber (arg, name = 'arg') { if (!Validator.isNumber(arg)) { return new Error(`The argument '${name}' must be a Number, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is an error instance or its subclass. * * See {@link Validator.isError}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {Error} if it's not an error or its subclass, nothing otherwise */ static ensureIsError (arg, name = 'arg') { if (!Validator.isError(arg)) { return new Error(`The argument '${name}' must be an Error or a subclass of it, instead got a '${typeof arg}'`) } } /** * Ensure that the given argument is a string version. * * See {@link Validator.isVersion}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {Error} if it's not a string version, nothing otherwise */ static ensureIsVersion (arg, name = 'arg') { if (!Validator.isVersion(arg)) { return new Error(`The argument '${name}' must be a string in the format 'n.n.n', and not '${arg}'`) } } /** * Ensure that the given argument is an URI/URL. * * See {@link Validator.isURI}. * * @static * @param {?object} arg the object to check * @param {?string} base the (optional) base to build the full URL * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @return {Error} if it's not an URI/URL, nothing otherwise */ static ensureIsURI (arg, base, name = 'arg') { if (!Validator.isURI(arg, base)) { return new Error(`The argument '${name}' must be an URI or URL string and not ('${arg}', '${base}')`) } } /** * Ensure that the given object contains the given property. * * See {@link Validator.doesObjectContainsProperty}. * * @static * @param {?object} obj the object to check * @param {?string} propName the name of the property * @param {boolean} [includeInherited=false] specify if search in nested/inherited properties * @param {string} [name='arg'] the name to use in generated error (for the first argument) * @return {boolean} true if the object contains theat property, otherwise false */ static ensureObjectContainsProperty (obj, propName, includeInherited = false, name = 'arg') { if (!Validator.doesObjectContainsProperty(obj, propName, includeInherited)) { return new Error(`The object with name '${name}' does not contains the property '${propName}' with search in inherited: ${includeInherited}`) } } /** * Ensure that the given object does not contain any property * that has a standard (reserved) property name. * * See {@link Validator.doesObjectContainsStandardProperty}. * * @static * @param {?object} arg the object to check * @param {?function} isPropStandard the function that tell the given argument (property), if it's standard * @param {string} [name='arg'] the name to use in generated error (for the first argument) * @return {Error} if at least one property with a standard name is found, nothing otherwise */ static ensureObjectDoesNotContainsStandardProperty (arg, isPropStandard, name = 'arg') { if (Validator.doesObjectContainsStandardProperty(arg, isPropStandard)) { return new Error(`The object with name '${name}' contains at least one property with a standard name`) } } /** * Tell the size of the given object * * @static * @param {?object} arg the object to check * @return {number} the size if it's an array|Map|Set|object|string, nothing otherwise * @throws {TypeError} if it's not an array nor a collection nor object nor a string */ static getSize (arg) { if ((arg === undefined || arg === null)) { return } if (Array.isArray(arg)) { return arg.length } else if (arg instanceof Map || arg instanceof Set) { return arg.size } else if (typeof arg === 'object') { return Object.keys(arg).length } else if (typeof arg === 'string') { return arg.length } // else throw new TypeError(`Unable to calculate the size of the argument '${arg}'.`) } /** * Tell the size in bytes of the given string. * * @static * @param {?string} str the string to check * @return {number} the size if it's a string, nothing otherwise * @throws {TypeError} if it's not a string */ static getSizeInBytes (str) { if ((str === undefined || str === null)) { return } if (typeof str === 'string') { return Buffer.from(str).length } // else throw new TypeError(`Unable to calculate the size in bytes of the argument '${str}'.`) } /** * Return the value of the variable given as argument. * * Note that this could have been written (in a shorter way) * as an arrow function. * * @static * @param {?object} arg the argument * @return {string} the value of the variable (if defined and not null), nothing otherwise */ static getArgumentValue (arg) { if ((arg === undefined || arg === null)) { return arg } // else return arguments[0] } /** * Return the name of the variable given as argument. * * To use it, must be called using the trick to wrap argument * inside an object literal, so for example use it inside a template string with: * `${getArgumentName({x})}` * with nested objects (like with options with a property x inside) * you need to use with: * `${getArgumentName({options})}.${getArgumentName({x})}`. * Note that this could have been written (in a shorter way) * as an arrow function. * * @static * @param {?object} arg the argument * @return {string} the name of the variable (if defined and not null), nothing otherwise */ static getArgumentName (arg) { if ((arg === undefined || arg === null)) { return } // else return Object.keys(arg)[0] } /** * Return the argument if it's defined and not null, * otherwise the given default value is returned. * * @static * @param {?object} arg the argument to return * @param {?object} def the default value to return * @return {object} the argument (if defined and not null), otherwise the default value */ static getOrElse (arg, def) { if (typeof arg !== 'undefined' && arg !== null) { return arg } // else return def } /** * Return a copy of the given ibject, * with all properties filtered by the given function (predicate). * * @static * @param {?object} obj the base object * @param {?function} propFilter the function (predicate) for filtering properties * @return {object} a new object containing only filtered properties * @throws {TypeError} if obj is not a plain object, or propFilter is not a function */ static getObjectFilteredProperties (obj, propFilter) { if (!Validator.isObjectPlain(obj)) throw new TypeError(`The argument 'obj' must be a plain object, instead got a '${typeof obj}'`) if (!Validator.isFunction(propFilter)) throw new TypeError(`The argument 'propFilter' must be a function, instead got a '${typeof propFilter}'`) const objFiltered = {} for (const [key, value] of Object.entries(obj)) { if (propFilter(key) === true) { objFiltered[key] = value } } return objFiltered } /** * Throw if the given argument is an error instance or its subclass. * * See {@link Validator.isError}. * * @static * @param {?object} arg the object to check * @throws {Error} the given error */ static throwOnError (arg) { if (Validator.isError(arg)) { throw arg } } /** * Throw if the given argument is false. * Note that this is similar to assertions. * * See {@link Validator.isError}. * * @static * @param {?object} arg the object to check * @param {string} [name='arg'] the name to use in generated error (or the value of first argument if not given) * @throws {Error} if the given argument is not a boolean, or if it's false */ static throwOnFalse (arg, name = 'arg') { if (!Validator.isBoolean(arg) || arg === false) { return new Error(`The argument '${name}' is false`) } } } module.exports = Validator