UNPKG

blow-validate

Version:
109 lines (108 loc) 4.21 kB
'use strict'; const Joi = require('joi'); const rxjs_1 = require('rxjs'); const ValidationResult_1 = require('./ValidationResult'); const ValidationError_1 = require('./ValidationError'); const JOIValidations = [ { validation: 'valid' }, { validation: 'invalid' }, { validation: 'required' }, { validation: 'optional' }, { validation: 'forbidden' }, { validation: 'min' }, { validation: 'max' }, { validation: 'length' }, { validation: 'unique' }, { validation: 'pattern' }, { validation: 'email' }, { validation: 'string' }, { validation: 'number' }, { validation: 'date' }, { validation: 'array' }, { validation: 'object' } ]; const JOI_VALIDATION_OPTIONS = { abortEarly: false, allowUnknown: true }; function isJOIValidation(name) { return JOIValidations.some(v => v['validation'] === name); } class Validator { constructor(schema) { this._schema = schema || {}; this._compile(); } _compile() { const properties = Object.keys(this._schema); this._compiledJoiSchema = {}; this._compiledCustomSchema = {}; for (const property of properties) { const validations = Object.keys(this._schema[property]); let propertyJoiSchema; let propertyCustomSchema; for (const validation of validations) { if (isJOIValidation(validation)) { if (!propertyJoiSchema) { propertyJoiSchema = Joi; } let options = this._schema[property][validation]; if (validation === 'email') { options = undefined; } propertyJoiSchema = propertyJoiSchema[validation](options); } else { if (!propertyCustomSchema) { propertyCustomSchema = []; } propertyCustomSchema.push({ name: validation, fn: this._schema[property][validation] }); } } if (propertyJoiSchema) { this._compiledJoiSchema[property] = propertyJoiSchema; } if (propertyCustomSchema) { this._compiledCustomSchema[property] = propertyCustomSchema; } } } _validateJoi(data) { if (!Object.keys(this._compiledJoiSchema).length) { return rxjs_1.Observable.of(new ValidationResult_1.ValidationResult()); } return rxjs_1.Observable.create(subscriber => { Joi.validate(data, this._compiledJoiSchema, JOI_VALIDATION_OPTIONS, err => { if (err) { const createError = e => ValidationError_1.ValidationError.create({ property: e.path, type: e.type.split('.')[1], message: e.message }); subscriber.next(err.details.map(createError)); } subscriber.complete(); }); }) .defaultIfEmpty() .map(errors => new ValidationResult_1.ValidationResult(errors)); } _validateCustom(data) { const properties = Object.keys(this._compiledCustomSchema); if (!properties.length) { return rxjs_1.Observable.of(ValidationResult_1.ValidationResult.create()); } return rxjs_1.Observable.from(properties) .map(property => [property, this._compiledCustomSchema[property]]) .mergeMap(row => rxjs_1.Observable.from(row[1]).mergeMap((v) => v.fn.bind(data)(row[0]))) .filter(e => !!e) .map(e => ValidationError_1.ValidationError.create({ property: e.path, type: e.type, message: e.message })) .toArray() .defaultIfEmpty() .map(ValidationResult_1.ValidationResult.create); } validate(data) { const mapResults = (joiResult, customResult) => joiResult.merge(customResult); return rxjs_1.Observable.combineLatest(this._validateJoi(data), this._validateCustom(data), mapResults); } static create(schema) { return new Validator(schema); } } exports.Validator = Validator;