import { IProperty , ISerializationSchema , ISerializer , ISerializerConfig , } from './types' ; import { DATA_TYPE } from './constants' ; const defaultParsers = { [ DATA_TYPE . BOOL ] : Boolean , [ DATA_TYPE . NUMBER ] : Number , [ DATA_TYPE . STRING ] : String , } ; param key param properties export const getPropertyForKey = ( key , properties = [ ] ) : IProperty => properties . find ( ( property ) => property . name === key ) ; param names param availableParsers export const getParsers = ( names , availableParsers ) => { const namesSet = new Set ( names ) ; return ( Object as any ) . entries ( availableParsers ) . filter ( ( [ key , parser ] ) => namesSet . has ( key ) ) . map ( ( [ key , parser ] ) => parser ) ; } ; param type param configurations export const getConfigurationForType = ( type , configurations ) => configurations . find ( ( configuration ) => configuration . name === type ) ; param firstArray param secondArray export const hasIntersection = ( firstArray , secondArray ) : boolean => { const secondArraySet = new Set ( secondArray ) ; return ( firstArray . filter ( ( value ) => secondArraySet . has ( value ) ) . length > 0 ) ; } ; param data param groups param properties param parsers export const serialize = ( data , groups , properties , parsers ) => ( Object as any ) . entries ( data ) . filter ( ( [ key , value ] ) => { const property = getPropertyForKey ( key , properties ) ; return ( property && ( ! property . groups || hasIntersection ( property . groups , groups ) ) ) ; } ) . reduce ( ( result , [ key , value ] ) => { const property = getPropertyForKey ( key , properties ) ; const propertyKey = property . serializedName || key ; return Object . assign ( result , { [ propertyKey ] : serializeEntry ( value , groups , property , parsers ) } ) ; } , { } ) ; param value param groups param property param availableParsers export const serializeEntry = ( value , groups , property , availableParsers ) : any => { const parsers = getParsers ( [ ... ( property . parsers || [ ] ) , property . type ] , availableParsers ) ; let serializedValue = value ; if ( property . properties && property . type === DATA_TYPE . OBJECT ) { serializedValue = serialize ( value , groups , property . properties , availableParsers ) ; } if ( property . properties && property . type === DATA_TYPE . ARRAY ) { serializedValue = value . map ( ( childValue ) => serialize ( childValue , groups , property . properties , availableParsers ) ) . reduce ( ( result , currentValue ) => [ ... result , currentValue ] , [ ] ) ; } if ( parsers ) { serializedValue = parsers . reduce ( ( accumulator , parser ) => parser ( accumulator ) , serializedValue ) ; } return serializedValue ; } ; param configuration param options const serializerProvider = ( config ) => { const parsers = { ... defaultParsers , ... ( config . parsers || { } ) , } as any ; const schemas = config . schemas || [ ] ; return { addParser : ( parser , key ) => { parsers [ key ] = parser ; return parser ; } , addSchema : ( schema ) => { schemas . push ( schema ) ; return schemas ; } , serialize : ( data , groups , configurationName ? ) => { const name = configurationName || data . constructor . name ; const foundConfiguration = schemas . find ( ( configuration ) => configuration . name === name ) ; if ( ! foundConfiguration ) { return Promise . reject ( new Error ( 'Configuration not found' ) ) ; } return Promise . resolve ( foundConfiguration ) . then ( ( schema ) => data && serialize ( data , groups , schema . properties , parsers ) ) ; } , } as ISerializer ; } ; export default serializerProvider ;