import is from 'is-type-of' ; import validator from 'validator' ; import _ from 'ramda' ; export interface Expect { required ? : boolean ; enum ? : any [ ] ; default ? : any ; properties ? : any ; [ name ] : any ; } const cRequired = ( input , expect = { } ) => { if ( expect . required && input === undefined ) { return { is : false } ; } return { is : true , val : input } ; } ; const cNullable = ( input , expect = { } ) => { if ( expect . nullable && is . null ( input ) ) { return { is : true , val : input } ; } return { is : false , val : input } ; } ; const cEnum = ( input , expect = { } ) => { if ( Array . isArray ( expect . enum ) && expect . enum . length ) { return expect . enum . includes ( input ) ? { is : true , val : input } : { is : false } ; } return { is : true , val : input } ; } ; const cDefault = ( input , expect = { } ) => expect . default !== undefined && input === undefined ? { is : true , val : expect . default } : { is : true , val : input } ; const cString = ( val , expect ) => { if ( ! cRequired ( val , expect ) . is ) return { is : false } ; if ( expect . enum && ! cEnum ( val , expect ) . is ) return { is : false } ; if ( expect . format && ! cFormat ( val , expect ) . is ) return { is : false } ; return typeof val === 'string' ? { is : true , val : String ( val ) } : { is : false } ; } ; const cFormat = ( val , expect ) => { if ( expect . format === 'email' && ! validator . isEmail ( val ) ) return { is : false } ; if ( expect . format === 'uuid' && ! validator . isUUID ( val ) ) return { is : false } ; if ( ( expect . format === 'date' || expect . format === 'date-time' ) && ! validator . isRFC3339 ( val ) ) return { is : false } ; if ( expect . format === 'byte' && ! validator . isBase64 ( val ) ) return { is : false } ; if ( expect . format === 'ipv4' && ! validator . isIP ( val , 4 ) ) return { is : false } ; if ( expect . format === 'ipv6' && ! validator . isIP ( val , 6 ) ) return { is : false } ; return { is : true , val : String ( val ) } ; } ; const cNum = ( val , expect ) => { if ( ! cRequired ( val , expect ) . is ) return { is : false } ; if ( expect . enum && ! cEnum ( Number ( val ) , expect ) . is ) return { is : false } ; if ( isNaN ( Number ( val ) ) || val === '' ) return { is : false } ; if ( expect . minimum && expect . minimum > Number ( val ) ) return { is : false } ; if ( expect . maximum && expect . maximum < Number ( val ) ) return { is : false } ; return { is : true , val : Number ( val ) } ; } ; const cBool = ( val , expect ) => { if ( ! cRequired ( val , expect ) . is ) return { is : false } ; const cond = _ . cond ( [ [ _ . equals ( 'true' ) , _ . always ( { is : true , val : true } ) ] , [ _ . equals ( 'false' ) , _ . always ( { is : true , val : false } ) ] , [ _ . T , _ . always ( { is : typeof val === 'boolean' , val } ) ] ] ) ; return cond ( val ) ; } ; const cObject = ( input , expect = { } ) => { if ( ! cRequired ( input , expect ) . is ) return { is : false } ; const res = { is : true , val : input } ; if ( ! is . object ( input ) ) return { is : false } ; if ( ! expect . properties ) return res ; for ( const key of Object . keys ( expect . properties ) ) { if ( ! expect . properties [ key ] . required && input [ key ] === undefined ) { continue ; } const { is , val } = check ( input [ key ] , expect . properties [ key ] ) ; if ( ! is ) { console . log ( 'error object properties:' , key ) ; res . is = false ; break ; } input [ key ] = is ? val : input [ key ] ; } return res ; } ; const cArray = ( input , expect ) => { if ( ! cRequired ( input , expect ) . is ) return { is : false } ; const res = { is : true , val : input } ; if ( ! Array . isArray ( input ) ) { return { is : false } ; } if ( ! expect . items ) { return res ; } if ( is . object ( expect . items ) ) { for ( const item of input ) { const { is } = check ( item , expect . items ) ; if ( ! is ) { res . is = false ; return res ; } } } if ( is . string ( expect . items ) ) { const check = ( func ) => ( ) => input . length === input . filter ( item => func ( item ) ) . length ; const cond = _ . cond ( [ [ _ . equals ( 'string' ) , check ( is . string ) ] , [ _ . equals ( 'boolean' ) , check ( is . boolean ) ] , [ _ . equals ( 'number' ) , check ( is . number ) ] , [ _ . equals ( 'object' ) , check ( is . object ) ] , [ _ . equals ( 'array' ) , check ( is . array ) ] , [ _ . T , true ] ] ) ; return { is : cond ( expect . items ) , val : input } ; } return res ; } ; const check = ( input , expect ) => { const r = cNullable ( input , expect ) ; if ( r . is === true ) return r ; const cond = _ . cond ( [ [ _ . equals ( 'string' ) , ( ) => cString ( input , expect ) ] , [ _ . equals ( 'boolean' ) , ( ) => cBool ( input , expect ) ] , [ _ . equals ( 'number' ) , ( ) => cNum ( input , expect ) ] , [ _ . equals ( 'object' ) , ( ) => cObject ( input , expect ) ] , [ _ . equals ( 'array' ) , ( ) => cArray ( input , expect ) ] , [ _ . T , ( ) => ( { is : true , val : input } ) ] ] ) ; return cond ( expect . type ) ; } ; const Checker = { required : cRequired , object : cObject , string : cString , num : cNum , bool : cBool , default : cDefault , array : cArray , check } ; export default Checker ;