UNPKG

topkat-utils

Version:

A comprehensive collection of TypeScript/JavaScript utility functions for common programming tasks. Includes validation, object manipulation, date handling, string formatting, and more. Zero dependencies, fully typed, and optimized for performance.

209 lines 11.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validatorReturnErrArray = exports.isType = exports.isValid = exports.validator = exports.checkCtxIntegrity = exports.checkAllObjectValuesAreEmpty = exports.isDateObject = exports.isEmptyOrNotSet = exports.issetOr = void 0; //---------------------------------------- // VALIDATION UTILS //---------------------------------------- const isset_1 = require("./isset"); const date_utils_1 = require("./date-utils"); const array_utils_1 = require("./array-utils"); const config_1 = require("./config"); const is_empty_1 = require("./is-empty"); const error_utils_1 = require("./error-utils"); const remove_circular_json_stringify_1 = require("./remove-circular-json-stringify"); function issetOr(...elms) { return elms.some(elm => typeof elm !== 'undefined' && elm !== null); } exports.issetOr = issetOr; function isEmptyOrNotSet(...elms) { return elms.some(elm => !(0, isset_1.isset)(elm) || (0, is_empty_1.isEmpty)(elm)); } exports.isEmptyOrNotSet = isEmptyOrNotSet; function isDateObject(variable) { return variable instanceof Date; } exports.isDateObject = isDateObject; /** Check all values are set */ function checkAllObjectValuesAreEmpty(o) { return Object.values(o).every(value => !(0, isset_1.isset)(value)); } exports.checkAllObjectValuesAreEmpty = checkAllObjectValuesAreEmpty; /** Throw an error in case data passed is not a valid ctx */ function checkCtxIntegrity(ctx) { if (!(0, isset_1.isset)(ctx) || !(0, isset_1.isset)(ctx.user)) throw new error_utils_1.DescriptiveError('ctxNotSet', { code: 500 }); } exports.checkCtxIntegrity = checkCtxIntegrity; function validator(...paramsToValidate) { const errArray = validatorReturnErrArray(...paramsToValidate); if (errArray.length) throw new error_utils_1.DescriptiveError(...errArray); } exports.validator = validator; /** Same as validator but return a boolean * See {@link validator} */ function isValid(...paramsToValidate) { const errArray = validatorReturnErrArray(...paramsToValidate); return errArray.length ? false : true; } exports.isValid = isValid; function parseValueForDisplay(value) { try { if (value === undefined) return 'undefined'; else if (value?.data?.data) return { ...value, data: 'Buffer' }; else return (0, remove_circular_json_stringify_1.removeCircularJSONstringify)(value).substring(0, 999); } catch (_) { return value; } } /** Default types + custom types * 'objectId','dateInt6','dateInt','dateInt8','dateInt12','time','humanReadableTimestamp','date','array','object','buffer','string','function','boolean','number','bigint', */ function isType(value, type) { return isValid({ name: 'Is type check', value, type, emptyAllowed: true }); } exports.isType = isType; function validatorReturnErrArray(...paramsToValidate) { const paramsFormatted = []; // support for multiple names with multiple values for one rule. Eg: {name: [{startDate:'20180101'}, {endDate:'20180101'}], type: 'dateInt8'} paramsToValidate.forEach(param => { if (typeof param !== 'object' || Array.isArray(param)) throw new error_utils_1.DescriptiveError(`wrongTypeForDataValidatorArgument`, { code: 500, origin: 'Generic validator', expectedType: 'object', actualType: Array.isArray(param) ? 'array' : typeof param }); // parse => name: {myVar1: 'blah, myvar2: myvar2} if (typeof param.name === 'object' && !Array.isArray(param.name)) Object.keys(param.name).forEach(name => paramsFormatted.push(Object.assign({}, param, { name: name, value: param?.name?.[name] }))); else paramsFormatted.push(param); }); for (const paramObj of paramsFormatted) { let name = paramObj.name; const hasValue = paramObj.hasOwnProperty('value'); let value = paramObj.value; let optional = paramObj.optional || false; const emptyAllowed = optional || paramObj.emptyAllowed || false; if (paramObj.isset === false) paramObj.mustNotBeSet = true; // ALIAS const errMess = (msg, extraInfos = {}, errCode = 422) => [msg, { code: errCode, origin: 'Generic validator', varName: name, varType: typeof value, gotValue: parseValueForDisplay(value), ...extraInfos }]; // accept syntax { 'myVar.var2': myVar.var2, ... } if (typeof name !== 'undefined' && !hasValue) { name = Object.keys(paramObj).find(param => !['name', 'value', 'type', 'eq', 'neq', 'in', 'lt', 'gt', 'lte', 'gte', 'length', 'minLength', 'maxLength', 'emptyAllowed', 'regexp', 'mustNotBeSet', 'isset', 'optional', 'isArray'].includes(param)); if (typeof name !== 'undefined') value = paramObj[name]; } // if nameString ends by $ sign it is optional if (typeof name !== 'undefined' && /.*\$$/.test(name)) { name = name.substr(0, name.length - 1); optional = true; } // DEFINED AND NOT EMPTY if ((typeof value === 'undefined') && optional) continue; if (typeof value !== 'undefined' && value !== null && paramObj.mustNotBeSet) return errMess('variableMustNotBeSet'); if (paramObj.mustNotBeSet) continue; // exit if (typeof value === 'undefined') return errMess('requiredVariableEmptyOrNotSet'); if (!emptyAllowed && value === '') return errMess('requiredVariableEmpty'); const isArray = paramObj.isArray; if (isArray && !Array.isArray(value)) return errMess('wrongTypeForVar', { expectedType: 'array', gotType: typeof value }); // TYPE if (typeof paramObj.type !== 'undefined') { const types = (0, array_utils_1.asArray)(paramObj.type); // support for multiple type const areSomeTypeValid = types.some(type => { if (type.endsWith('[]')) { if (!Array.isArray(value)) errMess('wrongTypeForVar', { expectedType: 'array', gotType: typeof value }); type = type.replace('[]', ''); } const allTypes = [ 'objectId', 'dateInt6', 'dateInt', 'dateInt8', 'dateInt12', 'time', 'humanReadableTimestamp', 'date', 'dateObject', 'array', 'object', 'buffer', 'string', 'function', 'boolean', 'number', 'bigint', 'year', 'any', 'email', //...Object.keys(configFn().customTypes) ]; if (!allTypes.includes(type)) throw new error_utils_1.DescriptiveError('typeDoNotExist', { code: 500, type }); const basicTypeCheck = { objectId: val => /^[0-9a-fA-F-]{24,}$/.test(val), dateInt6: val => (0, date_utils_1.isDateIntOrStringValid)(parseInt(val + '01'), true, 8), dateInt: val => (0, date_utils_1.isDateIntOrStringValid)(val, true, 8), dateInt8: val => (0, date_utils_1.isDateIntOrStringValid)(val, true, 8), dateInt12: val => (0, date_utils_1.isDateIntOrStringValid)(val, true, 12), time: val => /^\d\d:\d\d$/.test(val) && (0, date_utils_1.isTimeStringValid)(val), humanReadableTimestamp: val => (val + '').length === 17, date: val => (0, date_utils_1.isDateIsoOrObjectValid)(val, true), dateObject: val => (0, date_utils_1.isDateIsoOrObjectValid)(val, true), array: val => Array.isArray(val), object: val => !Array.isArray(val) && val !== null && typeof val === type, buffer: val => Buffer.isBuffer(val), year: val => /^\d\d\d\d$/.test(val), email: val => /^[^\s@]+@([^\s@.,]+\.)+[^\s@.,]+$/.test(val), any: () => true, }; return typeof basicTypeCheck?.[type] !== 'undefined' && basicTypeCheck?.[type](value) || typeof value === type && type !== 'object' || // for string, number, boolean... typeof (0, config_1.configFn)()?.customTypes?.[type] !== 'undefined' && (0, config_1.configFn)()?.customTypes?.[type]?.test(value); }); if (!areSomeTypeValid) return errMess(`wrongTypeForVar`, { expectedTypes: types.join(', '), gotType: Object.prototype.toString.call(value), gotValue: parseValueForDisplay(value) }); } // GREATER / LESS if (typeof paramObj.gte !== 'undefined' && value < paramObj.gte) return errMess(`valueShouldBeSuperiorOrEqualForVar`, { shouldBeSupOrEqTo: paramObj.gte }); if (typeof paramObj.lte !== 'undefined' && value > paramObj.lte) return errMess(`valueShouldBeInferiorOrEqualForVar`, { shouldBeInfOrEqTo: paramObj.lte }); if (typeof paramObj.gt !== 'undefined' && value <= paramObj.gt) return errMess(`valueShouldBeSuperiorForVar`, { shouldBeSupOrEqTo: paramObj.gt }); if (typeof paramObj.lt !== 'undefined' && value >= paramObj.lt) return errMess(`valueShouldBeInferiorForVar`, { shouldBeInfOrEqTo: paramObj.lt }); // IN VALUES if (typeof paramObj.in !== 'undefined') { const equals = Array.isArray(paramObj.in) ? paramObj.in : [paramObj.in]; if (!equals.some(equalVal => equalVal === value)) return errMess(`wrongValueForVar`, { supportedValues: parseValueForDisplay(equals) }); } // EQUAL (exact copy of .in) if (paramObj.hasOwnProperty('eq')) { const equals = Array.isArray(paramObj.eq) ? paramObj.eq : [paramObj.eq]; if (!equals.some(equalVal => equalVal === value)) return errMess(`wrongValueForVar`, { supportedValues: parseValueForDisplay(equals), }); } // NOT EQUAL if (paramObj.hasOwnProperty('neq')) { const notEquals = Array.isArray(paramObj.neq) ? paramObj.neq : [paramObj.neq]; if (notEquals.some(equalVal => equalVal === value)) return errMess(`wrongValueForVar`, { NOTsupportedValues: parseValueForDisplay(notEquals) }); } // INCLUDES if (typeof paramObj.includes !== 'undefined' && !value.includes(paramObj.includes)) return errMess(`wrongValueForVar`, { shouldIncludes: paramObj.includes }); // REGEXP if (typeof paramObj.regexp !== 'undefined' && !paramObj.regexp.test(value)) return errMess(`wrongValueForVar`, { shouldMatchRegexp: paramObj.regexp.toString() }); // MIN / MAX LENGTH works for number length. Eg: 20180101.length == 8 if (typeof paramObj.minLength !== 'undefined' && paramObj.minLength > (typeof value == 'number' ? value + '' : value).length) return errMess(`wrongLengthForVar`, { minLength: paramObj.minLength }); if (typeof paramObj.maxLength !== 'undefined' && paramObj.maxLength < (typeof value == 'number' ? value + '' : value).length) return errMess(`wrongLengthForVar`, { maxLength: paramObj.maxLength }); if (typeof paramObj.length !== 'undefined' && paramObj.length !== (typeof value == 'number' ? value + '' : value).length) return errMess(`wrongLengthForVar`, { length: paramObj.length }); } return []; } exports.validatorReturnErrArray = validatorReturnErrArray; //# sourceMappingURL=validation-utils.js.map