author Jeremy Daly <jeremy@jeremydaly.com>
 *  license import validateTypes from './validateTypes' ; import { error , transformAttr } from './utils' ; import { DocumentClient } from 'aws-sdk/clients/dynamodb' ; import Table from 'classes/Table' ; export default ( DocumentClient ) => ( schema , linked , data , filter = false ) => { const validateType = validateTypes ( DocumentClient ) ; const dependsOn = ( map , attr ) => { if ( schema [ attr ] . dependsOn ) { ( Array . isArray ( schema [ attr ] . dependsOn ) ? schema [ attr ] . dependsOn : [ schema [ attr ] . dependsOn ] ) . forEach ( ( dependent ) => { if ( schema [ dependent ] ) { if ( typeof map [ dependent ] === 'function' ) { map = dependsOn ( map , dependent ) ; } } else { error ( `'${ dependent }' is not a valid attribute or alias name` ) ; } } ) ; map [ attr ] = map [ attr ] ( map ) ; return map ; } else { try { map [ attr ] = map [ attr ] ( map ) ; if ( schema [ attr ] . alias ) map [ schema [ attr ] . alias ] = map [ attr ] ; if ( schema [ attr ] . map ) map [ schema [ attr ] . map ] = map [ attr ] ; } catch ( e ) { } return map ; } } ; let dataMap = Object . keys ( data ) . reduce ( ( acc , field ) => { return Object . assign ( acc , schema [ field ] ? { data : { ... acc . data , [ schema [ field ] . map || field ] : data [ field ] } , aliases : { ... acc . aliases , [ schema [ field ] . alias || field ] : data [ field ] } } : filter ? { } : field === '$remove' ? { data : { ... acc . data , $remove : data [ field ] } } : error ( `Field '${ field }' does not have a mapping or alias` ) ) ; } , { data : { } , aliases : { } } ) ; let defaultMap = { ... dataMap . data , ... dataMap . aliases } ; const defaults = Object . keys ( defaultMap ) . reduce ( ( acc , attr ) => { if ( typeof defaultMap [ attr ] === 'function' ) { let map = dependsOn ( defaultMap , attr ) ; defaultMap = map ; } return Object . assign ( acc , { [ attr ] : defaultMap [ attr ] } ) ; } , { } ) ; let _data = Object . keys ( dataMap . data ) . reduce ( ( acc , field ) => { return Object . assign ( acc , { [ field ] : defaults [ field ] } ) ; } , { } ) ; let composites = Object . keys ( linked ) . reduce ( ( acc , attr ) => { const field = ( schema [ attr ] && schema [ attr ] . map ) || attr ; if ( _data [ field ] !== undefined ) return acc ; let values = linked [ attr ] . map ( ( f ) => { if ( _data [ f ] === undefined ) { return null ; } return transformAttr ( schema [ f ] , validateType ( schema [ f ] , f , _data [ f ] ) , _data ) ; } ) . filter ( ( x ) => x !== null ) ; if ( values . length === linked [ attr ] . length ) { return Object . assign ( acc , { [ field ] : values . join ( schema [ attr ] . delimiter || '#' ) } ) ; } else { return acc ; } } , { } ) ; return Object . assign ( composites , _data ) ; } ;