import * as React from 'react' ; import inflection from 'inflection' ; import getValuesFromRecords from './getValuesFromRecords' ; import InferredElement from './InferredElement' ; import { isObject , valuesAreArray , valuesAreBoolean , valuesAreDate , valuesAreDateString , valuesAreHtml , valuesAreInteger , valuesAreNumeric , valuesAreObject , valuesAreString , } from './assertions' ; import { InferredTypeMap } from './types' ; const DefaultComponent = ( ) => < span > ; < /span>; const defaultType = { type : DefaultComponent , representation : ( ) => '<DefaultComponent />' , } ; const defaultTypes = { array : defaultType , boolean : defaultType , date : defaultType , email : defaultType , id : defaultType , number : defaultType , reference : defaultType , referenceArray : defaultType , richText : defaultType , string : defaultType , url : defaultType , } ; const hasType = ( type , types ) => typeof types [ type ] !== 'undefined' ; example example example param { string } name param { any [ ] } values param { Object } types return const inferElementFromValues = ( name , values = [ ] , types = defaultTypes ) => { if ( name === 'id' && hasType ( 'id' , types ) ) { return new InferredElement ( types . id , { source : name } ) ; } if ( name . substr ( name . length - 3 ) === '_id' && hasType ( 'reference' , types ) ) { const reference = inflection . pluralize ( name . substr ( 0 , name . length - 3 ) ) ; return ( types . reference && new InferredElement ( types . reference , { source : name , reference , } , new InferredElement ( types . referenceChild ) ) ) ; } if ( name . substr ( name . length - 2 ) === 'Id' && hasType ( 'reference' , types ) ) { const reference = inflection . pluralize ( name . substr ( 0 , name . length - 2 ) ) ; return ( types . reference && new InferredElement ( types . reference , { source : name , reference , } , new InferredElement ( types . referenceChild ) ) ) ; } if ( name . substr ( name . length - 4 ) === '_ids' && hasType ( 'referenceArray' , types ) ) { const reference = inflection . pluralize ( name . substr ( 0 , name . length - 4 ) ) ; return ( types . referenceArray && new InferredElement ( types . referenceArray , { source : name , reference , } , new InferredElement ( types . referenceArrayChild ) ) ) ; } if ( name . substr ( name . length - 3 ) === 'Ids' && hasType ( 'referenceArray' , types ) ) { const reference = inflection . pluralize ( name . substr ( 0 , name . length - 3 ) ) ; return ( types . referenceArray && new InferredElement ( types . referenceArray , { source : name , reference , } , new InferredElement ( types . referenceArrayChild ) ) ) ; } if ( values . length === 0 ) { return new InferredElement ( types . string , { source : name } ) ; } if ( valuesAreArray ( values ) ) { if ( isObject ( values [ 0 ] [ 0 ] ) && hasType ( 'array' , types ) ) { const leafValues = getValuesFromRecords ( values . reduce ( ( acc , vals ) => acc . concat ( vals ) , [ ] ) ) ; return ( types . array && new InferredElement ( types . array , { source : name , } , Object . keys ( leafValues ) . map ( leafName => inferElementFromValues ( leafName , leafValues [ leafName ] , types ) ) ) ) ; } return new InferredElement ( types . string , { source : name } ) ; } if ( valuesAreBoolean ( values ) && hasType ( 'boolean' , types ) ) { return new InferredElement ( types . boolean , { source : name } ) ; } if ( valuesAreDate ( values ) && hasType ( 'date' , types ) ) { return new InferredElement ( types . date , { source : name } ) ; } if ( valuesAreString ( values ) ) { if ( name === 'email' && hasType ( 'email' , types ) ) { return new InferredElement ( types . email , { source : name } ) ; } if ( name === 'url' && hasType ( 'url' , types ) ) { return new InferredElement ( types . url , { source : name } ) ; } if ( valuesAreDateString ( values ) && hasType ( 'date' , types ) ) { return new InferredElement ( types . date , { source : name } ) ; } if ( valuesAreHtml ( values ) && hasType ( 'richText' , types ) ) { return new InferredElement ( types . richText , { source : name } ) ; } return new InferredElement ( types . string , { source : name } ) ; } if ( ( valuesAreInteger ( values ) || valuesAreNumeric ( values ) ) && hasType ( 'number' , types ) ) { return new InferredElement ( types . number , { source : name } ) ; } if ( valuesAreObject ( values ) ) { const propName = Object . keys ( values [ 0 ] ) . shift ( ) ; const leafValues = values . map ( v => v [ propName ] ) ; return inferElementFromValues ( `${ name }.${ propName }` , leafValues , types ) ; } return new InferredElement ( types . string , { source : name } ) ; } ; export default inferElementFromValues ;