UNPKG

3.54 kBPlain TextView Raw
1import {
2 ObservableObjectAdministration,
3 observable,
4 Annotation,
5 defineProperty,
6 createAction,
7 globalState,
8 flow,
9 computed,
10 autoAction,
11 isGenerator,
12 MakeResult
13} from "../internal"
14
15const AUTO = "true"
16
17export const autoAnnotation: Annotation = createAutoAnnotation()
18
19export function createAutoAnnotation(options?: object): Annotation {
20 return {
21 annotationType_: AUTO,
22 options_: options,
23 make_,
24 extend_
25 }
26}
27
28function make_(
29 adm: ObservableObjectAdministration,
30 key: PropertyKey,
31 descriptor: PropertyDescriptor,
32 source: object
33): MakeResult {
34 // getter -> computed
35 if (descriptor.get) {
36 return computed.make_(adm, key, descriptor, source)
37 }
38 // lone setter -> action setter
39 if (descriptor.set) {
40 // TODO make action applicable to setter and delegate to action.make_
41 const set = createAction(key.toString(), descriptor.set) as (v: any) => void
42 // own
43 if (source === adm.target_) {
44 return adm.defineProperty_(key, {
45 configurable: globalState.safeDescriptors ? adm.isPlainObject_ : true,
46 set
47 }) === null
48 ? MakeResult.Cancel
49 : MakeResult.Continue
50 }
51 // proto
52 defineProperty(source, key, {
53 configurable: true,
54 set
55 })
56 return MakeResult.Continue
57 }
58 // function on proto -> autoAction/flow
59 if (source !== adm.target_ && typeof descriptor.value === "function") {
60 if (isGenerator(descriptor.value)) {
61 const flowAnnotation = this.options_?.autoBind ? flow.bound : flow
62 return flowAnnotation.make_(adm, key, descriptor, source)
63 }
64 const actionAnnotation = this.options_?.autoBind ? autoAction.bound : autoAction
65 return actionAnnotation.make_(adm, key, descriptor, source)
66 }
67 // other -> observable
68 // Copy props from proto as well, see test:
69 // "decorate should work with Object.create"
70 let observableAnnotation = this.options_?.deep === false ? observable.ref : observable
71 // if function respect autoBind option
72 if (typeof descriptor.value === "function" && this.options_?.autoBind) {
73 descriptor.value = descriptor.value.bind(adm.proxy_ ?? adm.target_)
74 }
75 return observableAnnotation.make_(adm, key, descriptor, source)
76}
77
78function extend_(
79 adm: ObservableObjectAdministration,
80 key: PropertyKey,
81 descriptor: PropertyDescriptor,
82 proxyTrap: boolean
83): boolean | null {
84 // getter -> computed
85 if (descriptor.get) {
86 return computed.extend_(adm, key, descriptor, proxyTrap)
87 }
88 // lone setter -> action setter
89 if (descriptor.set) {
90 // TODO make action applicable to setter and delegate to action.extend_
91 return adm.defineProperty_(
92 key,
93 {
94 configurable: globalState.safeDescriptors ? adm.isPlainObject_ : true,
95 set: createAction(key.toString(), descriptor.set) as (v: any) => void
96 },
97 proxyTrap
98 )
99 }
100 // other -> observable
101 // if function respect autoBind option
102 if (typeof descriptor.value === "function" && this.options_?.autoBind) {
103 descriptor.value = descriptor.value.bind(adm.proxy_ ?? adm.target_)
104 }
105 let observableAnnotation = this.options_?.deep === false ? observable.ref : observable
106 return observableAnnotation.extend_(adm, key, descriptor, proxyTrap)
107}