-
Notifications
You must be signed in to change notification settings - Fork 4
/
decorator.ts
75 lines (67 loc) · 2.43 KB
/
decorator.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
74
75
import Vue = require('vue')
import {$$Prop} from 'av-ts/dist/src/interface'
import {createMap} from 'av-ts/dist/src/util'
import {Component} from 'av-ts'
import {
Store, BG, BC, BD, BP, BCH, BDH,
Helper,
} from './interface'
import StoreImpl from './store'
const VUEX_PROP = '$$Vuex' as $$Prop
const GetterKey = '__isgetter'
export function Store(target: Vue, key: string): void {
let vuexProps = target[VUEX_PROP] = target[VUEX_PROP] || []
vuexProps.push(key)
}
export function Vuex(target: Vue, key: string): void {
console.warn('@Vuex decorator is deprecated! Please use @Store')
Store(target, key)
}
// we return a fake getter in helper to achieve a good API surface
// at compile time, helper.getters(key) return a value T
// at runtime, helper.getters(key) return a function that return value T
// so @Vuex getter = getters(key) will resolve to T at type level
// while on value level vuex decorator can wrap it in vue's `computed` field
export function getHelper<G extends BG, CH extends BCH, DH extends BDH>(store: Store<{}, G, BC, BD, BP, CH, DH>): Helper<G, CH, DH> {
if (store._helper) return store._helper
const impl: StoreImpl = store as any
const { commit, dispatch } = store
return impl._helper = ({
getters(k: string) {
if (!Component.inDefinition) return
let getter = impl._getters[k]
getter[GetterKey] = true // a flag to distinguish between methods and computed
return getter
},
commit: memoize((k: string) => {
if (!Component.inDefinition) return
return (...args: any[]) => commit.apply(null, [k, ...args])
}),
dispatch: memoize((k: string) => {
if (!Component.inDefinition) return
return (...args: any[]) => dispatch.apply(null, [k, ...args])
}),
} as any)
}
Component.register(VUEX_PROP, function(target, instance, optionsToWrite) {
let vuexProps: string[] = target[VUEX_PROP]
for (let key of vuexProps) {
let handler = instance[key]
if (handler[GetterKey]) {
optionsToWrite.computed![key] = handler
} else if (typeof handler === 'function'){
optionsToWrite.methods![key] = handler
}
delete instance[key]
}
})
type Cacheable<R> = (this: void, k: string) => R
function memoize<R>(func: Cacheable<R>): Cacheable<R> {
function memoized(key: string) {
let cache: {[k: string]: R} = memoized['cache']
if (!cache[key]) cache[key] = func(key)
return cache[key]
}
memoized['cache'] = createMap()
return memoized
}