import { get } from 'lodash' ; import { Reducer } from 'redux-actions' ; import { IDefinitionReducerMap , IInvokeDefinitionOptions , ReducerMapOrConstructor , IReducerDefinition , DefinitionGenerator } from '../types/definition' ; import { IModelDefinition } from '../types/model' ; import { makeScope } from '../makeScope' ; import { getActionType } from '../utils' ; import { getFormattedInitialState } from './initialState' ; import { ISelector , ISelectorMap } from '../types/selector' ; export interface ICreateModelGenerator < LocalState > { options : IInvokeDefinitionOptions ; defaultState : any ; reducerMap : ReducerMapOrConstructor < LocalState > ; selectorMap : ISelectorMap < LocalState > ; transformInitialState ? : ( state : any , params : { namespacing : string [ ] ; } ) => LocalState ; } export const createModelGenerator = < LocalState > ( params ) => ( namespacing ) : IModelDefinition < LocalState > => { const { options , defaultState , reducerMap , selectorMap , transformInitialState , } = params ; const formattedInitialState = getFormattedInitialState < typeof defaultState > ( { initialState : options . initialState , defaultState , transformInitialState , namespacing } ) ; const model = { kind : 'definition' , actions : { } , initialState : formattedInitialState , reducers : { } , selectors : { } } ; let reducers ; if ( typeof reducerMap === 'function' ) { reducers = reducerMap ( options ) ; } else { reducers = reducerMap ; } type ReducerTuple = [ string , Reducer < LocalState , any > ] ; const scope = makeScope ( namespacing ) ; for ( const [ key , fn ] of Object . entries ( reducers ) as ReducerTuple [ ] ) { const type = getActionType ( namespacing , key ) ; const { reducer , action } = scope ( type , fn ) ; model . reducers [ type ] = reducer ; model . actions [ key ] = action ; } type SelectorTuple = [ string , ISelector < LocalState > ] ; for ( const [ key , fn ] of Object . entries ( selectorMap ) as SelectorTuple [ ] ) { const selector = ( state , args ? ) => fn ( get ( state , namespacing ) , args ) ; model . selectors [ key ] = selector ; } return model ; } ;