-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
executable file
·73 lines (65 loc) · 1.89 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { Subject, Observable } from "rxjs";
import { toStream } from "mobx-utils";
import { observable } from "mobx";
import produce from "immer";
import { ObservableMap } from "mobx/lib/types/observablemap";
const rootState: ObservableMap<ObservableMap<any>> = observable.map({});
export const createState = (key: string, state: {}) => {
if (rootState.has(key)) {
return rootState.get(key);
}
rootState.set(key, observable.map(state));
return rootState.get(key);
};
export const getState = (key = ""): {} => {
if (rootState.has(key)) {
const state = rootState.get(key) as ObservableMap<any>;
return state.toJS();
}
return {};
};
export const setState = (key = "", stateMutator = state => {}) => {
if (!rootState.has(key)) {
createState(key, produce({}, stateMutator));
return;
}
const newState = produce(getState(key), stateMutator);
const state = rootState.get(key) as ObservableMap<any>;
state.replace(newState);
return;
};
export type AnyState = any;
export type StateMutator = (state: AnyState) => void;
export type ReactiveState = {
destroy$: Subject<any>;
destroy: () => void;
setState: (StateMutator) => void;
getState: () => AnyState;
state$: Observable<AnyState>;
};
export type GetReactiveState = (key: string, state: AnyState) => ReactiveState;
export const getReactiveState: GetReactiveState = (key, initialState) => {
const destroy$ = new Subject();
const destroy = () => {
destroy$.next();
};
createState(key, initialState);
const setReactiveState = mutator => {
setState(key, mutator);
};
const getReactiveState = () => {
return getState(key);
};
const state$ = Observable.from(toStream(() => getState())).takeUntil(
destroy$
);
// TODO: Add "pausable state"
return {
destroy,
destroy$,
getState: getReactiveState,
setState: setReactiveState,
state$
};
};
export default getReactiveState;