UNPKG

blow-data

Version:
83 lines (76 loc) 2.46 kB
'use strict'; import * as Joi from 'joi'; import {isFunction} from 'util'; import {Observable} from 'rxjs'; import {ValidationResult} from './ValidationResult'; import {IValidator, IValidationResult} from './interfaces'; export class Validator implements IValidator { protected _syncSchema; protected _asyncSchema; constructor(syncSchema, asyncSchema?) { this._syncSchema = syncSchema; this._asyncSchema = asyncSchema; } protected _syncValidate(data) { if(!this._syncSchema) { return Observable.of([]); } const validationOptions = { abortEarly: false, allowUnknown: true }; const result = Joi.validate(data, this._syncSchema, validationOptions); if(!result.error) { return Observable.of([]); } return Observable.of(result.error.details.map(r => { r['property'] = r['path']; const type = r['type'].split('.'); if(type.length > 1) { type.shift(); } r['type'] = type.join('.'); delete r['context']; delete r['path']; return r; })); } protected _asyncValidate(data) { if(!this._asyncSchema) { return Observable.of([]); } return Observable.from(Object.keys(this._asyncSchema)) .mergeMap(propertyName => { return Observable.from(this._asyncSchema[<string>propertyName]) .mergeMap(validator => { const result = (<Function>validator).bind(data)(propertyName); if(isFunction(result.subscribe)) { return result; } return Observable.of(result); }) .map(errorMessage => { if(errorMessage) { return { property: propertyName, type: 'custom', message: errorMessage }; } return null; }); }) .toArray() .map(result => result.reduce((aggr, curr) => { if(curr) { (<[]>aggr).push(curr); } return aggr; }, [])); } validate(data): Observable<IValidationResult> { const mapResults = (sync, async) => sync.concat(async); return Observable.combineLatest(this._syncValidate(data), this._asyncValidate(data), mapResults) .map(resultRaw => new ValidationResult(resultRaw)); } }