UNPKG

validator-list

Version:
184 lines (183 loc) 8.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.validate = void 0; const _ = require("lodash"); const _String = require("underscore.string"); const abstract_validator_1 = require("./validators/abstract-validator"); const async_filter_validator_1 = require("./validators/async-filter-validator"); const async_default_value_validator_1 = require("./validators/async-default-value-validator"); const required_validator_1 = require("./validators/required-validator"); const array_validator_1 = require("./validators/array-validator"); const boolean_validator_1 = require("./validators/boolean-validator"); const async_compare_validator_1 = require("./validators/async-compare-validator"); const number_validator_1 = require("./validators/number-validator"); const email_validator_1 = require("./validators/email-validator"); const async_range_validator_1 = require("./validators/async-range-validator"); const regular_expression_validator_1 = require("./validators/regular-expression-validator"); const string_validator_1 = require("./validators/string-validator"); const base_validator_1 = require("./validators/base-validator"); class Validator { constructor(rules, data, attributeLabels = {}, mixin = {}) { this.rules = rules; this.data = data; this.attributeLabels = attributeLabels; this.mixin = mixin; this.errors = {}; this.requireErrors = []; this.defaultValidators = { filter: async_filter_validator_1.AsyncFilterValidator, default: async_default_value_validator_1.AsyncDefaultValueValidator, required: required_validator_1.RequiredValidator, array: array_validator_1.ArrayValidator, boolean: boolean_validator_1.BooleanValidator, compare: async_compare_validator_1.AsyncCompareValidator, double: number_validator_1.NumberValidator, email: email_validator_1.EmailValidator, id: { class: number_validator_1.NumberValidator, options: { integerOnly: true, min: 1, tooSmall: '{attribute} must be correct id.' } }, in: async_range_validator_1.AsyncRangeValidator, integer: { class: number_validator_1.NumberValidator, options: { integerOnly: true } }, match: regular_expression_validator_1.RegularExpressionValidator, number: number_validator_1.NumberValidator, string: string_validator_1.StringValidator }; for (const rule of this.rules) { if (rule.length < 2) { throw new Error(`Rule should contain at least 2 arguments: ${rule}`); } const validator = _.isString(rule[1]) ? rule[1].trim() : rule[1]; if (!_.isFunction(validator) && !_.has(this.defaultValidators, validator)) { throw new Error(`Validator not found ${validator}`); } } this.rules = _.sortBy(this.rules, function (rule) { switch (rule[1]) { case 'required': return 1; case 'filter': return 2; case 'default': return 4; default: return 3; } }); } async validate() { for (const rule of this.rules) { const attributes = _.isArray(rule[0]) ? rule[0] : [rule[0]]; const validator = rule[1]; let options = rule[2] || {}; options.mixin = _.extend({}, this.mixin); if (_.isFunction(validator)) { for (const attribute of attributes) { if (await this.isAvailableForValidation(this.data[attribute], attribute, options)) { const error = await validator(this.data[attribute], this.getAttributeLabel(attribute, options.lowercaseLabel), options); if (error) { this.addError(attribute, error); } } } } else if (_.isString(validator)) { if (validator === 'filter') { for (const attribute of attributes) { const attributeLabel = this.getAttributeLabel(attribute, options.lowercaseLabel); if (_.isFunction(options.skip) && await options.skip(this.data[attribute], attributeLabel, options)) { continue; } // hasOwnProperty returns false for getters/setters if (attribute in this.data) { this.data[attribute] = await async_filter_validator_1.AsyncFilterValidator.validate(options.filter, this.data[attribute]); } } } else if (validator === 'required') { for (const attribute of attributes) { const attributeLabel = this.getAttributeLabel(attribute, options.lowercaseLabel); if (_.isFunction(options.skip) && await options.skip(this.data[attribute], attributeLabel, options)) { continue; } const error = new required_validator_1.RequiredValidator(attributeLabel, this.data[attribute], options).validate(); if (error) { this.addError(attribute, error); this.requireErrors.push(attribute); } } } else if (validator === 'default') { for (const attribute of attributes) { if (_.isFunction(options.skip) && await options.skip(this.data[attribute], this.getAttributeLabel(attribute, options.lowercaseLabel), options)) { continue; } if (!this.isHasError(attribute)) { this.data[attribute] = await async_default_value_validator_1.AsyncDefaultValueValidator.validate(this.data[attribute], options.value); } } } else { let validatorClass = this.defaultValidators[validator]; if (!abstract_validator_1.AbstractValidator.isPrototypeOf(validatorClass)) { options = _.extend(options, validatorClass.options); validatorClass = validatorClass.class; } for (const attribute of attributes) { if (await this.isAvailableForValidation(this.data[attribute], attribute, options)) { const error = await new validatorClass(this.getAttributeLabel(attribute, options.lowercaseLabel), this.data[attribute], options).validate(); if (error) { this.addError(attribute, error); } } } } } } return _.size(this.errors) ? this.errors : undefined; } isHasError(attribute) { return _.has(this.errors, attribute); } addError(attribute, error) { if (!this.errors[attribute]) { this.errors[attribute] = []; } this.errors[attribute].push(error); } async isAvailableForValidation(value, attribute, options) { if (_.isFunction(options.skip) && await options.skip(value, this.getAttributeLabel(attribute, options.lowercaseLabel), options)) { return false; } if (this.requireErrors.indexOf(attribute) !== -1) { return false; } if (options.skipOnEmpty && base_validator_1.BaseValidator.isEmptyValue(value)) { return false; } if (options.skipOnError && this.isHasError(attribute)) { return false; } return true; } getAttributeLabel(attribute, lowercase) { let label = !_.isUndefined(this.attributeLabels) && !_.isUndefined(this.attributeLabels[attribute]) ? this.attributeLabels[attribute] : attribute; label = _String.humanize(label); return lowercase ? _String.decapitalize(label) : label; // label = label.replace(/_/g, ' ').trim(); // return lowercase ? _String.decapitalize(label) : _String.capitalize(label); } } const validate = async function (rules, data, attributeLabels, mixin) { return await new Validator(rules, data, attributeLabels, mixin).validate(); }; exports.validate = validate;