1
import { StonexModule } from '.'
2
import { copy, isType, noop, types } from './helpers/base'
4
declare interface EmptyStateMap {
5
[moduleName: string]: any
9
* StateWorker it is class which do all work
10
* linked with state inside each Stonex Module connected to the store
18
* import { StateWorker, StonexStore } from '../src'
19
* import modules, { Modules } from './modules'
21
* class SuperStateWorker extends StateWorker {
23
* getState(moduleName: string){
25
* return super.getState(moduleName)
29
* const store = new StonexStore<Modules>(modules,{
30
* stateWorker: SuperStateWorker
33
export class StateWorker<StateMap = EmptyStateMap> {
36
* Map of stonex module states
40
* @memberof StateWorker
42
public state: StateMap = {} as StateMap
45
* Method which calls when Stonex initializing state inside your module
47
* @param {StonexModule<State>} moduleInstance
51
public initializeState<State = any> (moduleInstance: StonexModule<State>): void {
52
this.state[moduleInstance.moduleName] = copy(moduleInstance.__initialState)
54
Object.defineProperty(moduleInstance, 'state', {
55
get: () => moduleInstance.getState(),
58
`State of the module ${moduleInstance.moduleName} is immutable.\r\n` +
59
`Please use "this.setState" for updating state of the ${moduleInstance.moduleName} module`
66
* Preparing new state to update
68
* @param {StonexModule<State>} moduleInstance
69
* @param {Partial<State> | ((state: State) => Partial<State>)} changes
70
* @param {function?} callback
74
public setState<State> (
75
moduleInstance: StonexModule<State>,
76
changes: Partial<State> | ((state: State) => Partial<State>),
77
callback: (state: State) => any = noop
79
const changesAsFunction = isType(changes, types.function)
80
const changeAction = (stateChanges: Partial<State>) => {
81
this.updateState<State>(moduleInstance, stateChanges)
82
callback(moduleInstance.state)
84
if (changesAsFunction) {
85
setTimeout(() => changeAction((changes as (state: State) => Partial<State>)(moduleInstance.state)), 0)
87
changeAction(changes as Partial<State>)
92
* Returns state of stonex module
94
* @param {string} moduleName
98
public getState<State> (moduleName: string): State {
99
return copy(this.state[moduleName])
103
* Reset state of stonex module
105
* @param {StonexModule<State>} moduleInstance
106
* @param {function?} callback
110
public resetState<State> (moduleInstance: StonexModule<State>, callback: (state: any) => any = noop): void {
111
return this.setState(moduleInstance, moduleInstance.__initialState, callback)
115
* Updating state of stonex module
117
* @param {StonexModule<State>} moduleInstance
118
* @param {Partial<State>} stateChanges
120
private updateState<State> (moduleInstance: StonexModule<State>, stateChanges: Partial<State>): void | never {
121
let flattedStateChanges = null
123
if (isType(stateChanges, types.function)) {
124
throw new Error(`State of ${moduleInstance.moduleName} module can not have the type of function`)
127
if (isType(stateChanges, types.object)) {
128
flattedStateChanges = { ...copy(stateChanges) }
130
flattedStateChanges = isType(stateChanges, types.array) ? [...copy(stateChanges)] : stateChanges
133
this.state[moduleInstance.moduleName] = flattedStateChanges