import { observable , observe , notify , notifyByPath , computed , watch , extend as reactiveExtend , invisibleWork , } from '@src/store/reactive' ; import { ChartState , InitStoreState , ActionFunc , StoreOptions , ComputedFunc , WatchFunc , StoreModule , ObserveFunc , Options , } from '@t/store/store' ; import { isUndefined , forEach , pickPropertyWithMakeup , deepCopy } from '@src/helpers/utils' ; export default class Store < T extends Options > { state ! : ChartState < T > ; initStoreState ! : InitStoreState < T > ; computed : Record < string , any > = { } ; actions : Record < string , ActionFunc > = { } ; constructor ( initStoreState ) { this . initStoreState = deepCopy ( initStoreState ) ; this . setRootState ( { } ) ; } setRootState ( state ) { observable ( state ) ; this . state = state as ChartState < T > ; } setComputed ( namePath , fn , holder = this . computed ) { const splited = namePath . split ( '.' ) ; const key = splited . splice ( splited . length - 1 , 1 ) [ 0 ] ; const target = pickPropertyWithMakeup ( holder , splited ) ; computed ( target , key , fn . bind ( null , this . state , this . computed ) ) ; } setWatch ( namePath , fn ) { return watch ( this , namePath , fn ) ; } setAction ( name , fn ) { this . actions [ name ] = fn ; } dispatch ( name , payload ? , isInvisible ? ) { if ( isInvisible ) { invisibleWork ( ( ) => { this . actions [ name ] . call ( this , this , payload ) ; } ) ; } else { this . actions [ name ] . call ( this , this , payload ) ; } } observe ( fn ) { return observe ( fn . bind ( this , this . state , this . computed ) ) ; } observable ( target ) { return observable ( target ) ; } notifyByPath ( namePath ) { notifyByPath ( this , namePath ) ; } notify < T extends Record < string , any > , K extends keyof T > ( target , key ) { notify ( target , key ) ; } setModule ( name , param ? ) { if ( ! param ) { param = name as StoreModule ; name = ( param as StoreModule ) . name ; } if ( param . state ) { const moduleState = typeof param . state === 'function' ? param . state ( this . initStoreState ) : param . state ; extend ( this . state , moduleState ) ; } if ( param . computed ) { forEach ( param . computed , ( item , key ) => { this . setComputed ( key , item ) ; } ) ; } if ( param . watch ) { forEach ( param . watch , ( item , key ) => { this . setWatch ( key , item ) ; } ) ; } if ( param . action ) { forEach ( param . action , ( item , key ) => { this . setAction ( key , item ) ; } ) ; } if ( param . observe ) { forEach ( param . observe , ( item ) => { this . observe ( item ) ; } ) ; } } setValue ( target , key , source ) { extend ( target , { [ key ] : source , } ) ; } } export function extend < T extends Record < string , any > > ( target , source ) { const newItems = { } ; for ( const k in source ) { if ( ! source . hasOwnProperty ( k ) ) { continue ; } if ( ! isUndefined ( target [ k ] ) ) { if ( typeof source [ k ] === 'object' && ! Array . isArray ( source [ k ] ) ) { extend ( target [ k ] , source [ k ] ! ) ; } else { target [ k ] = source [ k ] ! ; } } else { newItems [ k ] = source [ k ] ; } } if ( Object . keys ( newItems ) . length ) { reactiveExtend ( target , newItems ) ; } }