zova-core 5.0.110 → 5.0.113
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bean/beanBaseSimple.d.ts.map +1 -1
- package/dist/bean/beanBaseSimple.js +10 -2
- package/dist/bean/beanBaseSimple.js.map +1 -1
- package/dist/core/resource.d.ts +6 -6
- package/dist/core/resource.d.ts.map +1 -1
- package/dist/core/resource.js +2 -6
- package/dist/core/resource.js.map +1 -1
- package/dist/decorator/class/use.js +8 -5
- package/dist/decorator/class/use.js.map +1 -1
- package/package.json +4 -3
- package/src/bean/beanBase.ts +53 -0
- package/src/bean/beanBaseSimple.ts +38 -0
- package/src/bean/beanContainer.ts +963 -0
- package/src/bean/beanControllerBase.ts +58 -0
- package/src/bean/beanControllerLike.ts +29 -0
- package/src/bean/beanControllerPageBase.ts +18 -0
- package/src/bean/beanRenderBase.ts +7 -0
- package/src/bean/beanRenderLike.ts +33 -0
- package/src/bean/beanSimple.ts +11 -0
- package/src/bean/beanStyleBase.ts +3 -0
- package/src/bean/index.ts +13 -0
- package/src/bean/resource/component/index.ts +1 -0
- package/src/bean/resource/component/type.ts +5 -0
- package/src/bean/resource/config/index.ts +1 -0
- package/src/bean/resource/config/type.ts +32 -0
- package/src/bean/resource/constant/index.ts +1 -0
- package/src/bean/resource/constant/type.ts +1 -0
- package/src/bean/resource/error/beanScopeError.ts +21 -0
- package/src/bean/resource/error/errorClass.ts +57 -0
- package/src/bean/resource/error/errorGlobal.ts +7 -0
- package/src/bean/resource/error/errorInternal.ts +66 -0
- package/src/bean/resource/error/errorObject.ts +4 -0
- package/src/bean/resource/error/index.ts +6 -0
- package/src/bean/resource/error/type.ts +10 -0
- package/src/bean/resource/icon/icon.ts +161 -0
- package/src/bean/resource/icon/iconGroup.ts +10 -0
- package/src/bean/resource/icon/index.ts +4 -0
- package/src/bean/resource/icon/types.ts +21 -0
- package/src/bean/resource/icon/useZovaIcon.ts +20 -0
- package/src/bean/resource/icon/utils.ts +20 -0
- package/src/bean/resource/icon/zovaIcon.ts +52 -0
- package/src/bean/resource/index.ts +8 -0
- package/src/bean/resource/locale/beanScopeLocale.ts +22 -0
- package/src/bean/resource/locale/index.ts +2 -0
- package/src/bean/resource/locale/type.ts +21 -0
- package/src/bean/resource/page/index.ts +1 -0
- package/src/bean/resource/page/type.ts +12 -0
- package/src/bean/resource/service/beanScopeService.ts +24 -0
- package/src/bean/resource/service/index.ts +2 -0
- package/src/bean/resource/service/type.ts +8 -0
- package/src/bean/scope/beanScopeBase.ts +74 -0
- package/src/bean/scope/index.ts +4 -0
- package/src/bean/scope/type.ts +23 -0
- package/src/bean/type.ts +31 -0
- package/src/composables/index.ts +4 -0
- package/src/composables/onControllerMounted.ts +12 -0
- package/src/composables/useApp.ts +7 -0
- package/src/composables/useContext.ts +7 -0
- package/src/composables/useController.ts +125 -0
- package/src/core/app/application.ts +76 -0
- package/src/core/app/config.ts +68 -0
- package/src/core/app/constant.ts +11 -0
- package/src/core/app/index.ts +6 -0
- package/src/core/app/locale.ts +12 -0
- package/src/core/app/meta.ts +44 -0
- package/src/core/app/util.ts +31 -0
- package/src/core/component/component.ts +44 -0
- package/src/core/component/cookie.ts +16 -0
- package/src/core/component/error.ts +18 -0
- package/src/core/component/event.ts +87 -0
- package/src/core/component/index.ts +3 -0
- package/src/core/component/locale.ts +97 -0
- package/src/core/component/module.ts +281 -0
- package/src/core/context/component.ts +34 -0
- package/src/core/context/context.ts +38 -0
- package/src/core/context/index.ts +4 -0
- package/src/core/context/meta.ts +26 -0
- package/src/core/context/state.ts +28 -0
- package/src/core/context/util.ts +20 -0
- package/src/core/index.ts +5 -0
- package/src/core/metadata.ts +54 -0
- package/src/core/resource.ts +186 -0
- package/src/decorator/class/bean.ts +19 -0
- package/src/decorator/class/index.ts +12 -0
- package/src/decorator/class/local.ts +18 -0
- package/src/decorator/class/model.ts +18 -0
- package/src/decorator/class/scope.ts +18 -0
- package/src/decorator/class/store.ts +18 -0
- package/src/decorator/class/style.ts +18 -0
- package/src/decorator/class/theme.ts +18 -0
- package/src/decorator/class/tool.ts +18 -0
- package/src/decorator/class/use.ts +37 -0
- package/src/decorator/class/useComposable.ts +16 -0
- package/src/decorator/class/useScope.ts +21 -0
- package/src/decorator/class/virtual.ts +20 -0
- package/src/decorator/index.ts +7 -0
- package/src/decorator/interface/beanOptions.ts +80 -0
- package/src/decorator/interface/useOptions.ts +37 -0
- package/src/decorator/type/constructable.ts +1 -0
- package/src/decorator/type/containerScope.ts +1 -0
- package/src/decorator/type/functionable.ts +1 -0
- package/src/decorator/type/injectionScope.ts +1 -0
- package/src/index.ts +9 -0
- package/src/plugins/bean.ts +16 -0
- package/src/plugins/index.ts +2 -0
- package/src/plugins/zova.ts +28 -0
- package/src/types/index.ts +2 -0
- package/src/types/interface/component.ts +36 -0
- package/src/types/interface/event.ts +28 -0
- package/src/types/interface/index.ts +6 -0
- package/src/types/interface/inject.ts +2 -0
- package/src/types/interface/module.ts +38 -0
- package/src/types/interface/monkey.ts +38 -0
- package/src/types/interface/pluginZova.ts +17 -0
- package/src/types/utils/cast.ts +8 -0
- package/src/types/utils/env.ts +35 -0
- package/src/types/utils/index.ts +3 -0
- package/src/types/utils/powerPartial.ts +3 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/isClass.ts +17 -0
- package/src/utils/stateLock.ts +47 -0
- package/src/utils/uuid.ts +84 -0
- package/src/vue/composable.ts +10 -0
- package/src/vue/computed.ts +7 -0
- package/src/vue/customRef.ts +5 -0
- package/src/vue/index.ts +4 -0
- package/src/vue/ref.ts +12 -0
- package/src/zod/index.ts +2 -0
- package/src/zod/zz.ts +77 -0
- package/dist/decorator/class/data.d.ts +0 -3
- package/dist/decorator/class/data.d.ts.map +0 -1
- package/dist/decorator/class/data.js +0 -18
- package/dist/decorator/class/data.js.map +0 -1
|
@@ -0,0 +1,963 @@
|
|
|
1
|
+
import { isClass } from '../utils/isClass.js';
|
|
2
|
+
import { AppUtil, ZovaApplication, ZovaContext } from '../core/index.js';
|
|
3
|
+
import {
|
|
4
|
+
Constructable,
|
|
5
|
+
Functionable,
|
|
6
|
+
IDecoratorBeanOptionsBase,
|
|
7
|
+
IDecoratorUseOptionsBase,
|
|
8
|
+
} from '../decorator/index.js';
|
|
9
|
+
import { appResource } from '../core/resource.js';
|
|
10
|
+
import { MetadataKey } from '../core/metadata.js';
|
|
11
|
+
import { IBeanRecord, IBeanScopeRecord, IControllerData, TypeBeanScopeRecordKeys } from './type.js';
|
|
12
|
+
import { BeanBase } from './beanBase.js';
|
|
13
|
+
import { BeanSimple } from './beanSimple.js';
|
|
14
|
+
import { compose, composeAsync } from '@cabloy/compose';
|
|
15
|
+
import { markRaw, reactive, shallowReactive, provide as composableProvide, inject as composableInject } from 'vue';
|
|
16
|
+
import { Cast } from '../types/utils/cast.js';
|
|
17
|
+
import { IInjectRecord } from '../types/interface/inject.js';
|
|
18
|
+
import { SymbolBeanFullName, SymbolInited } from './beanBaseSimple.js';
|
|
19
|
+
|
|
20
|
+
const SymbolBeanContainerParent = Symbol('Bean#BeanContainerParent');
|
|
21
|
+
const SymbolProxyMagic = Symbol('Bean#ProxyMagic');
|
|
22
|
+
export const BeanContainerInstances = Symbol('Bean#Instances');
|
|
23
|
+
|
|
24
|
+
export interface BeanContainer extends IBeanRecord {}
|
|
25
|
+
|
|
26
|
+
export class BeanContainer {
|
|
27
|
+
private app: ZovaApplication;
|
|
28
|
+
private ctx: ZovaContext;
|
|
29
|
+
private appUtil: AppUtil;
|
|
30
|
+
|
|
31
|
+
// fullName / uuid / propName
|
|
32
|
+
private [BeanContainerInstances]: Record<MetadataKey, unknown> = shallowReactive({});
|
|
33
|
+
|
|
34
|
+
static create(app: ZovaApplication, ctx: ZovaContext | null) {
|
|
35
|
+
const beanContainer = new BeanContainer(app, ctx);
|
|
36
|
+
const proxy = new Proxy(beanContainer, {
|
|
37
|
+
get(obj, prop) {
|
|
38
|
+
if (typeof prop === 'symbol') return obj[prop];
|
|
39
|
+
if (obj[prop]) return obj[prop];
|
|
40
|
+
return obj._getBeanSyncOnly(prop);
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
return markRaw(proxy);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
protected constructor(app: ZovaApplication, ctx: ZovaContext | null) {
|
|
47
|
+
this.app = app;
|
|
48
|
+
this.ctx = ctx as any;
|
|
49
|
+
this.appUtil = new AppUtil();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** @internal */
|
|
53
|
+
public dispose() {
|
|
54
|
+
const beanInstances = this[BeanContainerInstances];
|
|
55
|
+
for (const prop in beanInstances) {
|
|
56
|
+
if (prop.startsWith('$$')) continue;
|
|
57
|
+
const beanInstance = Cast(beanInstances[prop]);
|
|
58
|
+
if (beanInstance.__dispose__) {
|
|
59
|
+
this.app.meta.module._monkeyModule('beanDispose', undefined, this, beanInstance);
|
|
60
|
+
this.runWithInstanceScopeOrAppContext(() => {
|
|
61
|
+
beanInstance.__dispose__();
|
|
62
|
+
});
|
|
63
|
+
this.app.meta.module._monkeyModule('beanDisposed', undefined, this, beanInstance);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
this[BeanContainerInstances] = shallowReactive({});
|
|
67
|
+
this[SymbolBeanContainerParent] = undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get parent(): BeanContainer | null {
|
|
71
|
+
if (this[SymbolBeanContainerParent] === undefined) {
|
|
72
|
+
this[SymbolBeanContainerParent] = this._getParent();
|
|
73
|
+
}
|
|
74
|
+
return this[SymbolBeanContainerParent];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private _getParent(): BeanContainer | null {
|
|
78
|
+
let parent = this.ctx?.instance?.parent;
|
|
79
|
+
while (true) {
|
|
80
|
+
if (!parent) return null;
|
|
81
|
+
const beanContainerParent = parent.zova?.bean;
|
|
82
|
+
if (beanContainerParent) return beanContainerParent;
|
|
83
|
+
parent = parent.parent;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
runWithInstanceScopeOrAppContext(fn, tracking?: boolean) {
|
|
88
|
+
if (this.ctx) {
|
|
89
|
+
return this.ctx.meta.util.instanceScope(fn, tracking);
|
|
90
|
+
} else {
|
|
91
|
+
return this.app.vue.runWithContext(fn);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
provide<K extends keyof IInjectRecord>(injectKey: K, value: IInjectRecord[K]) {
|
|
96
|
+
return this.ctx.meta.util.instanceScope(() => {
|
|
97
|
+
return composableProvide(injectKey, value as any);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
inject<K extends keyof IInjectRecord>(injectKey: K): IInjectRecord[K];
|
|
102
|
+
inject<K extends keyof IInjectRecord>(
|
|
103
|
+
injectKey: K,
|
|
104
|
+
defaultValue: IInjectRecord[K],
|
|
105
|
+
treatDefaultAsFactory?: false,
|
|
106
|
+
): IInjectRecord[K];
|
|
107
|
+
inject<K extends keyof IInjectRecord>(
|
|
108
|
+
injectKey: K,
|
|
109
|
+
defaultValue: IInjectRecord[K] | (() => IInjectRecord[K]),
|
|
110
|
+
treatDefaultAsFactory?: true,
|
|
111
|
+
): IInjectRecord[K];
|
|
112
|
+
inject(injectKey, defaultValue?, treatDefaultAsFactory?) {
|
|
113
|
+
return this.ctx.meta.util.instanceScope(() => {
|
|
114
|
+
return composableInject(injectKey, defaultValue, treatDefaultAsFactory);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
defineProperty<T>(obj: T, prop: string, attributes: PropertyDescriptor & ThisType<any>): T {
|
|
119
|
+
const self = this;
|
|
120
|
+
const attrs = { ...attributes };
|
|
121
|
+
if (attributes.get) {
|
|
122
|
+
attrs.get = function () {
|
|
123
|
+
const innerKey = `__innerKey_${prop}`;
|
|
124
|
+
if (!obj[innerKey]) {
|
|
125
|
+
self.runWithInstanceScopeOrAppContext(() => {
|
|
126
|
+
obj[innerKey] = attributes.get!();
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return obj[innerKey];
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return Object.defineProperty(obj, prop, attrs);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** get specific module's scope */
|
|
136
|
+
scope<K extends TypeBeanScopeRecordKeys>(moduleScope: K): IBeanScopeRecord[K];
|
|
137
|
+
scope<T>(moduleScope: string): T;
|
|
138
|
+
scope<T>(moduleScope: string): T {
|
|
139
|
+
if (this !== this.app.bean) {
|
|
140
|
+
return this.app.bean.scope(moduleScope);
|
|
141
|
+
}
|
|
142
|
+
return this._getBeanSyncOnly(`${moduleScope}.scope.module`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async getScope<K extends TypeBeanScopeRecordKeys>(moduleScope: K): Promise<IBeanScopeRecord[K]>;
|
|
146
|
+
async getScope<T>(moduleScope: string): Promise<T>;
|
|
147
|
+
async getScope<T>(moduleScope: string): Promise<T> {
|
|
148
|
+
if (this !== this.app.bean) {
|
|
149
|
+
return await this.app.bean.getScope(moduleScope);
|
|
150
|
+
}
|
|
151
|
+
// module: load
|
|
152
|
+
await this.app.meta.module.use(moduleScope);
|
|
153
|
+
return this.scope(moduleScope);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
_getBeanSync<K extends keyof IBeanRecord>(
|
|
157
|
+
beanFullName: K,
|
|
158
|
+
markReactive?: boolean,
|
|
159
|
+
forceLoad?: boolean,
|
|
160
|
+
): IBeanRecord[K] | undefined;
|
|
161
|
+
_getBeanSync<T>(key: string, markReactive?: boolean, forceLoad?: boolean): T | undefined;
|
|
162
|
+
_getBeanSync<T>(key: string, markReactive?: boolean, forceLoad?: boolean): T | undefined {
|
|
163
|
+
const beanInstance: any = this[BeanContainerInstances][key];
|
|
164
|
+
if (!beanInstance) {
|
|
165
|
+
// bean not loaded, so async load to raise the next call
|
|
166
|
+
if (forceLoad !== false) {
|
|
167
|
+
this._getBean(key as any, markReactive);
|
|
168
|
+
}
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
if (beanInstance[SymbolInited] && !beanInstance[SymbolInited].state) {
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
return beanInstance as T;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
_getBeanSyncOnly<T>(key: MetadataKey): T {
|
|
178
|
+
return this[BeanContainerInstances][key] as T;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async _getBean<T>(A: Constructable<T>, markReactive?: boolean): Promise<T>;
|
|
182
|
+
async _getBean<K extends keyof IBeanRecord>(beanFullName: K, markReactive?: boolean): Promise<IBeanRecord[K]>;
|
|
183
|
+
// async _getBean<T>(beanFullName: string, markReactive?: boolean): Promise<T>;
|
|
184
|
+
async _getBean<T>(beanFullName: Constructable<T> | string, markReactive?: boolean): Promise<T> {
|
|
185
|
+
return await this._getBeanSelector(beanFullName as any, markReactive);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async _getBeanSelector<T>(A: Constructable<T>, markReactive?: boolean, selector?: string): Promise<T>;
|
|
189
|
+
async _getBeanSelector<K extends keyof IBeanRecord>(
|
|
190
|
+
beanFullName: K,
|
|
191
|
+
markReactive?: boolean,
|
|
192
|
+
selector?: string,
|
|
193
|
+
): Promise<IBeanRecord[K]>;
|
|
194
|
+
// async _getBeanSelector<T>(beanFullName: string, markReactive?: boolean, selector?: string): Promise<T>;
|
|
195
|
+
async _getBeanSelector<T>(
|
|
196
|
+
beanFullName: Constructable<T> | string,
|
|
197
|
+
markReactive?: boolean,
|
|
198
|
+
selector?: string,
|
|
199
|
+
): Promise<T> {
|
|
200
|
+
return await this._getBeanSelectorInner(true, null, undefined, beanFullName, markReactive, selector);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async _getBeanSelectorInner<T>(
|
|
204
|
+
newBeanForce: boolean,
|
|
205
|
+
recordProp: MetadataKey | null,
|
|
206
|
+
beanComposable: Functionable | undefined,
|
|
207
|
+
beanFullName: Constructable<T> | string | undefined,
|
|
208
|
+
markReactive?: boolean,
|
|
209
|
+
selector?: string,
|
|
210
|
+
): Promise<T> {
|
|
211
|
+
// fullName
|
|
212
|
+
const fullName = await this._getBeanFullNameByComposableOrClass(beanComposable, beanFullName);
|
|
213
|
+
if (!fullName) {
|
|
214
|
+
// not found
|
|
215
|
+
return null!;
|
|
216
|
+
}
|
|
217
|
+
// same as _getBean if selector is undefined/null/'', as as to get the same bean instance
|
|
218
|
+
// not use !selector which maybe is 0
|
|
219
|
+
const isSelectorValid = !this.app.meta.util.isNullOrEmptyString(selector);
|
|
220
|
+
const key = !isSelectorValid ? fullName : `${fullName}#${selector}`;
|
|
221
|
+
if (this[BeanContainerInstances][key] === undefined && newBeanForce) {
|
|
222
|
+
if (isSelectorValid) {
|
|
223
|
+
await this._newBeanInner(true, recordProp, null, beanComposable, fullName, markReactive, selector);
|
|
224
|
+
} else {
|
|
225
|
+
await this._newBeanInner(true, recordProp, null, beanComposable, fullName, markReactive);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return this[BeanContainerInstances][key] as T;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
_newBeanSimple<T>(A: Constructable<T>, markReactive: boolean, ...args): T {
|
|
232
|
+
// prepare
|
|
233
|
+
const beanInstance = this._prepareBeanInstance(undefined, A, A, args, false, markReactive);
|
|
234
|
+
// init
|
|
235
|
+
if (beanInstance.__init__) {
|
|
236
|
+
beanInstance.__init__(...args);
|
|
237
|
+
}
|
|
238
|
+
// ok
|
|
239
|
+
return beanInstance;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async _newBean<T>(A: Constructable<T>, markReactive?: boolean, ...args): Promise<T>;
|
|
243
|
+
async _newBean<K extends keyof IBeanRecord>(
|
|
244
|
+
beanFullName: K,
|
|
245
|
+
markReactive?: boolean,
|
|
246
|
+
...args
|
|
247
|
+
): Promise<IBeanRecord[K]>;
|
|
248
|
+
// async _newBean<T>(beanFullName: string, markReactive?: boolean, ...args): Promise<T>;
|
|
249
|
+
async _newBean<T>(beanFullName: Constructable<T> | string, markReactive?: boolean, ...args): Promise<T> {
|
|
250
|
+
return await this._newBeanInner(false, null, null, undefined, beanFullName, markReactive, ...args);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async _newBeanSelector<T>(A: Constructable<T>, markReactive?: boolean, selector?: string, ...args): Promise<T>;
|
|
254
|
+
async _newBeanSelector<K extends keyof IBeanRecord>(
|
|
255
|
+
beanFullName: K,
|
|
256
|
+
markReactive?: boolean,
|
|
257
|
+
selector?: string,
|
|
258
|
+
...args
|
|
259
|
+
): Promise<IBeanRecord[K]>;
|
|
260
|
+
// async _newBeanSelector<T>(beanFullName: string, markReactive?: boolean, selector?: string, ...args): Promise<T>;
|
|
261
|
+
async _newBeanSelector<T>(
|
|
262
|
+
beanFullName: Constructable<T> | string,
|
|
263
|
+
markReactive?: boolean,
|
|
264
|
+
selector?: string,
|
|
265
|
+
...args
|
|
266
|
+
): Promise<T> {
|
|
267
|
+
return await this._newBean(beanFullName as any, markReactive, selector, ...args);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/** @internal */
|
|
271
|
+
public async _newBeanInner<T>(
|
|
272
|
+
record: boolean,
|
|
273
|
+
recordProp: MetadataKey | null,
|
|
274
|
+
controllerData: any,
|
|
275
|
+
beanComposable: Functionable | undefined,
|
|
276
|
+
beanFullName: Constructable<T> | string | undefined,
|
|
277
|
+
markReactive?: boolean,
|
|
278
|
+
...args
|
|
279
|
+
): Promise<T> {
|
|
280
|
+
// bean composable
|
|
281
|
+
if (beanComposable) {
|
|
282
|
+
return await this._createBeanInstance<T>(
|
|
283
|
+
record,
|
|
284
|
+
recordProp,
|
|
285
|
+
controllerData,
|
|
286
|
+
beanComposable,
|
|
287
|
+
undefined,
|
|
288
|
+
undefined,
|
|
289
|
+
args,
|
|
290
|
+
false,
|
|
291
|
+
markReactive,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
// bean options
|
|
295
|
+
const beanOptions = await this._getBeanOptionsForce(beanFullName);
|
|
296
|
+
if (!beanOptions) {
|
|
297
|
+
// class
|
|
298
|
+
if (typeof beanFullName === 'function' && isClass(beanFullName)) {
|
|
299
|
+
return await this._createBeanInstance<T>(
|
|
300
|
+
record,
|
|
301
|
+
recordProp,
|
|
302
|
+
controllerData,
|
|
303
|
+
undefined,
|
|
304
|
+
undefined,
|
|
305
|
+
beanFullName,
|
|
306
|
+
args,
|
|
307
|
+
false,
|
|
308
|
+
markReactive,
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
// throw new Error(`bean not found: ${beanFullName}`);
|
|
312
|
+
return null!;
|
|
313
|
+
}
|
|
314
|
+
// beanFullName
|
|
315
|
+
return await this._createBeanInstance<T>(
|
|
316
|
+
record,
|
|
317
|
+
recordProp,
|
|
318
|
+
controllerData,
|
|
319
|
+
undefined,
|
|
320
|
+
beanOptions.beanFullName,
|
|
321
|
+
beanOptions.beanClass as Constructable<T>,
|
|
322
|
+
args,
|
|
323
|
+
beanOptions.aop,
|
|
324
|
+
// default is true: same as inject prop
|
|
325
|
+
markReactive ?? beanOptions.markReactive ?? true,
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private async _getBeanFullNameByComposableOrClass(beanComposable: Functionable | undefined, beanFullName: any) {
|
|
330
|
+
// bean composable
|
|
331
|
+
if (beanComposable) {
|
|
332
|
+
return appResource.getBeanFullNameOfComposable(beanComposable);
|
|
333
|
+
}
|
|
334
|
+
// bean options
|
|
335
|
+
const beanOptions = await this._getBeanOptionsForce(beanFullName);
|
|
336
|
+
if (!beanOptions) {
|
|
337
|
+
// not found
|
|
338
|
+
return undefined;
|
|
339
|
+
}
|
|
340
|
+
return beanOptions.beanFullName;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
private async _getBeanOptionsForce(beanFullName: any) {
|
|
344
|
+
// class
|
|
345
|
+
if (typeof beanFullName === 'function' && isClass(beanFullName)) {
|
|
346
|
+
return appResource.getBean(beanFullName);
|
|
347
|
+
}
|
|
348
|
+
// check if uuid
|
|
349
|
+
if (!this.appUtil.isUuid(beanFullName)) {
|
|
350
|
+
// module: name
|
|
351
|
+
const moduleName = beanFullName.split('.')[0];
|
|
352
|
+
// module: load
|
|
353
|
+
await this.app.meta.module.use(moduleName);
|
|
354
|
+
}
|
|
355
|
+
// get
|
|
356
|
+
return appResource.getBean(beanFullName);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
private async _createBeanInstance<T>(
|
|
360
|
+
record: boolean,
|
|
361
|
+
recordProp: MetadataKey | null,
|
|
362
|
+
controllerData: IControllerData,
|
|
363
|
+
beanComposable: Functionable | undefined,
|
|
364
|
+
beanFullName: string | undefined,
|
|
365
|
+
beanClass: Constructable<T> | undefined,
|
|
366
|
+
args: any[],
|
|
367
|
+
aop: boolean | undefined,
|
|
368
|
+
markReactive: boolean | undefined,
|
|
369
|
+
): Promise<T> {
|
|
370
|
+
// prepare
|
|
371
|
+
const beanInstance = this._prepareBeanInstance(beanComposable, beanFullName, beanClass, args, aop, markReactive);
|
|
372
|
+
// special for controller
|
|
373
|
+
if (controllerData) {
|
|
374
|
+
beanInstance.__initControllerData(controllerData);
|
|
375
|
+
}
|
|
376
|
+
// record
|
|
377
|
+
if (record) {
|
|
378
|
+
// fullName
|
|
379
|
+
const fullName = await this._getBeanFullNameByComposableOrClass(beanComposable, beanFullName);
|
|
380
|
+
if (fullName) {
|
|
381
|
+
this[BeanContainerInstances][fullName] = beanInstance;
|
|
382
|
+
}
|
|
383
|
+
// always record for app/ctx bean
|
|
384
|
+
if (recordProp) {
|
|
385
|
+
this.__recordProp(recordProp, fullName, beanInstance, true);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// init
|
|
389
|
+
if (!beanComposable) {
|
|
390
|
+
await this._initBeanInstance(beanFullName, beanInstance, args);
|
|
391
|
+
}
|
|
392
|
+
// ok
|
|
393
|
+
return beanInstance;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
private _prepareBeanInstance(
|
|
397
|
+
beanComposable: Functionable | undefined,
|
|
398
|
+
beanFullName,
|
|
399
|
+
beanClass,
|
|
400
|
+
args,
|
|
401
|
+
aop,
|
|
402
|
+
markReactive,
|
|
403
|
+
) {
|
|
404
|
+
// create
|
|
405
|
+
let beanInstance;
|
|
406
|
+
if (beanComposable) {
|
|
407
|
+
beanInstance = this._createBeanComposableInstance(beanComposable, args);
|
|
408
|
+
} else {
|
|
409
|
+
if (beanClass.prototype.__init__) {
|
|
410
|
+
beanInstance = new beanClass();
|
|
411
|
+
} else {
|
|
412
|
+
beanInstance = new beanClass(...args);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// app/ctx
|
|
416
|
+
if (beanInstance instanceof BeanSimple) {
|
|
417
|
+
// app
|
|
418
|
+
(<any>beanInstance).app = this.app;
|
|
419
|
+
// ctx: always set even if is null, so as to prevent magic method __get__ take effect.
|
|
420
|
+
(<any>beanInstance).ctx = this.ctx;
|
|
421
|
+
}
|
|
422
|
+
// beanFullName
|
|
423
|
+
if (typeof beanFullName === 'string') {
|
|
424
|
+
__setPropertyValue(beanInstance, SymbolBeanFullName, beanFullName);
|
|
425
|
+
}
|
|
426
|
+
// reactive
|
|
427
|
+
if (markReactive) {
|
|
428
|
+
beanInstance = reactive(beanInstance);
|
|
429
|
+
} else {
|
|
430
|
+
beanInstance = markRaw(beanInstance);
|
|
431
|
+
}
|
|
432
|
+
// aop: proxy
|
|
433
|
+
const beanInstanceProxy = this._patchBeanInstance(beanFullName || beanClass, beanInstance, aop);
|
|
434
|
+
if (beanInstanceProxy) {
|
|
435
|
+
// reactive
|
|
436
|
+
if (markReactive) {
|
|
437
|
+
beanInstance = reactive(beanInstanceProxy);
|
|
438
|
+
} else {
|
|
439
|
+
beanInstance = markRaw(beanInstanceProxy);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
// ok
|
|
443
|
+
return beanInstance;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
private _createBeanComposableInstance(beanComposable, args) {
|
|
447
|
+
return this.runWithInstanceScopeOrAppContext(function () {
|
|
448
|
+
return beanComposable(...args);
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
private async _initBeanInstance(beanFullName, beanInstance, args) {
|
|
453
|
+
// inject
|
|
454
|
+
await this._injectBeanInstance(beanInstance, beanFullName);
|
|
455
|
+
// init
|
|
456
|
+
if (this.app) {
|
|
457
|
+
await this.app.meta.module._monkeyModule('beanInit', undefined, this, beanInstance);
|
|
458
|
+
}
|
|
459
|
+
if (beanInstance.__init__) {
|
|
460
|
+
await this.runWithInstanceScopeOrAppContext(async () => {
|
|
461
|
+
await beanInstance.__init__(...args);
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
if (this.app) {
|
|
465
|
+
await this.app.meta.module._monkeyModule('beanInited', undefined, this, beanInstance);
|
|
466
|
+
}
|
|
467
|
+
if (beanInstance[SymbolInited]) {
|
|
468
|
+
beanInstance[SymbolInited].touch();
|
|
469
|
+
}
|
|
470
|
+
// ok
|
|
471
|
+
return beanInstance;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
private async _injectBeanInstance(beanInstance, beanFullName) {
|
|
475
|
+
const beanOptions = appResource.getBean(beanFullName);
|
|
476
|
+
if (!beanOptions) return;
|
|
477
|
+
const uses = appResource.getUses(beanOptions.beanClass.prototype);
|
|
478
|
+
if (!uses) return;
|
|
479
|
+
for (const key in uses) {
|
|
480
|
+
const useOptions = uses[key];
|
|
481
|
+
// beanComposable
|
|
482
|
+
const targetBeanComposable = useOptions.beanComposable;
|
|
483
|
+
// beanClass
|
|
484
|
+
let targetBeanFullName = useOptions.beanFullName;
|
|
485
|
+
if (!targetBeanFullName && useOptions.beanClass) {
|
|
486
|
+
targetBeanFullName = appResource.getBeanFullName(useOptions.beanClass);
|
|
487
|
+
}
|
|
488
|
+
const targetBeanInstance = await this._injectBeanInstanceProp(
|
|
489
|
+
targetBeanComposable,
|
|
490
|
+
targetBeanFullName,
|
|
491
|
+
useOptions,
|
|
492
|
+
);
|
|
493
|
+
if (targetBeanInstance) {
|
|
494
|
+
targetBeanInstance.__v_isShallow_patch = true;
|
|
495
|
+
beanInstance[key] = targetBeanInstance;
|
|
496
|
+
delete targetBeanInstance.__v_isShallow_patch;
|
|
497
|
+
} else {
|
|
498
|
+
beanInstance[key] = targetBeanInstance;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
private async _injectBeanInstanceProp(
|
|
504
|
+
targetBeanComposable: Functionable | undefined,
|
|
505
|
+
targetBeanFullName: string | undefined,
|
|
506
|
+
useOptions: IDecoratorUseOptionsBase,
|
|
507
|
+
) {
|
|
508
|
+
// 0. host/skipSelf
|
|
509
|
+
if (useOptions.injectionScope === 'host') {
|
|
510
|
+
return await this._getBeanFromHost(true, this, targetBeanComposable, targetBeanFullName, useOptions);
|
|
511
|
+
} else if (useOptions.injectionScope === 'skipSelf') {
|
|
512
|
+
return await this._getBeanFromHost(true, this.parent, targetBeanComposable, targetBeanFullName, useOptions);
|
|
513
|
+
}
|
|
514
|
+
// 1. use name
|
|
515
|
+
if (useOptions.name) {
|
|
516
|
+
return this[BeanContainerInstances][useOptions.name];
|
|
517
|
+
}
|
|
518
|
+
// 2. use prop
|
|
519
|
+
if (!targetBeanComposable && !targetBeanFullName) {
|
|
520
|
+
return this[BeanContainerInstances][useOptions.prop];
|
|
521
|
+
}
|
|
522
|
+
// 3. targetBeanFullName
|
|
523
|
+
let targetOptions: Pick<IDecoratorBeanOptionsBase, 'containerScope' | 'markReactive'> | undefined;
|
|
524
|
+
if (targetBeanComposable) {
|
|
525
|
+
targetOptions = {
|
|
526
|
+
containerScope: undefined,
|
|
527
|
+
markReactive: undefined,
|
|
528
|
+
};
|
|
529
|
+
} else if (targetBeanFullName) {
|
|
530
|
+
targetOptions = await this._getBeanOptionsForce(targetBeanFullName);
|
|
531
|
+
if (!targetOptions) {
|
|
532
|
+
throw new Error(`not found bean class: ${targetBeanFullName}`);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
// options: injectionScope
|
|
536
|
+
const injectionScope = useOptions.injectionScope ?? targetOptions!.containerScope ?? 'ctx';
|
|
537
|
+
// options: markReactive: default is true
|
|
538
|
+
const markReactive = useOptions.markReactive ?? targetOptions!.markReactive ?? true;
|
|
539
|
+
// options: selector: maybe empty string
|
|
540
|
+
const selector = useOptions.selector;
|
|
541
|
+
// recordProp
|
|
542
|
+
//const recordProp = useOptions.name || useOptions.prop;
|
|
543
|
+
const recordProp = useOptions.prop;
|
|
544
|
+
// targetInstance
|
|
545
|
+
let targetInstance;
|
|
546
|
+
if (injectionScope === 'app') {
|
|
547
|
+
targetInstance = await this.app.bean._getBeanSelectorInner(
|
|
548
|
+
true,
|
|
549
|
+
null,
|
|
550
|
+
targetBeanComposable,
|
|
551
|
+
targetBeanFullName,
|
|
552
|
+
markReactive,
|
|
553
|
+
selector,
|
|
554
|
+
);
|
|
555
|
+
await this._injectBeanInstanceProp_appBean(recordProp, targetBeanComposable, targetBeanFullName, targetInstance);
|
|
556
|
+
} else if (injectionScope === 'ctx') {
|
|
557
|
+
targetInstance = await this._getBeanSelectorInner(
|
|
558
|
+
true,
|
|
559
|
+
recordProp,
|
|
560
|
+
targetBeanComposable,
|
|
561
|
+
targetBeanFullName,
|
|
562
|
+
markReactive,
|
|
563
|
+
selector,
|
|
564
|
+
);
|
|
565
|
+
} else if (injectionScope === 'new') {
|
|
566
|
+
// not record prop
|
|
567
|
+
targetInstance = await this._newBeanInner(
|
|
568
|
+
false,
|
|
569
|
+
null,
|
|
570
|
+
null,
|
|
571
|
+
targetBeanComposable,
|
|
572
|
+
targetBeanFullName,
|
|
573
|
+
markReactive,
|
|
574
|
+
selector,
|
|
575
|
+
);
|
|
576
|
+
}
|
|
577
|
+
return targetInstance;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
private async _getBeanFromHost(
|
|
581
|
+
recordProp: boolean,
|
|
582
|
+
beanContainerStart: BeanContainer | null,
|
|
583
|
+
targetBeanComposable: Functionable | undefined,
|
|
584
|
+
targetBeanFullName: string | undefined,
|
|
585
|
+
useOptions: IDecoratorUseOptionsBase,
|
|
586
|
+
) {
|
|
587
|
+
let beanContainerParent = beanContainerStart;
|
|
588
|
+
while (true) {
|
|
589
|
+
if (!beanContainerParent) return null;
|
|
590
|
+
const beanInstance = await this._getBeanFromHostInner(
|
|
591
|
+
beanContainerParent,
|
|
592
|
+
targetBeanComposable,
|
|
593
|
+
targetBeanFullName,
|
|
594
|
+
useOptions,
|
|
595
|
+
);
|
|
596
|
+
// null is valid value
|
|
597
|
+
if (beanInstance !== undefined) {
|
|
598
|
+
// record prop
|
|
599
|
+
if (recordProp) {
|
|
600
|
+
this.__recordProp(useOptions.prop, undefined, beanInstance, false);
|
|
601
|
+
}
|
|
602
|
+
return beanInstance;
|
|
603
|
+
}
|
|
604
|
+
beanContainerParent = beanContainerParent.parent;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
private async _getBeanFromHostInner(
|
|
609
|
+
beanContainerParent: BeanContainer,
|
|
610
|
+
targetBeanComposable: Functionable | undefined,
|
|
611
|
+
targetBeanFullName: string | undefined,
|
|
612
|
+
useOptions: IDecoratorUseOptionsBase,
|
|
613
|
+
) {
|
|
614
|
+
// 1. use name
|
|
615
|
+
if (useOptions.name) {
|
|
616
|
+
return beanContainerParent[BeanContainerInstances][useOptions.name];
|
|
617
|
+
}
|
|
618
|
+
// 2. use prop
|
|
619
|
+
if (!targetBeanComposable && !targetBeanFullName) {
|
|
620
|
+
return beanContainerParent[BeanContainerInstances][useOptions.prop];
|
|
621
|
+
}
|
|
622
|
+
// 3. targetBeanFullName
|
|
623
|
+
return await beanContainerParent._getBeanSelectorInner(
|
|
624
|
+
false,
|
|
625
|
+
null,
|
|
626
|
+
targetBeanComposable,
|
|
627
|
+
targetBeanFullName,
|
|
628
|
+
undefined,
|
|
629
|
+
useOptions.selector,
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
private async _injectBeanInstanceProp_appBean(recordProp, targetBeanComposable, _targetBeanFullName, targetInstance) {
|
|
634
|
+
if (targetInstance === undefined) return;
|
|
635
|
+
// only when ctx bean
|
|
636
|
+
if (!this.ctx) return;
|
|
637
|
+
// record prop
|
|
638
|
+
this.__recordProp(recordProp, undefined, targetInstance, false);
|
|
639
|
+
// force init
|
|
640
|
+
if (!targetBeanComposable && targetInstance) {
|
|
641
|
+
await targetInstance[SymbolInited].wait();
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
private _patchBeanInstance(beanFullNameOrBeanClass, beanInstance, aop) {
|
|
646
|
+
if (!beanFullNameOrBeanClass) return undefined;
|
|
647
|
+
// not aop on aop
|
|
648
|
+
if (aop) return undefined;
|
|
649
|
+
// aop chains
|
|
650
|
+
const _aopChains = this._prepareAopChains(beanFullNameOrBeanClass, beanInstance);
|
|
651
|
+
// no aop
|
|
652
|
+
if (_aopChains.length === 0) return undefined;
|
|
653
|
+
// aop
|
|
654
|
+
return this._newBeanProxy(beanFullNameOrBeanClass, beanInstance);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
private _newBeanProxy(beanFullName, beanInstance) {
|
|
658
|
+
const self = this;
|
|
659
|
+
const proxy = new Proxy(beanInstance, {
|
|
660
|
+
get(target, prop, receiver) {
|
|
661
|
+
if (typeof prop === 'symbol') {
|
|
662
|
+
return target[prop];
|
|
663
|
+
}
|
|
664
|
+
if (__isInnerMethod(prop)) {
|
|
665
|
+
if (prop === '__v_isShallow' && target.__v_isShallow_patch) return target.__v_isShallow_patch;
|
|
666
|
+
return target[prop];
|
|
667
|
+
}
|
|
668
|
+
// descriptorInfo
|
|
669
|
+
const descriptorInfo = __getPropertyDescriptor(target, prop);
|
|
670
|
+
if (!__checkAopOfDescriptorInfo(descriptorInfo)) return target[prop];
|
|
671
|
+
const methodType = __methodTypeOfDescriptor(descriptorInfo);
|
|
672
|
+
// get prop
|
|
673
|
+
if (!methodType) {
|
|
674
|
+
const methodName = `__get_${prop}__`;
|
|
675
|
+
const methodNameMagic = '__get__';
|
|
676
|
+
const _aopChainsProp = self._getAopChainsProp(beanFullName, methodName, methodNameMagic);
|
|
677
|
+
if (_aopChainsProp.length === 0) return target[prop];
|
|
678
|
+
// context
|
|
679
|
+
const context = {
|
|
680
|
+
target,
|
|
681
|
+
receiver,
|
|
682
|
+
prop,
|
|
683
|
+
value: undefined,
|
|
684
|
+
};
|
|
685
|
+
// aop
|
|
686
|
+
self.__composeForProp(_aopChainsProp)(context, (context, next) => {
|
|
687
|
+
if (context.value === undefined) {
|
|
688
|
+
if (!descriptorInfo && target.__get__) {
|
|
689
|
+
context.value = target.__get__(prop);
|
|
690
|
+
} else {
|
|
691
|
+
context.value = target[prop];
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
next();
|
|
695
|
+
});
|
|
696
|
+
// ok
|
|
697
|
+
return context.value;
|
|
698
|
+
}
|
|
699
|
+
// method
|
|
700
|
+
return self._getInstanceMethodProxy(beanFullName, target, prop, methodType);
|
|
701
|
+
},
|
|
702
|
+
set(target, prop, value, receiver) {
|
|
703
|
+
if (typeof prop === 'symbol') {
|
|
704
|
+
target[prop] = value;
|
|
705
|
+
return true;
|
|
706
|
+
}
|
|
707
|
+
if (__isInnerMethod(prop)) {
|
|
708
|
+
target[prop] = value;
|
|
709
|
+
return true;
|
|
710
|
+
}
|
|
711
|
+
// descriptorInfo
|
|
712
|
+
const descriptorInfo = __getPropertyDescriptor(target, prop);
|
|
713
|
+
if (!__checkAopOfDescriptorInfo(descriptorInfo)) {
|
|
714
|
+
target[prop] = value;
|
|
715
|
+
return true;
|
|
716
|
+
}
|
|
717
|
+
const methodName = `__set_${prop}__`;
|
|
718
|
+
const methodNameMagic = '__set__';
|
|
719
|
+
const _aopChainsProp = self._getAopChainsProp(beanFullName, methodName, methodNameMagic);
|
|
720
|
+
if (_aopChainsProp.length === 0) {
|
|
721
|
+
target[prop] = value;
|
|
722
|
+
return true;
|
|
723
|
+
}
|
|
724
|
+
// context
|
|
725
|
+
const context = {
|
|
726
|
+
target,
|
|
727
|
+
receiver,
|
|
728
|
+
prop,
|
|
729
|
+
value,
|
|
730
|
+
};
|
|
731
|
+
// aop
|
|
732
|
+
self.__composeForProp(_aopChainsProp)(context, (context, next) => {
|
|
733
|
+
if (!descriptorInfo && target.__set__) {
|
|
734
|
+
const res = target.__set__(prop, context.value);
|
|
735
|
+
if (res === undefined) throw new Error('__set__ must return true/false');
|
|
736
|
+
if (!res) {
|
|
737
|
+
target[prop] = context.value;
|
|
738
|
+
}
|
|
739
|
+
} else {
|
|
740
|
+
target[prop] = context.value;
|
|
741
|
+
}
|
|
742
|
+
next();
|
|
743
|
+
});
|
|
744
|
+
// ok
|
|
745
|
+
return true;
|
|
746
|
+
},
|
|
747
|
+
});
|
|
748
|
+
return proxy;
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
private _getInstanceMethodProxy(beanFullName, beanInstance, prop, methodType) {
|
|
752
|
+
const self = this;
|
|
753
|
+
// not aop magic methods
|
|
754
|
+
if (__isInnerMethod(prop)) {
|
|
755
|
+
return beanInstance[prop];
|
|
756
|
+
}
|
|
757
|
+
// aop chains
|
|
758
|
+
const _aopChainsProp = this._getAopChainsProp(beanFullName, prop, null);
|
|
759
|
+
if (_aopChainsProp.length === 0) return beanInstance[prop];
|
|
760
|
+
// proxy
|
|
761
|
+
const methodProxyKey = `__aopproxy_method_${prop}__`;
|
|
762
|
+
if (beanInstance[methodProxyKey]) return beanInstance[methodProxyKey];
|
|
763
|
+
const methodProxy = new Proxy(beanInstance[prop], {
|
|
764
|
+
apply(target, thisArg, args) {
|
|
765
|
+
// context
|
|
766
|
+
const context = {
|
|
767
|
+
target: beanInstance,
|
|
768
|
+
receiver: thisArg,
|
|
769
|
+
prop,
|
|
770
|
+
arguments: args,
|
|
771
|
+
result: undefined,
|
|
772
|
+
};
|
|
773
|
+
// aop
|
|
774
|
+
if (methodType === 'Function') {
|
|
775
|
+
self.__composeForProp(_aopChainsProp)(context, (context, next) => {
|
|
776
|
+
if (context.result === undefined) {
|
|
777
|
+
context.result = target.apply(thisArg, args);
|
|
778
|
+
}
|
|
779
|
+
next();
|
|
780
|
+
});
|
|
781
|
+
// ok
|
|
782
|
+
return context.result;
|
|
783
|
+
}
|
|
784
|
+
if (methodType === 'AsyncFunction') {
|
|
785
|
+
return new Promise((resolve, reject) => {
|
|
786
|
+
self
|
|
787
|
+
.__composeForPropAsync(_aopChainsProp)(context, async (context, next) => {
|
|
788
|
+
if (context.result === undefined) {
|
|
789
|
+
context.result = await target.apply(thisArg, args);
|
|
790
|
+
}
|
|
791
|
+
await next();
|
|
792
|
+
})
|
|
793
|
+
.then(() => {
|
|
794
|
+
resolve(context.result);
|
|
795
|
+
})
|
|
796
|
+
.catch(err => {
|
|
797
|
+
reject(err);
|
|
798
|
+
});
|
|
799
|
+
});
|
|
800
|
+
}
|
|
801
|
+
},
|
|
802
|
+
});
|
|
803
|
+
__setPropertyValue(beanInstance, methodProxyKey, methodProxy);
|
|
804
|
+
return methodProxy;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
private _prepareAopChains(beanFullNameOrBeanClass, beanInstance) {
|
|
808
|
+
if (!beanFullNameOrBeanClass) return [];
|
|
809
|
+
// beanFullName maybe class
|
|
810
|
+
const beanOptions = appResource.getBean(beanFullNameOrBeanClass);
|
|
811
|
+
const host = beanOptions || beanFullNameOrBeanClass;
|
|
812
|
+
if (host.__aopChains__) return host.__aopChains__;
|
|
813
|
+
// chains
|
|
814
|
+
let chains: MetadataKey[] = [];
|
|
815
|
+
if (beanOptions && !beanOptions.aop) {
|
|
816
|
+
const aops = appResource.findAopsMatched(beanOptions.beanFullName);
|
|
817
|
+
if (aops) {
|
|
818
|
+
chains = chains.concat(aops);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
// magic self
|
|
822
|
+
if (__hasMagicMothod(beanInstance)) {
|
|
823
|
+
chains.push(SymbolProxyMagic);
|
|
824
|
+
}
|
|
825
|
+
// hold
|
|
826
|
+
host.__aopChains__ = chains;
|
|
827
|
+
return chains;
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
private _getAopChains(beanFullName) {
|
|
831
|
+
// beanFullName maybe class
|
|
832
|
+
const beanOptions = appResource.getBean(beanFullName);
|
|
833
|
+
const host = beanOptions || beanFullName;
|
|
834
|
+
return host.__aopChains__;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
private _getAopChainsProp(beanFullName, methodName, methodNameMagic) {
|
|
838
|
+
const chainsKey = `__aopChains_${methodName}__`;
|
|
839
|
+
const beanOptions = appResource.getBean(beanFullName);
|
|
840
|
+
const host = beanOptions || beanFullName;
|
|
841
|
+
if (!host.__aopChainsKey__) host.__aopChainsKey__ = {};
|
|
842
|
+
if (host.__aopChainsKey__[chainsKey]) return host.__aopChainsKey__[chainsKey];
|
|
843
|
+
const _aopChains = this._getAopChains(beanFullName);
|
|
844
|
+
const chains: [MetadataKey, string][] = [];
|
|
845
|
+
for (const aopKey of _aopChains) {
|
|
846
|
+
if (aopKey === SymbolProxyMagic) {
|
|
847
|
+
chains.push([aopKey, methodName]);
|
|
848
|
+
} else {
|
|
849
|
+
const aop: any = this._getBeanSyncOnly(aopKey as string);
|
|
850
|
+
if (aop[methodName]) {
|
|
851
|
+
chains.push([aopKey, methodName]);
|
|
852
|
+
} else if (methodNameMagic && aop[methodNameMagic]) {
|
|
853
|
+
chains.push([aopKey, methodNameMagic]);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
host.__aopChainsKey__[chainsKey] = chains;
|
|
858
|
+
return chains;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
private __composeForPropAdapter = (_context, chain) => {
|
|
862
|
+
const [aopKey, methodName] = chain;
|
|
863
|
+
// SymbolProxyMagic
|
|
864
|
+
if (aopKey === SymbolProxyMagic) return null;
|
|
865
|
+
// chain
|
|
866
|
+
const aop = this._getBeanSyncOnly(aopKey);
|
|
867
|
+
if (!aop) throw new Error(`aop not found: ${chain}`);
|
|
868
|
+
if (!aop[methodName]) return null;
|
|
869
|
+
return {
|
|
870
|
+
receiver: aop,
|
|
871
|
+
fn: aop[methodName],
|
|
872
|
+
};
|
|
873
|
+
};
|
|
874
|
+
|
|
875
|
+
private __composeForProp(chains) {
|
|
876
|
+
return compose(chains, this.__composeForPropAdapter);
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
private __composeForPropAsync(chains) {
|
|
880
|
+
return composeAsync(chains, this.__composeForPropAdapter);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
private __recordProp(recordProp, fullName: string | undefined, beanInstance, throwError: boolean) {
|
|
884
|
+
if (this[BeanContainerInstances][recordProp] !== undefined && throwError) {
|
|
885
|
+
throw new Error(`prop exsits: ${recordProp.toString()}, ${fullName}`);
|
|
886
|
+
}
|
|
887
|
+
if (this[BeanContainerInstances][recordProp] === undefined) {
|
|
888
|
+
this[BeanContainerInstances][recordProp] = beanInstance;
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
function __checkAopOfDescriptorInfo(descriptorInfo) {
|
|
894
|
+
if (!descriptorInfo) return true;
|
|
895
|
+
return !descriptorInfo.dynamic && !descriptorInfo.ofBeanBase;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
function __getPropertyDescriptor(obj, prop) {
|
|
899
|
+
// dynamic
|
|
900
|
+
const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
|
|
901
|
+
if (descriptor) return { descriptor, dynamic: true };
|
|
902
|
+
// static
|
|
903
|
+
return __getPropertyDescriptorStatic(obj, prop);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
function __getPropertyDescriptorStatic(obj, prop) {
|
|
907
|
+
let proto = Object.getPrototypeOf(obj);
|
|
908
|
+
let ofBeanBase = false;
|
|
909
|
+
while (proto) {
|
|
910
|
+
if (proto.constructor.name === BeanBase.name) {
|
|
911
|
+
ofBeanBase = true;
|
|
912
|
+
}
|
|
913
|
+
const descriptor = Object.getOwnPropertyDescriptor(proto, prop);
|
|
914
|
+
if (descriptor) return { descriptor, dynamic: false, ofBeanBase };
|
|
915
|
+
proto = Object.getPrototypeOf(proto);
|
|
916
|
+
}
|
|
917
|
+
return null;
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
function __setPropertyValue(obj, prop, value) {
|
|
921
|
+
Object.defineProperty(obj, prop, {
|
|
922
|
+
enumerable: false,
|
|
923
|
+
configurable: true,
|
|
924
|
+
get() {
|
|
925
|
+
return value;
|
|
926
|
+
},
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
function __hasMagicMothod(instance) {
|
|
931
|
+
return !!instance.__get__ || !!instance.__set__;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
function __isInnerMethod(prop) {
|
|
935
|
+
return [
|
|
936
|
+
'__get__',
|
|
937
|
+
'__set__',
|
|
938
|
+
'__init__',
|
|
939
|
+
'__dispose__',
|
|
940
|
+
'then',
|
|
941
|
+
'__v_skip',
|
|
942
|
+
'__v_isReactive',
|
|
943
|
+
'__v_isReadonly',
|
|
944
|
+
'__v_isShallow',
|
|
945
|
+
'__v_raw',
|
|
946
|
+
'__v_isRef',
|
|
947
|
+
'__v_isVNode',
|
|
948
|
+
'__v_cache',
|
|
949
|
+
'__v_isShallow_patch',
|
|
950
|
+
].includes(prop);
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
function __methodTypeOfDescriptor(descriptorInfo) {
|
|
954
|
+
if (!descriptorInfo) return null;
|
|
955
|
+
const { descriptor, dynamic } = descriptorInfo;
|
|
956
|
+
if (dynamic) return null;
|
|
957
|
+
if (descriptor.get) return null;
|
|
958
|
+
const methodType = descriptor.value?.constructor?.name;
|
|
959
|
+
if (['Function', 'AsyncFunction'].includes(methodType)) {
|
|
960
|
+
return methodType;
|
|
961
|
+
}
|
|
962
|
+
return null;
|
|
963
|
+
}
|