stonex

Форк
0
/
StateWorker.ts 
136 строк · 3.7 Кб
1
import { StonexModule } from '.'
2
import { copy, isType, noop, types } from './helpers/base'
3

4
declare interface EmptyStateMap {
5
  [moduleName: string]: any
6
}
7

8
/**
9
 * StateWorker it is class which do all work
10
 * linked with state inside each Stonex Module connected to the store
11
 *
12
 * @export
13
 * @class StateWorker
14
 * @template StateMap
15
 *
16
 *
17
 * @example
18
 * import { StateWorker, StonexStore } from '../src'
19
 * import modules, { Modules } from './modules'
20
 *
21
 * class SuperStateWorker extends StateWorker {
22
 *
23
 *  getState(moduleName: string){
24
 *    // own behaviour
25
 *    return super.getState(moduleName)
26
 *  }
27
 * }
28
 *
29
 * const store = new StonexStore<Modules>(modules,{
30
 *  stateWorker: SuperStateWorker
31
 * })
32
 */
33
export class StateWorker<StateMap = EmptyStateMap> {
34

35
  /**
36
   * Map of stonex module states
37
   *
38
   * @public
39
   * @type {StateMap}
40
   * @memberof StateWorker
41
   */
42
  public state: StateMap = {} as StateMap
43

44
  /**
45
   * Method which calls when Stonex initializing state inside your module
46
   *
47
   * @param {StonexModule<State>} moduleInstance
48
   *
49
   * @public
50
   */
51
  public initializeState<State = any> (moduleInstance: StonexModule<State>): void {
52
    this.state[moduleInstance.moduleName] = copy(moduleInstance.__initialState)
53

54
    Object.defineProperty(moduleInstance, 'state', {
55
      get: () => moduleInstance.getState(),
56
      set: () => {
57
        throw new Error(
58
          `State of the module ${moduleInstance.moduleName} is immutable.\r\n` +
59
          `Please use "this.setState" for updating state of the ${moduleInstance.moduleName} module`
60
        )
61
      },
62
    })
63
  }
64

65
  /**
66
   * Preparing new state to update
67
   *
68
   * @param {StonexModule<State>} moduleInstance
69
   * @param {Partial<State> | ((state: State) => Partial<State>)} changes
70
   * @param {function?} callback
71
   *
72
   * @public
73
   */
74
  public setState<State> (
75
    moduleInstance: StonexModule<State>,
76
    changes: Partial<State> | ((state: State) => Partial<State>),
77
    callback: (state: State) => any = noop
78
  ): void {
79
    const changesAsFunction = isType(changes, types.function)
80
    const changeAction = (stateChanges: Partial<State>) => {
81
      this.updateState<State>(moduleInstance, stateChanges)
82
      callback(moduleInstance.state)
83
    }
84
    if (changesAsFunction) {
85
      setTimeout(() => changeAction((changes as (state: State) => Partial<State>)(moduleInstance.state)), 0)
86
    } else {
87
      changeAction(changes as Partial<State>)
88
    }
89
  }
90

91
  /**
92
   * Returns state of stonex module
93
   *
94
   * @param {string} moduleName
95
   *
96
   * @public
97
   */
98
  public getState<State> (moduleName: string): State {
99
    return copy(this.state[moduleName])
100
  }
101

102
  /**
103
   * Reset state of stonex module
104
   *
105
   * @param {StonexModule<State>} moduleInstance
106
   * @param {function?} callback
107
   *
108
   * @public
109
   */
110
  public resetState<State> (moduleInstance: StonexModule<State>, callback: (state: any) => any = noop): void {
111
    return this.setState(moduleInstance, moduleInstance.__initialState, callback)
112
  }
113

114
  /**
115
   * Updating state of stonex module
116
   *
117
   * @param {StonexModule<State>} moduleInstance
118
   * @param {Partial<State>} stateChanges
119
   */
120
  private updateState<State> (moduleInstance: StonexModule<State>, stateChanges: Partial<State>): void | never {
121
    let flattedStateChanges = null
122

123
    if (isType(stateChanges, types.function)) {
124
      throw new Error(`State of ${moduleInstance.moduleName} module can not have the type of function`)
125
    }
126

127
    if (isType(stateChanges, types.object)) {
128
      flattedStateChanges = { ...copy(stateChanges) }
129
    } else {
130
      flattedStateChanges = isType(stateChanges, types.array) ? [...copy(stateChanges)] : stateChanges
131
    }
132

133
    this.state[moduleInstance.moduleName] = flattedStateChanges
134
  }
135

136
}
137

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.