import { useEffect , useCallback , useState } from 'react' ; import EventEmitter from 'eventemitter3' ; import Container from './container' ; import { Bootstrap , Plugin } from '../index.d' ; const DISPATCH_TYPE = 'CS_DISPATCH_TYPE' ; const plugins = [ ] ; param { object } modules const bootstrap = < Modules > ( modules ) => { const container = new Container ( modules ) ; const pluginEmitter = new EventEmitter ( ) ; const dispatch = ( nameAndMethod , payload ) => { const [ namespace , methodName ] = nameAndMethod . split ( '/' ) ; const combineModule = container . getModule ( namespace ) ; const { state , reducers , effects } = combineModule [ namespace ] ; const rootState = container . getRootState ( ) ; if ( effects [ methodName ] ) { pluginEmitter . emit ( DISPATCH_TYPE , { type : nameAndMethod , payload } ) ; return effects [ methodName ] ( { state , payload , rootState , dispatch } ) ; } else if ( reducers [ methodName ] ) { const newState = reducers [ methodName ] ( { state , rootState , payload } ) ; container . setState ( namespace , newState ) ; pluginEmitter . emit ( DISPATCH_TYPE , { type : nameAndMethod , payload , newState } ) ; } } ; const injectFns = ( reducersOrEffects ) => { Object . keys ( reducersOrEffects ) . forEach ( ( key ) => { if ( ! dispatch [ key ] ) dispatch [ key ] = { } ; const originFns = reducersOrEffects [ key ] ; const fns = { } ; Object . keys ( originFns ) . forEach ( ( fnKey ) => { fns [ fnKey ] = ( payload ) => dispatch ( `${ key }/${ fnKey }` , payload ) ; } ) ; Object . assign ( dispatch [ key ] , fns ) ; } ) ; } ; function useModule ( namespace ) { const [ , setState ] = useState ( { } ) ; const setStateProxy = useCallback ( ( ) => setState ( { } ) , [ setState ] ) ; useEffect ( ( ) => { container . addListener ( namespace , setStateProxy ) ; return ( ) => container . removeListener ( namespace , setStateProxy ) ; } , [ namespace , setStateProxy ] ) ; return container . getState ( namespace ) ; } const rootReducers = container . getRootReducers ( ) ; const rootEffects = container . getRootEffects ( ) ; injectFns ( rootReducers ) ; injectFns ( rootEffects ) ; plugins . forEach ( ( plugin ) => plugin ( modules , pluginEmitter ) ) ; return { useModule : useModule as any , dispatch } ; } ; bootstrap . addPlugin = ( plugin ) => { plugins . push ( plugin ) ; } ; bootstrap . DISPATCH_TYPE = DISPATCH_TYPE ; export default bootstrap ;