-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.ts
64 lines (61 loc) · 1.66 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
type DeepReadonly<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
}
export abstract class Mutations<State> {
protected state: State
constructor(state: State) {
this.state = state
}
commit(mutation: (state: State) => any) {
mutation(this.state)
}
}
export abstract class Actions<State, Mutations> {
protected state: DeepReadonly<State>
protected mutations: Mutations
constructor(state: State, mutations: Mutations) {
this.state = state as any
this.mutations = mutations
}
}
export const createModel = <S, M, A>(
State: { new (): S, },
Mutations: { new (s: S): M, },
Actions: { new (s: S, m: M): A },
) => {
let subscribers = [] as ((state: S) => any)[]
let mutating = 0
function commitify(func: Function, thisp?: any) {
const tmp = {
[func.name]: function (this: any, ...args: any[]) {
mutating++
func.apply(thisp || this, args)
mutating--
if (!mutating) {
subscribers.forEach(subscriber => subscriber(state))
}
}
}
return tmp[func.name] as typeof func
}
const state = new State();
const mutations = new Mutations(state);
for (const key in mutations) {
const mutation = (mutations as any)[key]
if (key !== 'constructor' && typeof mutation === 'function') {
(mutations as any)[key] = commitify(mutation, mutations)
}
}
const actions = new Actions(state, mutations)
return {
state: state as any as DeepReadonly<S>,
mutations: mutations,
actions,
subscribe(subscriber: (state: S) => any) {
subscribers.push(subscriber)
return () => {
subscribers = subscribers.filter(s => s !== subscriber)
}
}
}
}