import Validator , { RuleItem , Rules , ValidateSource } from 'async-validator' ; import { toPath , setWith , get , set , } from './utils' ; const getRulePath = ( path ) => toPath ( path ) . join ( '.fields.' ) ; const getRule = ( rules , path ) => { const rulePath = getRulePath ( path ) ; return get ( rules , rulePath ) as RuleItem ; } ; const setRule = ( rules , path , rule ) => { const rulePath = getRulePath ( path ) ; const pathArr = toPath ( path ) ; let index = 0 ; return setWith ( rules , rulePath , rule , ( pathValue , key ) => { if ( key !== 'fields' ) { index += 1 ; const type = /^\d$/ . test ( pathArr [ index ] ) ? 'array' : 'object' ; return pathValue || ( { type , } as RuleItem ) ; } return pathValue ; } ) ; } ; export type Errors = { [ key ] : { message : string ; field : string ; } ; } ; const DeepValidator = ( rules = { } ) => { const registerRule = ( path , rule ) => { setRule ( rules , path , rule ) ; } ; const removeRule = ( path ) => { setRule ( rules , path , { } ) ; } ; const validate = async ( data ) => { try { await new Validator ( rules ) . validate ( data ) ; return undefined ; } catch ( { errors , fields } ) { const errorObject = Object . keys ( fields ) . reduce ( ( acc , key ) => { acc [ key ] = get ( fields , [ key , 0 ] ) ; return acc ; } , { } as Errors ) ; throw errorObject ; } } ; return { getRules : ( ) => rules , registerRule , removeRule , validate , validateField : async ( path , value ) => { const fieldRule = setRule ( { } , path , getRule ( rules , path ) ) ; try { await new Validator ( fieldRule ) . validate ( set ( { } , path , value ) ) ; return undefined ; } catch ( { fields } ) { throw get ( fields , [ path , 0 ] ) ; } } , } ; } ; export default DeepValidator ;