vona-core 5.0.104 → 5.0.106
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/index.js +3196 -2
- package/dist/lib/bean/beanBase.d.ts +1 -0
- package/dist/lib/bean/beanBaseSimple.d.ts +0 -2
- package/dist/lib/bean/beanContainer.d.ts +9 -5
- package/dist/lib/core/hmr.d.ts +20 -0
- package/dist/lib/core/hmrDeps.d.ts +12 -0
- package/dist/lib/core/index.d.ts +2 -0
- package/dist/lib/core/meta.d.ts +5 -1
- package/dist/lib/core/response.d.ts +7 -0
- package/dist/lib/decorator/class/util.d.ts +1 -0
- package/dist/lib/decorator/interface/beanOptions.d.ts +1 -0
- package/dist/lib/decorator/type/containerScope.d.ts +1 -0
- package/dist/lib/mappedClass/extendClass.d.ts +2 -0
- package/dist/lib/mappedClass/mappedClass.d.ts +2 -0
- package/package.json +13 -14
- package/dist/lib/bean/beanAopBase.js +0 -3
- package/dist/lib/bean/beanAopMethodBase.js +0 -3
- package/dist/lib/bean/beanBase.js +0 -41
- package/dist/lib/bean/beanBaseSimple.js +0 -32
- package/dist/lib/bean/beanContainer.js +0 -586
- package/dist/lib/bean/beanSimple.js +0 -9
- package/dist/lib/bean/index.js +0 -9
- package/dist/lib/bean/resource/config/index.js +0 -1
- package/dist/lib/bean/resource/config/type.js +0 -1
- package/dist/lib/bean/resource/constant/index.js +0 -1
- package/dist/lib/bean/resource/constant/type.js +0 -1
- package/dist/lib/bean/resource/error/beanScopeError.js +0 -17
- package/dist/lib/bean/resource/error/beanScopeErrorImpl.js +0 -18
- package/dist/lib/bean/resource/error/errorApplication.js +0 -1
- package/dist/lib/bean/resource/error/errorClass.js +0 -75
- package/dist/lib/bean/resource/error/errorGlobal.js +0 -1
- package/dist/lib/bean/resource/error/errorInternal.js +0 -68
- package/dist/lib/bean/resource/error/errorObject.js +0 -1
- package/dist/lib/bean/resource/error/index.js +0 -8
- package/dist/lib/bean/resource/error/type.js +0 -1
- package/dist/lib/bean/resource/index.js +0 -4
- package/dist/lib/bean/resource/locale/appLocale.js +0 -51
- package/dist/lib/bean/resource/locale/beanScopeLocale.js +0 -16
- package/dist/lib/bean/resource/locale/index.js +0 -4
- package/dist/lib/bean/resource/locale/type.js +0 -1
- package/dist/lib/bean/resource/locale/utils.js +0 -3
- package/dist/lib/bean/scope/beanScopeBase.js +0 -97
- package/dist/lib/bean/scope/beanScopeContainer.js +0 -15
- package/dist/lib/bean/scope/beanScopeScene.js +0 -20
- package/dist/lib/bean/scope/beanScopeUtil.js +0 -18
- package/dist/lib/bean/scope/index.js +0 -4
- package/dist/lib/bean/type.js +0 -2
- package/dist/lib/core/application.js +0 -86
- package/dist/lib/core/asyncLocalStorage.js +0 -23
- package/dist/lib/core/config.js +0 -54
- package/dist/lib/core/context.js +0 -121
- package/dist/lib/core/ctxCounter.js +0 -20
- package/dist/lib/core/index.js +0 -7
- package/dist/lib/core/locales.js +0 -6
- package/dist/lib/core/logger/appLogger.js +0 -103
- package/dist/lib/core/logger/index.js +0 -2
- package/dist/lib/core/logger/utils.js +0 -76
- package/dist/lib/core/meta.js +0 -120
- package/dist/lib/core/metadata.js +0 -80
- package/dist/lib/core/resource.js +0 -146
- package/dist/lib/decorator/class/beanInfo.js +0 -8
- package/dist/lib/decorator/class/createBeanDecorator.js +0 -22
- package/dist/lib/decorator/class/index.js +0 -5
- package/dist/lib/decorator/class/proxyDisable.js +0 -8
- package/dist/lib/decorator/class/use.js +0 -74
- package/dist/lib/decorator/class/util.js +0 -9
- package/dist/lib/decorator/class/virtual.js +0 -8
- package/dist/lib/decorator/index.js +0 -3
- package/dist/lib/decorator/interface/beanOptions.js +0 -1
- package/dist/lib/decorator/interface/index.js +0 -2
- package/dist/lib/decorator/interface/useOptions.js +0 -1
- package/dist/lib/decorator/type/constructable.js +0 -1
- package/dist/lib/decorator/type/containerScope.js +0 -1
- package/dist/lib/decorator/type/function.js +0 -1
- package/dist/lib/decorator/type/index.js +0 -4
- package/dist/lib/decorator/type/injectionScope.js +0 -1
- package/dist/lib/framework/bootstrap.js +0 -13
- package/dist/lib/framework/cluster.js +0 -33
- package/dist/lib/framework/createApp.js +0 -73
- package/dist/lib/framework/index.js +0 -4
- package/dist/lib/framework/process.js +0 -44
- package/dist/lib/framework/start.js +0 -79
- package/dist/lib/framework/useApp.js +0 -61
- package/dist/lib/index.js +0 -6
- package/dist/lib/locale/en-us.js +0 -5
- package/dist/lib/locale/zh-cn.js +0 -69
- package/dist/lib/mappedClass/index.js +0 -4
- package/dist/lib/mappedClass/mappedClass.js +0 -10
- package/dist/lib/mappedClass/mixinClass.js +0 -8
- package/dist/lib/mappedClass/omitClass.js +0 -14
- package/dist/lib/mappedClass/partialClass.js +0 -16
- package/dist/lib/mappedClass/pickClass.js +0 -6
- package/dist/lib/mappedClass/pickClassInner.js +0 -12
- package/dist/lib/mappedClass/type.js +0 -1
- package/dist/lib/mappedClass/utils.js +0 -80
- package/dist/lib/module/config.js +0 -17
- package/dist/lib/module/constant.js +0 -16
- package/dist/lib/module/errors.js +0 -29
- package/dist/lib/module/loader.js +0 -25
- package/dist/lib/module/locales.js +0 -49
- package/dist/lib/module/module.js +0 -32
- package/dist/lib/utils/customKey.js +0 -3
- package/dist/lib/utils/index.js +0 -6
- package/dist/lib/utils/retry.js +0 -16
- package/dist/lib/utils/sqlite3.js +0 -38
- package/dist/lib/utils/util.js +0 -316
- package/dist/lib/utils/zod-enhance.js +0 -18
- package/dist/lib/utils/zod-openapi.js +0 -29
- package/dist/types/application/app.js +0 -1
- package/dist/types/application/index.js +0 -1
- package/dist/types/config/config.js +0 -1
- package/dist/types/config/index.js +0 -3
- package/dist/types/config/instance.js +0 -1
- package/dist/types/config/locale.js +0 -3
- package/dist/types/context/contextBase.js +0 -1
- package/dist/types/context/contextConfig.js +0 -1
- package/dist/types/context/contextOthers.js +0 -1
- package/dist/types/context/contextState.js +0 -1
- package/dist/types/context/index.js +0 -1
- package/dist/types/enum/appEvent.js +0 -4
- package/dist/types/enum/index.js +0 -1
- package/dist/types/index.js +0 -6
- package/dist/types/interface/bootstrap.js +0 -1
- package/dist/types/interface/index.js +0 -4
- package/dist/types/interface/logger.js +0 -1
- package/dist/types/interface/module.js +0 -1
- package/dist/types/interface/monkey.js +0 -1
- package/dist/types/utils/cast.js +0 -3
- package/dist/types/utils/demo.js +0 -1
- package/dist/types/utils/env.js +0 -1
- package/dist/types/utils/index.js +0 -6
- package/dist/types/utils/omitNever.js +0 -1
- package/dist/types/utils/powerPartial.js +0 -8
- package/dist/types/utils/type.js +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3198 @@
|
|
|
1
1
|
import '@cabloy/set';
|
|
2
2
|
import '@cabloy/json5';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { combineApiPathControllerAndActionRaw, combineApiPathControllerAndAction, combineApiPath, combineResourceName, sleep, isUndefined, isClass, isNilOrEmptyString, evaluateExpressions, catchErrorSync, isEmptyObject, hashkey } from '@cabloy/utils';
|
|
4
|
+
import { toLowerCaseFirstChar, splitWords } from '@cabloy/word-utils';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import crypto from 'node:crypto';
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
import { pathToFileURL } from 'node:url';
|
|
9
|
+
import { compose as compose$1 } from '@cabloy/compose';
|
|
10
|
+
import { extend } from '@cabloy/extend';
|
|
11
|
+
import fse from 'fs-extra';
|
|
12
|
+
import * as uuid from 'uuid';
|
|
13
|
+
import { setLocaleErrors, setLocaleAdapter, translateError } from '@cabloy/zod-errors-custom';
|
|
14
|
+
import { ZodMetadata } from '@cabloy/zod-openapi';
|
|
15
|
+
import { setParseAdapter } from '@cabloy/zod-query';
|
|
16
|
+
import 'reflect-metadata';
|
|
17
|
+
import { parseModuleName as parseModuleName$1, parseModuleFile as parseModuleFile$1, ParseModuleNameLevelInit } from '@cabloy/module-info-pro';
|
|
18
|
+
import * as localeutil from '@cabloy/localeutil';
|
|
19
|
+
import { getOnionMetasMeta } from '@cabloy/module-info';
|
|
20
|
+
import KoaApplication from 'koa';
|
|
21
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
22
|
+
import chalk from 'chalk';
|
|
23
|
+
import * as Winston from 'winston';
|
|
24
|
+
import DailyRotateFile from 'winston-daily-rotate-file';
|
|
25
|
+
import os from 'node:os';
|
|
26
|
+
import { MESSAGE, LEVEL } from 'triple-beam';
|
|
27
|
+
import cluster from 'node:cluster';
|
|
28
|
+
import { extendZodWithOpenApi } from '@cabloy/zod-to-openapi';
|
|
29
|
+
import { z } from 'zod';
|
|
30
|
+
import * as Retry from 'retry';
|
|
31
|
+
export { Retry };
|
|
32
|
+
|
|
33
|
+
function cast(source) {
|
|
34
|
+
return source;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
class BeanSimple {
|
|
38
|
+
constructor() {
|
|
39
|
+
this.app = void 0;
|
|
40
|
+
}
|
|
41
|
+
get ctx() {
|
|
42
|
+
return this.app.currentContext;
|
|
43
|
+
}
|
|
44
|
+
get bean() {
|
|
45
|
+
return this.app.bean;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const localeDefault = {
|
|
50
|
+
modules: {}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const EnumAppEvent = {
|
|
54
|
+
AppStarted: 'eb:event:appStarted',
|
|
55
|
+
AppStartError: 'eb:event:appStartError'
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
function zodEnhance() {
|
|
59
|
+
setLocaleAdapter((text, iss) => {
|
|
60
|
+
const app = useApp();
|
|
61
|
+
return translateError((text, ...args) => {
|
|
62
|
+
return app.meta.text(text, ...args);
|
|
63
|
+
}, text, iss);
|
|
64
|
+
});
|
|
65
|
+
setParseAdapter(ZodMetadata);
|
|
66
|
+
}
|
|
67
|
+
function zodSetLocaleErrors(app, localeErrors, localeDefault) {
|
|
68
|
+
setLocaleErrors(() => {
|
|
69
|
+
return app.meta.locale.current;
|
|
70
|
+
}, localeErrors, localeDefault);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const SymbolProdRootPath = Symbol('SymbolProdRootPath');
|
|
74
|
+
class AppUtil extends BeanSimple {
|
|
75
|
+
constructor(...args) {
|
|
76
|
+
super(...args);
|
|
77
|
+
this[SymbolProdRootPath] = void 0;
|
|
78
|
+
}
|
|
79
|
+
instanceStarted(instanceName) {
|
|
80
|
+
return this.app.meta.appReadyInstances && this.app.meta.appReadyInstances[instanceName];
|
|
81
|
+
}
|
|
82
|
+
get protocol() {
|
|
83
|
+
const config = this.ctx ? this.ctx.config : this.app.config;
|
|
84
|
+
return config.server.serve.protocol || this.ctx?.protocol;
|
|
85
|
+
}
|
|
86
|
+
get host() {
|
|
87
|
+
const config = this.ctx ? this.ctx.config : this.app.config;
|
|
88
|
+
return config.server.serve.host || this.ctx?.host;
|
|
89
|
+
}
|
|
90
|
+
getAbsoluteUrl(path) {
|
|
91
|
+
const prefix = this.host ? `${this.protocol}://${this.host}` : '';
|
|
92
|
+
return `${prefix}${path || ''}`;
|
|
93
|
+
}
|
|
94
|
+
getAbsoluteUrlByApiPath(path) {
|
|
95
|
+
return this.getAbsoluteUrl(this.combineApiPath(path, '', true, true));
|
|
96
|
+
}
|
|
97
|
+
combineApiPathControllerAndActionRaw(moduleName, controllerPath, actionPath, simplify) {
|
|
98
|
+
return combineApiPathControllerAndActionRaw(moduleName, controllerPath, actionPath, simplify);
|
|
99
|
+
}
|
|
100
|
+
combineApiPathControllerAndAction(moduleName, controllerPath, actionPath, prefix, simplify) {
|
|
101
|
+
return combineApiPathControllerAndAction(moduleName, controllerPath, actionPath, prefix, simplify, this.app.config.server.globalPrefix);
|
|
102
|
+
}
|
|
103
|
+
combineApiPath(path, moduleName, prefix, simplify) {
|
|
104
|
+
return combineApiPath(path, moduleName, prefix, simplify, this.app.config.server.globalPrefix);
|
|
105
|
+
}
|
|
106
|
+
combineStaticPath(staticPath, moduleName) {
|
|
107
|
+
const globalPrefix = '/api/static';
|
|
108
|
+
if (!staticPath) staticPath = '';
|
|
109
|
+
// safe
|
|
110
|
+
staticPath = path.normalize(staticPath);
|
|
111
|
+
if (staticPath.includes('..')) throw new Error(`unsafe path: ${staticPath}`);
|
|
112
|
+
// ignore globalPrefix
|
|
113
|
+
if (staticPath.startsWith('//')) return staticPath.substring(1);
|
|
114
|
+
// ignore module path
|
|
115
|
+
if (staticPath.startsWith('/')) return `${globalPrefix}${staticPath}`;
|
|
116
|
+
// globalPrefix + module path + arg
|
|
117
|
+
if (!moduleName) throw new Error('should specify the moduleName');
|
|
118
|
+
if (typeof moduleName !== 'string') moduleName = moduleName.relativeName;
|
|
119
|
+
const parts = moduleName.split('-');
|
|
120
|
+
// path
|
|
121
|
+
return `${globalPrefix}/${parts[0]}/${parts[1]}/${staticPath}`;
|
|
122
|
+
}
|
|
123
|
+
combineResourceName(resourceName, moduleName, simplify, simplifyProviderId) {
|
|
124
|
+
return combineResourceName(resourceName, moduleName, simplify, simplifyProviderId);
|
|
125
|
+
}
|
|
126
|
+
async getPublicPathPhysical(subdir, ensure) {
|
|
127
|
+
const rootPath = this.app.config.server.publicDir;
|
|
128
|
+
// use instance.id, not instanceName
|
|
129
|
+
const dir = combineFilePathSafe(path.join(rootPath, cast(this.ctx).instance.id.toString()), subdir || '');
|
|
130
|
+
if (!dir) throw new Error('not valid path');
|
|
131
|
+
if (ensure) {
|
|
132
|
+
await fse.ensureDir(dir);
|
|
133
|
+
}
|
|
134
|
+
return dir;
|
|
135
|
+
}
|
|
136
|
+
get prodRootPath() {
|
|
137
|
+
if (!this.app.meta.isProd) throw new Error('only invoked in prod');
|
|
138
|
+
if (!this[SymbolProdRootPath]) {
|
|
139
|
+
this[SymbolProdRootPath] = import.meta.dirname;
|
|
140
|
+
}
|
|
141
|
+
return this[SymbolProdRootPath];
|
|
142
|
+
}
|
|
143
|
+
getAssetPathPhysical(moduleName, scene, assetPath) {
|
|
144
|
+
if (typeof moduleName !== 'string') moduleName = moduleName.relativeName;
|
|
145
|
+
if (this.app.meta.isProd) {
|
|
146
|
+
return combineFilePathSafe(path.join(this.prodRootPath, 'assets', scene, moduleName), assetPath || '');
|
|
147
|
+
} else {
|
|
148
|
+
const module = this.app.meta.modules[moduleName];
|
|
149
|
+
if (!module) throw new Error('module not found');
|
|
150
|
+
return combineFilePathSafe(path.join(module.root, 'assets', scene), assetPath || '');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
createError(data, returnObject) {
|
|
154
|
+
const error = returnObject ? {} : new Error();
|
|
155
|
+
error.code = data.code !== undefined ? data.code : 500;
|
|
156
|
+
if (data.message && typeof data.message === 'object') {
|
|
157
|
+
error.message = JSON.stringify(data.message, null, 2);
|
|
158
|
+
} else {
|
|
159
|
+
error.message = data.message;
|
|
160
|
+
}
|
|
161
|
+
if (!this.app.meta.isProd) {
|
|
162
|
+
if (data.stack) error.stack = data.stack;
|
|
163
|
+
if (data.name) error.name = data.name;
|
|
164
|
+
if (data.errno) error.errno = data.errno;
|
|
165
|
+
if (data.sqlMessage) error.sqlMessage = data.sqlMessage;
|
|
166
|
+
if (data.sqlState) error.sqlState = data.sqlState;
|
|
167
|
+
if (data.index) error.index = data.index;
|
|
168
|
+
if (data.sql) error.sql = data.sql;
|
|
169
|
+
}
|
|
170
|
+
return error;
|
|
171
|
+
}
|
|
172
|
+
async monkeyModule(ebAppMonkey, ebModulesMonkey, monkeyName, moduleTarget, ...monkeyData) {
|
|
173
|
+
// self: main
|
|
174
|
+
if (moduleTarget && moduleTarget.mainInstance && moduleTarget.mainInstance[monkeyName]) {
|
|
175
|
+
// @ts-ignore ignore
|
|
176
|
+
await moduleTarget.mainInstance[monkeyName](...monkeyData);
|
|
177
|
+
}
|
|
178
|
+
// module monkey
|
|
179
|
+
for (const key in ebModulesMonkey) {
|
|
180
|
+
const moduleMonkey = ebModulesMonkey[key];
|
|
181
|
+
if (moduleMonkey.monkeyInstance && moduleMonkey.monkeyInstance[monkeyName]) {
|
|
182
|
+
if (moduleTarget === undefined) {
|
|
183
|
+
// @ts-ignore ignore
|
|
184
|
+
await moduleMonkey.monkeyInstance[monkeyName](...monkeyData);
|
|
185
|
+
} else {
|
|
186
|
+
// @ts-ignore ignore
|
|
187
|
+
await moduleMonkey.monkeyInstance[monkeyName](moduleTarget, ...monkeyData);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// app monkey
|
|
192
|
+
if (ebAppMonkey && ebAppMonkey[monkeyName]) {
|
|
193
|
+
if (moduleTarget === undefined) {
|
|
194
|
+
await ebAppMonkey[monkeyName](...monkeyData);
|
|
195
|
+
} else {
|
|
196
|
+
await ebAppMonkey[monkeyName](moduleTarget, ...monkeyData);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
monkeyModuleSync(ebAppMonkey, ebModulesMonkey, monkeyName, moduleTarget, ...monkeyData) {
|
|
201
|
+
// self: main
|
|
202
|
+
if (moduleTarget && moduleTarget.mainInstance && moduleTarget.mainInstance[monkeyName]) {
|
|
203
|
+
// @ts-ignore ignore
|
|
204
|
+
moduleTarget.mainInstance[monkeyName](...monkeyData);
|
|
205
|
+
}
|
|
206
|
+
// module monkey
|
|
207
|
+
for (const key in ebModulesMonkey) {
|
|
208
|
+
const moduleMonkey = ebModulesMonkey[key];
|
|
209
|
+
if (moduleMonkey.monkeyInstance && moduleMonkey.monkeyInstance[monkeyName]) {
|
|
210
|
+
if (moduleTarget === undefined) {
|
|
211
|
+
// @ts-ignore ignore
|
|
212
|
+
moduleMonkey.monkeyInstance[monkeyName](...monkeyData);
|
|
213
|
+
} else {
|
|
214
|
+
// @ts-ignore ignore
|
|
215
|
+
moduleMonkey.monkeyInstance[monkeyName](moduleTarget, ...monkeyData);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// app monkey
|
|
220
|
+
if (ebAppMonkey && ebAppMonkey[monkeyName]) {
|
|
221
|
+
if (moduleTarget === undefined) {
|
|
222
|
+
ebAppMonkey[monkeyName](...monkeyData);
|
|
223
|
+
} else {
|
|
224
|
+
ebAppMonkey[monkeyName](moduleTarget, ...monkeyData);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
detectErrorMessage(err) {
|
|
229
|
+
// detect json parse error
|
|
230
|
+
if (err.status === 400 && err.name === 'SyntaxError' && this.ctx.request.is('application/json', 'application/vnd.api+json', 'application/csp-report')) {
|
|
231
|
+
return 'Problems parsing JSON';
|
|
232
|
+
}
|
|
233
|
+
return err.message;
|
|
234
|
+
}
|
|
235
|
+
detectStatus(err) {
|
|
236
|
+
// detect status
|
|
237
|
+
let status = err.status || 500;
|
|
238
|
+
if (typeof status !== 'number') status = Number(status);
|
|
239
|
+
if (status < 200) {
|
|
240
|
+
// invalid status consider as 500, like urllib will return -1 status
|
|
241
|
+
status = 500;
|
|
242
|
+
}
|
|
243
|
+
return status;
|
|
244
|
+
}
|
|
245
|
+
accepts() {
|
|
246
|
+
if (this.ctx.acceptJSON) return 'json';
|
|
247
|
+
return 'html';
|
|
248
|
+
}
|
|
249
|
+
getModuleConfigRaw(moduleName) {
|
|
250
|
+
return this.app.config.modules[moduleName];
|
|
251
|
+
}
|
|
252
|
+
setLocaleErrors(localeErrors, localeDefault) {
|
|
253
|
+
return zodSetLocaleErrors(this.app, localeErrors, localeDefault);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function compose(chains, adapter) {
|
|
257
|
+
return compose$1(chains, adapter);
|
|
258
|
+
}
|
|
259
|
+
function instanceDesp(instanceName) {
|
|
260
|
+
if (instanceName === undefined || instanceName === null) return '~';
|
|
261
|
+
return instanceName || '-';
|
|
262
|
+
}
|
|
263
|
+
function requireDynamic(file) {
|
|
264
|
+
if (!file) throw new Error('file should not empty');
|
|
265
|
+
const require = createRequire(import.meta.url);
|
|
266
|
+
let instance = require(file);
|
|
267
|
+
const mtime = _requireDynamic_getFileTime(file);
|
|
268
|
+
if (instance.__requireDynamic_mtime === undefined) {
|
|
269
|
+
instance.__requireDynamic_mtime = mtime;
|
|
270
|
+
} else if (instance.__requireDynamic_mtime !== mtime) {
|
|
271
|
+
delete require.cache[require.resolve(file)];
|
|
272
|
+
instance = require(file);
|
|
273
|
+
instance.__requireDynamic_mtime = mtime;
|
|
274
|
+
}
|
|
275
|
+
return instance;
|
|
276
|
+
}
|
|
277
|
+
function _requireDynamic_getFileTime(file) {
|
|
278
|
+
if (!path.isAbsolute(file)) return null;
|
|
279
|
+
const exists = fse.pathExistsSync(file);
|
|
280
|
+
if (!exists) return null;
|
|
281
|
+
// stat
|
|
282
|
+
const stat = fse.statSync(file);
|
|
283
|
+
return stat.mtime.valueOf();
|
|
284
|
+
}
|
|
285
|
+
function deepExtend(target, ...args) {
|
|
286
|
+
return extend(true, target, ...args);
|
|
287
|
+
}
|
|
288
|
+
function uuidv4() {
|
|
289
|
+
return uuid.v4();
|
|
290
|
+
}
|
|
291
|
+
function createHash(str, encoding, algorithm, options) {
|
|
292
|
+
const hash = crypto.createHash(algorithm ?? 'sha256', options);
|
|
293
|
+
hash.update(str);
|
|
294
|
+
return hash.digest(encoding ?? 'hex');
|
|
295
|
+
}
|
|
296
|
+
async function disposeInstance(instance) {
|
|
297
|
+
await instance?.__dispose__?.();
|
|
298
|
+
}
|
|
299
|
+
function polyfillDispose(instance) {
|
|
300
|
+
if (!instance || instance.__dispose__) return;
|
|
301
|
+
Object.getPrototypeOf(instance).__dispose__ = () => {};
|
|
302
|
+
}
|
|
303
|
+
function pathToHref(fileName) {
|
|
304
|
+
return pathToFileURL(fileName).href;
|
|
305
|
+
// return Path.sep === '\\' ? pathToFileURL(fileName).href : fileName;
|
|
306
|
+
}
|
|
307
|
+
function prepareEnv(env) {
|
|
308
|
+
const env2 = {
|
|
309
|
+
...env
|
|
310
|
+
};
|
|
311
|
+
for (const key of Object.keys(env2)) {
|
|
312
|
+
if (process.env[key] !== undefined) {
|
|
313
|
+
env2[key] = process.env[key];
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return env2;
|
|
317
|
+
}
|
|
318
|
+
function beanFullNameFromOnionName(onionName, sceneName) {
|
|
319
|
+
return onionName.replace(':', `.${sceneName}.`);
|
|
320
|
+
}
|
|
321
|
+
function onionNameFromBeanFullName(beanFullName, sceneName) {
|
|
322
|
+
return beanFullName.replace(`.${sceneName}.`, ':');
|
|
323
|
+
}
|
|
324
|
+
function filterHeaders(headers, whitelist) {
|
|
325
|
+
if (!headers) return;
|
|
326
|
+
const res = {};
|
|
327
|
+
for (const key in headers) {
|
|
328
|
+
if (whitelist.includes(key)) {
|
|
329
|
+
res[key] = headers[key];
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return res;
|
|
333
|
+
}
|
|
334
|
+
function combineFilePathSafe(dir, file) {
|
|
335
|
+
const fullPath = path.normalize(path.join(dir, file));
|
|
336
|
+
// files that can be accessd should be under options.dir
|
|
337
|
+
if (fullPath.indexOf(dir) !== 0) throw new Error(`unsafe dir: ${dir}`);
|
|
338
|
+
return fullPath;
|
|
339
|
+
}
|
|
340
|
+
async function loadJSONFile(fileName) {
|
|
341
|
+
const pkgContent = (await fse.readFile(fileName)).toString();
|
|
342
|
+
return JSON.parse(pkgContent);
|
|
343
|
+
}
|
|
344
|
+
async function saveJSONFile(fileName, json) {
|
|
345
|
+
await fse.writeFile(fileName, `${JSON.stringify(json, null, 2)}\n`);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function useApp() {
|
|
349
|
+
return globalThis.__app__;
|
|
350
|
+
}
|
|
351
|
+
async function closeApp(terminate) {
|
|
352
|
+
while (globalThis.__closing__) {
|
|
353
|
+
await sleep(50);
|
|
354
|
+
}
|
|
355
|
+
try {
|
|
356
|
+
globalThis.__closing__ = true;
|
|
357
|
+
if (globalThis.__app__) {
|
|
358
|
+
await globalThis.__app__.meta.close();
|
|
359
|
+
delete globalThis.__app__;
|
|
360
|
+
}
|
|
361
|
+
} finally {
|
|
362
|
+
globalThis.__closing__ = false;
|
|
363
|
+
}
|
|
364
|
+
if (terminate) {
|
|
365
|
+
process.kill(process.pid, 'SIGTERM');
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
async function createGeneralApp(projectPath, envRuntime) {
|
|
369
|
+
if (envRuntime) {
|
|
370
|
+
for (const key of Object.keys(envRuntime)) {
|
|
371
|
+
process.env[key] = envRuntime[key];
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (process.env.META_MODE === 'prod') {
|
|
375
|
+
const testFile = path.join(projectPath, `dist/${process.env.META_FLAVOR}/bootstrap.js`);
|
|
376
|
+
const testInstance = await import(pathToHref(testFile));
|
|
377
|
+
return await testInstance.appBootstrap;
|
|
378
|
+
} else {
|
|
379
|
+
const testFile = path.join(projectPath, '.vona/app.ts');
|
|
380
|
+
const testInstance = await import(pathToHref(testFile));
|
|
381
|
+
return await testInstance.createSingleApp();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// export async function reloadApp() {
|
|
386
|
+
// while (globalThis.__reloading__) {
|
|
387
|
+
// await sleep(100);
|
|
388
|
+
// }
|
|
389
|
+
// try {
|
|
390
|
+
// globalThis.__reloading__ = true;
|
|
391
|
+
// await closeApp();
|
|
392
|
+
// await createApp(globalThis.__bootstrapOptions__);
|
|
393
|
+
// } finally {
|
|
394
|
+
// globalThis.__reloading__ = false;
|
|
395
|
+
// }
|
|
396
|
+
// }
|
|
397
|
+
|
|
398
|
+
class AppMetadata {
|
|
399
|
+
defineMetadata(metadataKey, metadataValue, target, prop) {
|
|
400
|
+
if (isUndefined(prop)) {
|
|
401
|
+
Reflect.defineMetadata(metadataKey, metadataValue, target);
|
|
402
|
+
} else {
|
|
403
|
+
Reflect.defineMetadata(metadataKey, metadataValue, target, prop);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
hasOwnMetadata(metadataKey, target, prop) {
|
|
407
|
+
if (isUndefined(prop)) return Reflect.hasOwnMetadata(metadataKey, target);
|
|
408
|
+
return Reflect.hasOwnMetadata(metadataKey, target, prop);
|
|
409
|
+
}
|
|
410
|
+
hasMetadata(metadataKey, target, prop) {
|
|
411
|
+
if (isUndefined(prop)) return Reflect.hasMetadata(metadataKey, target);
|
|
412
|
+
return Reflect.hasMetadata(metadataKey, target, prop);
|
|
413
|
+
}
|
|
414
|
+
getOwnMetadata(metadataKey, target, prop) {
|
|
415
|
+
if (isUndefined(prop)) return Reflect.getOwnMetadata(metadataKey, target);
|
|
416
|
+
return Reflect.getOwnMetadata(metadataKey, target, prop);
|
|
417
|
+
}
|
|
418
|
+
getMetadata(metadataKey, target, prop) {
|
|
419
|
+
if (isUndefined(prop)) return Reflect.getMetadata(metadataKey, target);
|
|
420
|
+
return Reflect.getMetadata(metadataKey, target, prop);
|
|
421
|
+
}
|
|
422
|
+
getOwnMetadataArray(inherit, metadataKey, target, prop) {
|
|
423
|
+
let own = this.getOwnMetadata(metadataKey, target, prop);
|
|
424
|
+
if (!own) {
|
|
425
|
+
if (!inherit) {
|
|
426
|
+
own = [];
|
|
427
|
+
} else {
|
|
428
|
+
const parent = this.getMetadata(metadataKey, target, prop);
|
|
429
|
+
if (parent) {
|
|
430
|
+
own = parent.slice();
|
|
431
|
+
} else {
|
|
432
|
+
own = [];
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
this.defineMetadata(metadataKey, own, target, prop);
|
|
436
|
+
}
|
|
437
|
+
return own;
|
|
438
|
+
}
|
|
439
|
+
getOwnMetadataMap(inherit, metadataKey, target, prop) {
|
|
440
|
+
let own = this.getOwnMetadata(metadataKey, target, prop);
|
|
441
|
+
if (!own) {
|
|
442
|
+
if (!inherit) {
|
|
443
|
+
own = {};
|
|
444
|
+
} else {
|
|
445
|
+
const parent = this.getMetadata(metadataKey, target, prop);
|
|
446
|
+
if (parent) {
|
|
447
|
+
own = Object.assign({}, parent);
|
|
448
|
+
} else {
|
|
449
|
+
own = {};
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
this.defineMetadata(metadataKey, own, target, prop);
|
|
453
|
+
}
|
|
454
|
+
return own;
|
|
455
|
+
}
|
|
456
|
+
getDesignType(target, prop) {
|
|
457
|
+
return this.getMetadata('design:type', target, prop);
|
|
458
|
+
}
|
|
459
|
+
getDesignParamtypes(target, prop) {
|
|
460
|
+
return this.getMetadata('design:paramtypes', target, prop);
|
|
461
|
+
}
|
|
462
|
+
getDesignReturntype(target, prop) {
|
|
463
|
+
return this.getMetadata('design:returntype', target, prop);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
const appMetadata = new AppMetadata();
|
|
467
|
+
|
|
468
|
+
const SymbolMappedClassMetadataKeys = Symbol('SymbolMappedClassMetakeys');
|
|
469
|
+
|
|
470
|
+
function registerMappedClassMetadataKey(target, metadataKey, options) {
|
|
471
|
+
const metadataKeys = appMetadata.getOwnMetadataMap(true, SymbolMappedClassMetadataKeys, target);
|
|
472
|
+
if (!Object.hasOwn(metadataKeys, metadataKey)) {
|
|
473
|
+
metadataKeys[metadataKey] = options;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
function getMappedClassMetadataKeys(target) {
|
|
477
|
+
return appMetadata.getMetadata(SymbolMappedClassMetadataKeys, target);
|
|
478
|
+
}
|
|
479
|
+
function setMappedClassMetadataKeys(target, metadataKeys) {
|
|
480
|
+
return appMetadata.defineMetadata(SymbolMappedClassMetadataKeys, metadataKeys, target);
|
|
481
|
+
}
|
|
482
|
+
function copyPropertiesOfClasses(target, sources, filter) {
|
|
483
|
+
for (const source of sources) {
|
|
484
|
+
copyProperties(target, source, ['constructor', 'prototype', 'length', 'name'], filter); // copy static
|
|
485
|
+
copyProperties(target.prototype, source.prototype, ['constructor', 'prototype'], filter); // copy prototype
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
function copyProperties(target, source, keysIgnore, filter) {
|
|
489
|
+
const protos = [];
|
|
490
|
+
let _proto = source;
|
|
491
|
+
while (_proto) {
|
|
492
|
+
if (!['Object'].includes(_proto.constructor?.name) && !Object.hasOwn(_proto, 'arguments')) {
|
|
493
|
+
protos.unshift(_proto);
|
|
494
|
+
}
|
|
495
|
+
_proto = Object.getPrototypeOf(_proto);
|
|
496
|
+
}
|
|
497
|
+
for (const proto of protos) {
|
|
498
|
+
for (const key of Reflect.ownKeys(proto)) {
|
|
499
|
+
if (keysIgnore.includes(key)) continue;
|
|
500
|
+
if (filter && !filter(key)) continue;
|
|
501
|
+
// desc
|
|
502
|
+
const desc = Object.getOwnPropertyDescriptor(proto, key);
|
|
503
|
+
Object.defineProperty(target, key, desc);
|
|
504
|
+
// metadata
|
|
505
|
+
const metaKeys = Reflect.getOwnMetadataKeys(proto, key);
|
|
506
|
+
for (const metaKey of metaKeys) {
|
|
507
|
+
const metaValue = Reflect.getOwnMetadata(metaKey, proto, key);
|
|
508
|
+
Reflect.defineMetadata(metaKey, metaValue, target, key);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
function copyMetadataOfClasses(target, sources, transform) {
|
|
514
|
+
//
|
|
515
|
+
const metadataKeys = {};
|
|
516
|
+
for (const source of sources) {
|
|
517
|
+
const _metadataKeys = getMappedClassMetadataKeys(source);
|
|
518
|
+
if (_metadataKeys) {
|
|
519
|
+
Object.assign(metadataKeys, _metadataKeys);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
setMappedClassMetadataKeys(target, metadataKeys);
|
|
523
|
+
//
|
|
524
|
+
for (const metadataKey of Object.getOwnPropertySymbols(metadataKeys)) {
|
|
525
|
+
const metadataKeyOptions = metadataKeys[metadataKey];
|
|
526
|
+
const rulesNew = {};
|
|
527
|
+
for (const source of sources) {
|
|
528
|
+
const rules = appMetadata.getMetadata(metadataKey, source);
|
|
529
|
+
if (!rules) continue;
|
|
530
|
+
if (!transform) {
|
|
531
|
+
Object.assign(rulesNew, rules);
|
|
532
|
+
} else {
|
|
533
|
+
for (const key in rules) {
|
|
534
|
+
const ruleNew = transform(rules, key, metadataKeyOptions);
|
|
535
|
+
if (ruleNew !== undefined) {
|
|
536
|
+
rulesNew[key] = ruleNew;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
appMetadata.defineMetadata(metadataKey, rulesNew, target);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const SymbolDecoratorBeanFullName = Symbol('SymbolDecoratorBeanFullName');
|
|
546
|
+
const SymbolDecoratorBeanInfo = Symbol('SymbolDecoratorBeanInfo');
|
|
547
|
+
const SymbolDecoratorProxyDisable = Symbol('SymbolDecoratorProxyDisable');
|
|
548
|
+
const SymbolDecoratorVirtual = Symbol('SymbolDecoratorVirtual');
|
|
549
|
+
const SymbolDecoratorUse = Symbol('SymbolDecoratorUse');
|
|
550
|
+
class AppResource extends BeanSimple {
|
|
551
|
+
constructor(...args) {
|
|
552
|
+
super(...args);
|
|
553
|
+
this.beans = {};
|
|
554
|
+
this.scenes = {};
|
|
555
|
+
}
|
|
556
|
+
addUse(target, options) {
|
|
557
|
+
registerMappedClassMetadataKey(target, SymbolDecoratorUse);
|
|
558
|
+
const uses = appMetadata.getOwnMetadataMap(true, SymbolDecoratorUse, target);
|
|
559
|
+
uses[options.prop] = options;
|
|
560
|
+
}
|
|
561
|
+
getUses(target) {
|
|
562
|
+
return appMetadata.getMetadata(SymbolDecoratorUse, target);
|
|
563
|
+
}
|
|
564
|
+
addBean(beanOptions) {
|
|
565
|
+
let {
|
|
566
|
+
module,
|
|
567
|
+
scene,
|
|
568
|
+
name,
|
|
569
|
+
beanClass,
|
|
570
|
+
options,
|
|
571
|
+
optionsPrimitive
|
|
572
|
+
} = beanOptions;
|
|
573
|
+
// virtual
|
|
574
|
+
const virtual = appMetadata.getOwnMetadata(SymbolDecoratorVirtual, beanClass);
|
|
575
|
+
// name
|
|
576
|
+
name = this._parseBeanName(beanClass, scene, name);
|
|
577
|
+
// module
|
|
578
|
+
if (!module) {
|
|
579
|
+
throw new Error(`module name not parsed for bean: ${scene}.${name}`);
|
|
580
|
+
}
|
|
581
|
+
// beanFullName
|
|
582
|
+
const beanFullName = scene && scene !== 'bean' ? `${module}.${scene}.${name}` : name;
|
|
583
|
+
// moduleBelong
|
|
584
|
+
const moduleBelong = this._parseModuleBelong(module, beanClass, virtual);
|
|
585
|
+
// options
|
|
586
|
+
const options2 = this._prepareOnionOptions(options, optionsPrimitive, scene, `${module}:${name}`);
|
|
587
|
+
// beanOptions2
|
|
588
|
+
const beanOptions2 = {
|
|
589
|
+
...beanOptions,
|
|
590
|
+
beanFullName,
|
|
591
|
+
name,
|
|
592
|
+
moduleBelong,
|
|
593
|
+
options: options2
|
|
594
|
+
};
|
|
595
|
+
// record
|
|
596
|
+
this.beans[beanFullName] = beanOptions2;
|
|
597
|
+
if (!this.scenes[scene]) this.scenes[scene] = {};
|
|
598
|
+
if (!this.scenes[scene][module]) this.scenes[scene][module] = {};
|
|
599
|
+
this.scenes[scene][module][beanFullName] = beanOptions2;
|
|
600
|
+
// set metadata
|
|
601
|
+
appMetadata.defineMetadata(SymbolDecoratorBeanFullName, beanFullName, beanOptions2.beanClass);
|
|
602
|
+
// ok
|
|
603
|
+
return beanOptions2;
|
|
604
|
+
}
|
|
605
|
+
getBeanFullName(beanFullName) {
|
|
606
|
+
if (!beanFullName) return beanFullName;
|
|
607
|
+
if (typeof beanFullName === 'function' && isClass(beanFullName)) {
|
|
608
|
+
return appMetadata.getOwnMetadata(SymbolDecoratorBeanFullName, beanFullName);
|
|
609
|
+
}
|
|
610
|
+
return beanFullName;
|
|
611
|
+
}
|
|
612
|
+
getBean(beanFullName) {
|
|
613
|
+
const fullName = this.getBeanFullName(beanFullName);
|
|
614
|
+
if (!fullName) return null;
|
|
615
|
+
return this.beans[fullName];
|
|
616
|
+
}
|
|
617
|
+
_parseBeanName(beanClass, scene, name) {
|
|
618
|
+
// name
|
|
619
|
+
if (name) return name;
|
|
620
|
+
// scene
|
|
621
|
+
if (!scene) scene = 'bean';
|
|
622
|
+
scene = scene.replace(/\./g, '');
|
|
623
|
+
// bean class name
|
|
624
|
+
const beanClassName = this._fixClassName(beanClass.name);
|
|
625
|
+
if (beanClassName.toLocaleUpperCase().startsWith(scene.toLocaleUpperCase())) {
|
|
626
|
+
name = beanClassName.substring(scene.length);
|
|
627
|
+
} else {
|
|
628
|
+
name = beanClassName;
|
|
629
|
+
}
|
|
630
|
+
// lowerCase
|
|
631
|
+
name = toLowerCaseFirstChar(name);
|
|
632
|
+
return name;
|
|
633
|
+
}
|
|
634
|
+
_parseModuleBelong(module, beanClass, virtual) {
|
|
635
|
+
if (!virtual) return module;
|
|
636
|
+
// check parent
|
|
637
|
+
let moduleBelong;
|
|
638
|
+
let parent = Object.getPrototypeOf(beanClass);
|
|
639
|
+
while (parent) {
|
|
640
|
+
const beanOptions = this.getBean(parent);
|
|
641
|
+
if (beanOptions && beanOptions.moduleBelong) {
|
|
642
|
+
moduleBelong = beanOptions.moduleBelong;
|
|
643
|
+
break;
|
|
644
|
+
}
|
|
645
|
+
parent = Object.getPrototypeOf(parent);
|
|
646
|
+
}
|
|
647
|
+
return moduleBelong;
|
|
648
|
+
}
|
|
649
|
+
_getModuleBelong(beanFullName) {
|
|
650
|
+
const beanOptions = this.getBean(beanFullName);
|
|
651
|
+
if (!beanOptions || !beanOptions.moduleBelong) throw new Error(`not found module belong: ${beanFullName}`);
|
|
652
|
+
return beanOptions.moduleBelong;
|
|
653
|
+
}
|
|
654
|
+
_getModuleName(beanFullName) {
|
|
655
|
+
const beanOptions = this.getBean(beanFullName);
|
|
656
|
+
return beanOptions?.module;
|
|
657
|
+
}
|
|
658
|
+
_fixClassName(className) {
|
|
659
|
+
while (className.endsWith('2')) {
|
|
660
|
+
className = className.substring(0, className.length - 1);
|
|
661
|
+
}
|
|
662
|
+
return className;
|
|
663
|
+
}
|
|
664
|
+
_prepareOnionOptions(options, optionsPrimitive, scene, name) {
|
|
665
|
+
const app = useApp();
|
|
666
|
+
if (!app?.config && scene !== 'scope') {
|
|
667
|
+
throw new Error('Should not import vona module in config');
|
|
668
|
+
}
|
|
669
|
+
const optionsConfig = cast(app?.config)?.onions?.[scene]?.[name];
|
|
670
|
+
if (optionsPrimitive) {
|
|
671
|
+
return optionsConfig === undefined ? options : optionsConfig;
|
|
672
|
+
} else {
|
|
673
|
+
return deepExtend({}, options, optionsConfig);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
const appResource = new AppResource();
|
|
678
|
+
|
|
679
|
+
const SymbolBeanFullName = Symbol('SymbolBeanFullName');
|
|
680
|
+
const SymbolBeanInstanceKey = Symbol('SymbolBeanInstanceKey');
|
|
681
|
+
const SymbolModuleBelong = Symbol('SymbolModuleBelong');
|
|
682
|
+
const SymbolModuleName = Symbol('SymbolModuleName');
|
|
683
|
+
class BeanBaseSimple extends BeanSimple {
|
|
684
|
+
constructor(...args) {
|
|
685
|
+
super(...args);
|
|
686
|
+
this[SymbolBeanFullName] = void 0;
|
|
687
|
+
}
|
|
688
|
+
get [SymbolModuleBelong]() {
|
|
689
|
+
return appResource._getModuleBelong(this[SymbolBeanFullName]);
|
|
690
|
+
}
|
|
691
|
+
get [SymbolModuleName]() {
|
|
692
|
+
return appResource._getModuleName(this[SymbolBeanFullName]);
|
|
693
|
+
}
|
|
694
|
+
get $beanFullName() {
|
|
695
|
+
return this[SymbolBeanFullName];
|
|
696
|
+
}
|
|
697
|
+
get $beanOptions() {
|
|
698
|
+
return appResource.getBean(this[SymbolBeanFullName]);
|
|
699
|
+
}
|
|
700
|
+
get $onionName() {
|
|
701
|
+
const parts = this.$beanFullName.split('.');
|
|
702
|
+
return `${parts[0]}:${parts[2]}`;
|
|
703
|
+
}
|
|
704
|
+
get $onionOptions() {
|
|
705
|
+
return this.$beanOptions.options;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
const SymbolText = Symbol('SymbolText');
|
|
710
|
+
const SymbolLogger = Symbol('SymbolLogger');
|
|
711
|
+
const SymbolLoggerChildren = Symbol('SymbolLoggerChildren');
|
|
712
|
+
class BeanBase extends BeanBaseSimple {
|
|
713
|
+
constructor(...args) {
|
|
714
|
+
super(...args);
|
|
715
|
+
this[SymbolText] = void 0;
|
|
716
|
+
this[SymbolLogger] = {};
|
|
717
|
+
this[SymbolLoggerChildren] = {};
|
|
718
|
+
}
|
|
719
|
+
get $text() {
|
|
720
|
+
if (!this[SymbolText]) {
|
|
721
|
+
this[SymbolText] = this.app.meta.locale.createLocaleText(this[SymbolModuleBelong]);
|
|
722
|
+
}
|
|
723
|
+
return this[SymbolText];
|
|
724
|
+
}
|
|
725
|
+
get $logger() {
|
|
726
|
+
return this.$loggerClient('default');
|
|
727
|
+
}
|
|
728
|
+
$loggerClient(clientName = 'default') {
|
|
729
|
+
if (!this[SymbolLogger][clientName]) {
|
|
730
|
+
this[SymbolLogger][clientName] = this.app.meta.logger.get(clientName).child({
|
|
731
|
+
beanFullName: this.$beanFullName
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
return this[SymbolLogger][clientName];
|
|
735
|
+
}
|
|
736
|
+
$loggerChild(childName, clientName = 'default') {
|
|
737
|
+
if (!this[SymbolLoggerChildren][clientName]) this[SymbolLoggerChildren][clientName] = {};
|
|
738
|
+
if (!this[SymbolLoggerChildren][clientName][childName]) {
|
|
739
|
+
this[SymbolLoggerChildren][clientName][childName] = this.app.meta.logger.get(clientName).child({
|
|
740
|
+
beanFullName: this.$beanFullName,
|
|
741
|
+
name: childName
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
return this[SymbolLoggerChildren][clientName][childName];
|
|
745
|
+
}
|
|
746
|
+
$mutate(args) {
|
|
747
|
+
this.app.meta.hmr?.mutateBeanInstance(this.$beanFullName, this[SymbolBeanInstanceKey], args);
|
|
748
|
+
}
|
|
749
|
+
get $scope() {
|
|
750
|
+
return this.app.meta.scopeContainer;
|
|
751
|
+
}
|
|
752
|
+
get scope() {
|
|
753
|
+
return this.bean.scope(this[SymbolModuleBelong]);
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
class BeanAopBase extends BeanBase {}
|
|
758
|
+
|
|
759
|
+
class BeanAopMethodBase extends BeanBase {}
|
|
760
|
+
|
|
761
|
+
function BeanInfo(options) {
|
|
762
|
+
return function (target) {
|
|
763
|
+
// set metadata
|
|
764
|
+
appMetadata.defineMetadata(SymbolDecoratorBeanInfo, options, target);
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
class AppHmrDeps extends BeanSimple {
|
|
769
|
+
constructor(...args) {
|
|
770
|
+
super(...args);
|
|
771
|
+
this._deps = {};
|
|
772
|
+
this._depsTemp = void 0;
|
|
773
|
+
}
|
|
774
|
+
get deps() {
|
|
775
|
+
return this._deps;
|
|
776
|
+
}
|
|
777
|
+
addBeans(classRefs) {
|
|
778
|
+
for (const classRef of classRefs) {
|
|
779
|
+
this.addBean(classRef);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
addBean(classRef) {
|
|
783
|
+
const beanOptions = appResource.getBean(classRef);
|
|
784
|
+
if (beanOptions) {
|
|
785
|
+
this.add(beanOptions.beanFullName);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
add(beanFullName) {
|
|
789
|
+
if (!this._depsTemp) this._depsTemp = new Set();
|
|
790
|
+
this._depsTemp.add(beanFullName);
|
|
791
|
+
}
|
|
792
|
+
end(beanFullName) {
|
|
793
|
+
if (!this._depsTemp || this._depsTemp.size === 0) return;
|
|
794
|
+
const depsTemp = this._depsTemp;
|
|
795
|
+
this._depsTemp = undefined;
|
|
796
|
+
for (const depTemp of depsTemp) {
|
|
797
|
+
if (!this._deps[depTemp]) this._deps[depTemp] = new Set();
|
|
798
|
+
this._deps[depTemp].add(beanFullName);
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
const appHmrDeps = new AppHmrDeps();
|
|
803
|
+
|
|
804
|
+
const ParseModuleNameLevel = ParseModuleNameLevelInit + 5;
|
|
805
|
+
function parseModuleName(beanClass) {
|
|
806
|
+
// beanInfo
|
|
807
|
+
const beanInfo = appMetadata.getOwnMetadata(SymbolDecoratorBeanInfo, beanClass);
|
|
808
|
+
return beanInfo?.module || parseModuleName$1(ParseModuleNameLevel);
|
|
809
|
+
}
|
|
810
|
+
function parseModuleFile() {
|
|
811
|
+
return parseModuleFile$1(ParseModuleNameLevel);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
function createBeanDecorator(scene, options, optionsPrimitive, fn) {
|
|
815
|
+
return function (target) {
|
|
816
|
+
const beanClass = target;
|
|
817
|
+
// module
|
|
818
|
+
const module = parseModuleName(beanClass);
|
|
819
|
+
const file = process.env.META_MODE !== 'prod' ? parseModuleFile() : undefined;
|
|
820
|
+
// name
|
|
821
|
+
const name = scene === 'scope' ? 'module' : undefined;
|
|
822
|
+
// add
|
|
823
|
+
const beanOptions = appResource.addBean({
|
|
824
|
+
module,
|
|
825
|
+
scene,
|
|
826
|
+
name,
|
|
827
|
+
beanClass,
|
|
828
|
+
options,
|
|
829
|
+
optionsPrimitive,
|
|
830
|
+
file
|
|
831
|
+
});
|
|
832
|
+
// fn
|
|
833
|
+
fn?.(beanClass);
|
|
834
|
+
appHmrDeps.end(beanOptions.beanFullName);
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
function ProxyDisable() {
|
|
839
|
+
return function (target) {
|
|
840
|
+
// set metadata
|
|
841
|
+
appMetadata.defineMetadata(SymbolDecoratorProxyDisable, true, target);
|
|
842
|
+
};
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
function Use(options) {
|
|
846
|
+
return function (target, prop, descriptor) {
|
|
847
|
+
if (!options) options = {};
|
|
848
|
+
if (typeof options === 'string') {
|
|
849
|
+
options = {
|
|
850
|
+
beanFullName: options
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
// beanClass maybe has no specific class type
|
|
854
|
+
const beanClass = appMetadata.getDesignType(target, prop);
|
|
855
|
+
// beanFullName
|
|
856
|
+
let beanFullName = options.beanFullName;
|
|
857
|
+
if (!beanFullName) {
|
|
858
|
+
beanFullName = appResource.getBeanFullName(beanClass);
|
|
859
|
+
if (!beanFullName) {
|
|
860
|
+
throw new Error(`@Use not found valid beanFullName for: ${target.constructor.name}.${String(prop)}`);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
// record
|
|
864
|
+
appResource.addUse(target, {
|
|
865
|
+
...options,
|
|
866
|
+
prop,
|
|
867
|
+
beanFullName,
|
|
868
|
+
descriptor
|
|
869
|
+
});
|
|
870
|
+
};
|
|
871
|
+
}
|
|
872
|
+
function usePrepareArg(arg, withSelector) {
|
|
873
|
+
return {
|
|
874
|
+
withSelector,
|
|
875
|
+
args: [arg]
|
|
876
|
+
};
|
|
877
|
+
}
|
|
878
|
+
function usePrepareArgs(args, withSelector) {
|
|
879
|
+
return {
|
|
880
|
+
withSelector,
|
|
881
|
+
args
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
function __prepareInjectSelectorInfo(beanInstance, useOptions) {
|
|
885
|
+
let selectorInfo = __prepareInjectSelectorInfo_descriptor(beanInstance, useOptions);
|
|
886
|
+
if (!selectorInfo) {
|
|
887
|
+
selectorInfo = __prepareInjectSelectorInfo_init(beanInstance, useOptions);
|
|
888
|
+
}
|
|
889
|
+
if (!selectorInfo && !isNilOrEmptyString(useOptions.selector)) {
|
|
890
|
+
const selector = evaluateExpressions(useOptions.selector, {
|
|
891
|
+
self: beanInstance,
|
|
892
|
+
app: beanInstance.app,
|
|
893
|
+
ctx: beanInstance.ctx
|
|
894
|
+
});
|
|
895
|
+
return {
|
|
896
|
+
withSelector: true,
|
|
897
|
+
args: [selector]
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
return selectorInfo ?? {
|
|
901
|
+
withSelector: false,
|
|
902
|
+
args: []
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
function __prepareInjectSelectorInfo_descriptor(beanInstance, useOptions) {
|
|
906
|
+
const fnGet = useOptions.descriptor?.get;
|
|
907
|
+
if (!fnGet) return;
|
|
908
|
+
const res = fnGet.call(beanInstance);
|
|
909
|
+
if (!res) return;
|
|
910
|
+
const withSelector = res.withSelector ?? false;
|
|
911
|
+
const args = res.args.map(arg => typeof arg === 'function' ? arg() : arg);
|
|
912
|
+
return {
|
|
913
|
+
withSelector,
|
|
914
|
+
args
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
function __prepareInjectSelectorInfo_init(beanInstance, useOptions) {
|
|
918
|
+
const init = useOptions.init;
|
|
919
|
+
if (!init) return;
|
|
920
|
+
const withSelector = init.withSelector ?? false;
|
|
921
|
+
const _args = init.args ?? [init.arg];
|
|
922
|
+
if (!_args) return;
|
|
923
|
+
const args = _args.map(arg => evaluateExpressions(arg, {
|
|
924
|
+
self: beanInstance,
|
|
925
|
+
app: beanInstance.app,
|
|
926
|
+
ctx: beanInstance.ctx
|
|
927
|
+
}));
|
|
928
|
+
return {
|
|
929
|
+
withSelector,
|
|
930
|
+
args
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
function Virtual() {
|
|
935
|
+
return function (target) {
|
|
936
|
+
// set metadata
|
|
937
|
+
appMetadata.defineMetadata(SymbolDecoratorVirtual, true, target);
|
|
938
|
+
};
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
const functionNoop = () => {};
|
|
942
|
+
|
|
943
|
+
const SymbolProxyMagic = Symbol('SymbolProxyMagic');
|
|
944
|
+
const SymbolProxyAopMethod = Symbol('SymbolProxyAopMethod');
|
|
945
|
+
const SymbolCacheAopChains = Symbol('SymbolCacheAopChains');
|
|
946
|
+
const SymbolCacheAopChainsKey = Symbol('SymbolCacheAopChainsKey');
|
|
947
|
+
const SymbolBeanContainerInstances = Symbol('SymbolBeanContainerInstances');
|
|
948
|
+
const SymbolBeanInstancePropsLazy = Symbol('SymbolBeanInstancePropsLazy');
|
|
949
|
+
// const BeanInstanceScope = Symbol('BeanInstance#Scope');
|
|
950
|
+
|
|
951
|
+
class BeanContainer {
|
|
952
|
+
static create(app, ctx) {
|
|
953
|
+
const beanContainer = new BeanContainer(app, ctx);
|
|
954
|
+
return new Proxy(beanContainer, {
|
|
955
|
+
get(obj, prop) {
|
|
956
|
+
if (typeof prop === 'symbol') return obj[prop];
|
|
957
|
+
if (obj[prop]) return obj[prop];
|
|
958
|
+
return obj._getBean(prop);
|
|
959
|
+
}
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
constructor(app, ctx) {
|
|
963
|
+
this.app = void 0;
|
|
964
|
+
this.ctx = void 0;
|
|
965
|
+
this[SymbolBeanContainerInstances] = {};
|
|
966
|
+
this.app = app;
|
|
967
|
+
this.ctx = ctx;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/** @internal */
|
|
971
|
+
async dispose() {
|
|
972
|
+
const beanInstances = this[SymbolBeanContainerInstances];
|
|
973
|
+
for (const prop in beanInstances) {
|
|
974
|
+
const beanInstance = cast(beanInstances[prop]);
|
|
975
|
+
if (beanInstance && !(beanInstance instanceof BeanAopBase) && beanInstance.__dispose__) {
|
|
976
|
+
await beanInstance.__dispose__();
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
this[SymbolBeanContainerInstances] = {};
|
|
980
|
+
}
|
|
981
|
+
async _removeBean(beanInstanceKeyLike) {
|
|
982
|
+
const beanInstanceKey = typeof beanInstanceKeyLike === 'string' ? beanInstanceKeyLike : beanInstanceKeyLike[SymbolBeanInstanceKey];
|
|
983
|
+
if (!beanInstanceKey) return;
|
|
984
|
+
const beanInstance = this[SymbolBeanContainerInstances][beanInstanceKey];
|
|
985
|
+
if (beanInstance) {
|
|
986
|
+
if (!(beanInstance instanceof BeanAopBase) && beanInstance.__dispose__) {
|
|
987
|
+
await beanInstance.__dispose__();
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
// maybe null
|
|
991
|
+
delete this[SymbolBeanContainerInstances][beanInstanceKey];
|
|
992
|
+
}
|
|
993
|
+
get containerType() {
|
|
994
|
+
if (!this.ctx) return 'app';
|
|
995
|
+
return 'ctx';
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
/** get specific module's scope */
|
|
999
|
+
|
|
1000
|
+
// scope<T>(moduleScope: string): T;
|
|
1001
|
+
scope(moduleScope) {
|
|
1002
|
+
return this._getBean(`${moduleScope}.scope.module`);
|
|
1003
|
+
}
|
|
1004
|
+
// _getBean<T>(beanFullName: string, ...args): T;
|
|
1005
|
+
_getBean(beanFullName, ...args) {
|
|
1006
|
+
return this._getBeanSelectorInner(beanFullName, false, ...args);
|
|
1007
|
+
}
|
|
1008
|
+
// _getBeanSelector<T>(beanFullName: string, selector?: string, ...args): T;
|
|
1009
|
+
_getBeanSelector(beanFullName, selector, ...args) {
|
|
1010
|
+
return this._getBeanSelectorInner(beanFullName, true, selector, ...args);
|
|
1011
|
+
}
|
|
1012
|
+
_getBeanSelectorInner(beanFullName, withSelector, ...args) {
|
|
1013
|
+
// bean options
|
|
1014
|
+
const beanOptions = appResource.getBean(beanFullName);
|
|
1015
|
+
if (!beanOptions) {
|
|
1016
|
+
// not found
|
|
1017
|
+
return null;
|
|
1018
|
+
}
|
|
1019
|
+
const fullName = beanOptions.beanFullName;
|
|
1020
|
+
const key = __getSelectorKey(fullName, withSelector, args[0]);
|
|
1021
|
+
if (this[SymbolBeanContainerInstances][key] === undefined) {
|
|
1022
|
+
this._newBeanInner(true, fullName, withSelector, ...args);
|
|
1023
|
+
}
|
|
1024
|
+
return this[SymbolBeanContainerInstances][key];
|
|
1025
|
+
}
|
|
1026
|
+
// _newBean<T>(beanFullName: string, ...args): T;
|
|
1027
|
+
_newBean(beanFullName, ...args) {
|
|
1028
|
+
return this._newBeanInner(false, beanFullName, false, ...args);
|
|
1029
|
+
}
|
|
1030
|
+
// _newBeanSelector<T>(beanFullName: string, selector?: string, ...args): T;
|
|
1031
|
+
_newBeanSelector(beanFullName, selector, ...args) {
|
|
1032
|
+
return this._newBean(beanFullName, selector, ...args);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
/** @internal */
|
|
1036
|
+
_newBeanInner(record, beanFullName, withSelector, ...args) {
|
|
1037
|
+
// bean options
|
|
1038
|
+
const beanOptions = appResource.getBean(beanFullName);
|
|
1039
|
+
if (!beanOptions) {
|
|
1040
|
+
// class
|
|
1041
|
+
if (typeof beanFullName === 'function' && isClass(beanFullName)) {
|
|
1042
|
+
return this._createBeanInstance(record, undefined, beanFullName, args, false, withSelector);
|
|
1043
|
+
}
|
|
1044
|
+
// throw new Error(`bean not found: ${beanFullName}`);
|
|
1045
|
+
return null;
|
|
1046
|
+
}
|
|
1047
|
+
// instance
|
|
1048
|
+
return this._createBeanInstance(record, beanOptions.beanFullName, beanOptions.beanClass, args, cast(beanOptions.scene) === 'aop', withSelector);
|
|
1049
|
+
}
|
|
1050
|
+
_createBeanInstance(record, beanFullName, beanClass, args, aop, withSelector) {
|
|
1051
|
+
// prepare
|
|
1052
|
+
const beanInstance = this._prepareBeanInstance(beanFullName, beanClass, args, aop);
|
|
1053
|
+
// record
|
|
1054
|
+
if (record) {
|
|
1055
|
+
// fullName
|
|
1056
|
+
const fullName = appResource.getBeanFullName(beanFullName);
|
|
1057
|
+
if (fullName) {
|
|
1058
|
+
const key = __getSelectorKey(fullName, withSelector, args[0]);
|
|
1059
|
+
__setPropertyValue(beanInstance, SymbolBeanInstanceKey, key);
|
|
1060
|
+
this[SymbolBeanContainerInstances][key] = beanInstance;
|
|
1061
|
+
this.containerType === 'app' && this.app.meta.hmr?.addBeanInstance(fullName, key, args, withSelector);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
// init
|
|
1065
|
+
this._initBeanInstance(beanFullName, beanInstance, args);
|
|
1066
|
+
// ok
|
|
1067
|
+
return beanInstance;
|
|
1068
|
+
}
|
|
1069
|
+
_prepareBeanInstance(beanFullName, BeanClass, args, aop) {
|
|
1070
|
+
// create
|
|
1071
|
+
let beanInstance;
|
|
1072
|
+
if (BeanClass.prototype.__init__) {
|
|
1073
|
+
beanInstance = new BeanClass();
|
|
1074
|
+
} else {
|
|
1075
|
+
beanInstance = new BeanClass(...args);
|
|
1076
|
+
}
|
|
1077
|
+
// app/ctx
|
|
1078
|
+
if (beanInstance instanceof BeanSimple) {
|
|
1079
|
+
beanInstance.app = this.app;
|
|
1080
|
+
if (this.ctx) {
|
|
1081
|
+
__setPropertyValue(beanInstance, 'ctx', this.ctx);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
// beanFullName
|
|
1085
|
+
if (typeof beanFullName === 'string') {
|
|
1086
|
+
__setPropertyValue(beanInstance, SymbolBeanFullName, beanFullName);
|
|
1087
|
+
}
|
|
1088
|
+
// aop: proxy
|
|
1089
|
+
return this._patchBeanInstance(beanFullName || BeanClass, beanInstance, aop);
|
|
1090
|
+
}
|
|
1091
|
+
_initBeanInstance(beanFullName, beanInstance, args) {
|
|
1092
|
+
// inject
|
|
1093
|
+
this._injectBeanInstance(beanInstance, beanFullName);
|
|
1094
|
+
// init
|
|
1095
|
+
if (!(beanInstance instanceof BeanAopBase) && beanInstance.__init__) {
|
|
1096
|
+
beanInstance.__init__(...args);
|
|
1097
|
+
}
|
|
1098
|
+
// ok
|
|
1099
|
+
return beanInstance;
|
|
1100
|
+
}
|
|
1101
|
+
_injectBeanInstance(beanInstance, beanFullName) {
|
|
1102
|
+
const beanOptions = appResource.getBean(beanFullName);
|
|
1103
|
+
if (!beanOptions) return;
|
|
1104
|
+
const uses = appResource.getUses(beanOptions.beanClass.prototype);
|
|
1105
|
+
if (!uses) return;
|
|
1106
|
+
for (const key in uses) {
|
|
1107
|
+
const useOptions = uses[key];
|
|
1108
|
+
this._injectBeanInstancePropLazy(beanInstance, useOptions.prop, useOptions.beanFullName, useOptions);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
_injectBeanInstancePropLazy(beanInstance, prop, targetBeanFullName, useOptions) {
|
|
1112
|
+
const self = this;
|
|
1113
|
+
Object.defineProperty(beanInstance, prop, {
|
|
1114
|
+
enumerable: true,
|
|
1115
|
+
configurable: true,
|
|
1116
|
+
get() {
|
|
1117
|
+
if (!beanInstance[SymbolBeanInstancePropsLazy]) beanInstance[SymbolBeanInstancePropsLazy] = {};
|
|
1118
|
+
if (!beanInstance[SymbolBeanInstancePropsLazy][prop]) {
|
|
1119
|
+
beanInstance[SymbolBeanInstancePropsLazy][prop] = self._injectBeanInstanceProp(beanInstance, targetBeanFullName, useOptions);
|
|
1120
|
+
self.containerType === 'app' && self.app.meta.hmr?.addBeanInstanceProp(beanInstance, prop, targetBeanFullName);
|
|
1121
|
+
}
|
|
1122
|
+
return beanInstance[SymbolBeanInstancePropsLazy][prop];
|
|
1123
|
+
}
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
_injectBeanInstanceProp(beanInstance, targetBeanFullName, useOptions) {
|
|
1127
|
+
// injectionScope
|
|
1128
|
+
const injectionScope = useOptions.injectionScope ?? 'app';
|
|
1129
|
+
// options: selectorInfo
|
|
1130
|
+
const selectorInfo = __prepareInjectSelectorInfo(beanInstance, useOptions);
|
|
1131
|
+
// targetInstance
|
|
1132
|
+
let targetInstance;
|
|
1133
|
+
// selector maybe empty string
|
|
1134
|
+
if (injectionScope === 'app') {
|
|
1135
|
+
targetInstance = this.app.bean._getBeanSelectorInner(targetBeanFullName, selectorInfo.withSelector, ...selectorInfo.args);
|
|
1136
|
+
} else if (injectionScope === 'ctx') {
|
|
1137
|
+
targetInstance = this._getBeanSelectorInner(targetBeanFullName, selectorInfo.withSelector, ...selectorInfo.args);
|
|
1138
|
+
} else if (injectionScope === 'new') {
|
|
1139
|
+
targetInstance = this._newBeanInner(false, targetBeanFullName, selectorInfo.withSelector, ...selectorInfo.args);
|
|
1140
|
+
}
|
|
1141
|
+
return targetInstance;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
// private _injectBeanInstanceScope(beanInstance, beanFullName) {
|
|
1145
|
+
// if (typeof beanFullName !== 'string' || beanFullName.indexOf('.scope.module') > -1) return;
|
|
1146
|
+
// Object.defineProperty(beanInstance, 'scope', {
|
|
1147
|
+
// enumerable: false,
|
|
1148
|
+
// configurable: true,
|
|
1149
|
+
// get() {
|
|
1150
|
+
// if (!this[BeanInstanceScope]) {
|
|
1151
|
+
// this[BeanInstanceScope] = this.bean._getBean(`${this[SymbolModuleBelong]}.scope.module`);
|
|
1152
|
+
// }
|
|
1153
|
+
// return this[BeanInstanceScope];
|
|
1154
|
+
// },
|
|
1155
|
+
// });
|
|
1156
|
+
// }
|
|
1157
|
+
|
|
1158
|
+
_patchBeanInstance(beanFullNameOrBeanClass, beanInstance, aop) {
|
|
1159
|
+
if (!beanFullNameOrBeanClass) return beanInstance;
|
|
1160
|
+
// not aop on aop
|
|
1161
|
+
if (aop) return beanInstance;
|
|
1162
|
+
// aop chains
|
|
1163
|
+
const _aopChains = this._prepareAopChains(beanFullNameOrBeanClass, beanInstance);
|
|
1164
|
+
// no aop
|
|
1165
|
+
if (_aopChains.length === 0) return beanInstance;
|
|
1166
|
+
// aop
|
|
1167
|
+
return this._newBeanProxy(beanFullNameOrBeanClass, beanInstance);
|
|
1168
|
+
}
|
|
1169
|
+
_newBeanProxy(beanFullName, beanInstance) {
|
|
1170
|
+
const self = this;
|
|
1171
|
+
return new Proxy(beanInstance, {
|
|
1172
|
+
get(target, prop, receiver) {
|
|
1173
|
+
if (typeof prop === 'symbol') {
|
|
1174
|
+
return Reflect.get(target, prop, receiver);
|
|
1175
|
+
}
|
|
1176
|
+
if (__isInnerMethod(prop)) {
|
|
1177
|
+
return Reflect.get(target, prop, receiver);
|
|
1178
|
+
}
|
|
1179
|
+
// descriptorInfo
|
|
1180
|
+
const descriptorInfo = __getPropertyDescriptor(target, prop);
|
|
1181
|
+
if (!__checkAopOfDescriptorInfo(descriptorInfo)) return Reflect.get(target, prop, receiver);
|
|
1182
|
+
const methodType = __methodTypeOfDescriptor(descriptorInfo);
|
|
1183
|
+
// get prop
|
|
1184
|
+
if (!methodType) {
|
|
1185
|
+
if (__isLifeCycleMethod(prop)) return Reflect.get(target, prop, receiver);
|
|
1186
|
+
const methodName = `__get_${prop}__`;
|
|
1187
|
+
const methodNameMagic = '__get__';
|
|
1188
|
+
const _aopChainsProp = self._getAopChainsProp(beanFullName, beanInstance, methodName, methodNameMagic, 'get', prop);
|
|
1189
|
+
if (!_aopChainsProp) return Reflect.get(target, prop, receiver);
|
|
1190
|
+
// aop
|
|
1191
|
+
return _aopChainsProp([receiver, undefined], ([receiver, _]) => {
|
|
1192
|
+
if (!descriptorInfo && target.__get__) {
|
|
1193
|
+
return Reflect.apply(target.__get__, receiver, [prop, target]);
|
|
1194
|
+
} else {
|
|
1195
|
+
return Reflect.get(target, prop, receiver);
|
|
1196
|
+
}
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
// method
|
|
1200
|
+
return self._getInstanceMethodProxy(beanFullName, beanInstance, target, prop, receiver);
|
|
1201
|
+
},
|
|
1202
|
+
set(target, prop, value, receiver) {
|
|
1203
|
+
if (typeof prop === 'symbol') {
|
|
1204
|
+
Reflect.set(target, prop, value, receiver);
|
|
1205
|
+
return true;
|
|
1206
|
+
}
|
|
1207
|
+
if (__isInnerMethod(prop)) {
|
|
1208
|
+
Reflect.set(target, prop, value, receiver);
|
|
1209
|
+
return true;
|
|
1210
|
+
}
|
|
1211
|
+
// descriptorInfo
|
|
1212
|
+
const descriptorInfo = __getPropertyDescriptor(target, prop);
|
|
1213
|
+
if (!__checkAopOfDescriptorInfo(descriptorInfo)) {
|
|
1214
|
+
Reflect.set(target, prop, value, receiver);
|
|
1215
|
+
return true;
|
|
1216
|
+
}
|
|
1217
|
+
const methodName = `__set_${prop}__`;
|
|
1218
|
+
const methodNameMagic = '__set__';
|
|
1219
|
+
const _aopChainsProp = self._getAopChainsProp(beanFullName, beanInstance, methodName, methodNameMagic, 'set', prop);
|
|
1220
|
+
if (!_aopChainsProp) {
|
|
1221
|
+
Reflect.set(target, prop, value, receiver);
|
|
1222
|
+
return true;
|
|
1223
|
+
}
|
|
1224
|
+
// aop
|
|
1225
|
+
return _aopChainsProp([receiver, value], ([receiver, value]) => {
|
|
1226
|
+
if (!descriptorInfo && target.__set__) {
|
|
1227
|
+
const res = Reflect.apply(target.__set__, receiver, [prop, value, target]);
|
|
1228
|
+
if (res === undefined) throw new Error('__set__ must return true/false');
|
|
1229
|
+
if (!res) {
|
|
1230
|
+
Reflect.set(target, prop, value, receiver);
|
|
1231
|
+
}
|
|
1232
|
+
} else {
|
|
1233
|
+
Reflect.set(target, prop, value, receiver);
|
|
1234
|
+
}
|
|
1235
|
+
// ok: prop be set
|
|
1236
|
+
return true;
|
|
1237
|
+
});
|
|
1238
|
+
}
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
_getInstanceMethodProxy(beanFullName, beanInstance, target, prop, receiver) {
|
|
1242
|
+
// not aop magic methods
|
|
1243
|
+
if (__isInnerMethod(prop)) {
|
|
1244
|
+
return Reflect.get(target, prop, receiver);
|
|
1245
|
+
}
|
|
1246
|
+
// aop chains
|
|
1247
|
+
const methodNameMagic = '__method__';
|
|
1248
|
+
const _aopChainsProp = this._getAopChainsProp(beanFullName, beanInstance, prop, methodNameMagic, 'method', prop);
|
|
1249
|
+
if (!_aopChainsProp) return Reflect.get(target, prop, receiver);
|
|
1250
|
+
// proxy
|
|
1251
|
+
const methodProxyKey = `__aopproxy_method_${prop}__`;
|
|
1252
|
+
if (target[methodProxyKey]) return target[methodProxyKey];
|
|
1253
|
+
const methodProxy = new Proxy(target[prop], {
|
|
1254
|
+
apply(target, thisArg, args) {
|
|
1255
|
+
// aop
|
|
1256
|
+
return _aopChainsProp([thisArg, args], ([thisArg, args]) => {
|
|
1257
|
+
return Reflect.apply(target, thisArg, args);
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1260
|
+
});
|
|
1261
|
+
__setPropertyValue(target, methodProxyKey, methodProxy);
|
|
1262
|
+
return methodProxy;
|
|
1263
|
+
}
|
|
1264
|
+
_prepareAopChains(beanFullNameOrBeanClass, beanInstance) {
|
|
1265
|
+
if (!beanFullNameOrBeanClass) return [];
|
|
1266
|
+
// beanFullName maybe class
|
|
1267
|
+
const beanOptions = appResource.getBean(beanFullNameOrBeanClass);
|
|
1268
|
+
const cacheKey = beanOptions?.beanFullName || beanFullNameOrBeanClass;
|
|
1269
|
+
// ProxyDisable
|
|
1270
|
+
const proxyDisable = beanOptions?.beanClass ? appMetadata.getMetadata(SymbolDecoratorProxyDisable, beanOptions?.beanClass) : false;
|
|
1271
|
+
// host
|
|
1272
|
+
const host = this._aopCacheHost();
|
|
1273
|
+
if (!host[SymbolCacheAopChains]) host[SymbolCacheAopChains] = {};
|
|
1274
|
+
if (host[SymbolCacheAopChains][cacheKey]) return host[SymbolCacheAopChains][cacheKey];
|
|
1275
|
+
// chains
|
|
1276
|
+
let chains = [];
|
|
1277
|
+
// aop
|
|
1278
|
+
if (!proxyDisable && beanOptions && cast(beanOptions.scene) !== 'aop') {
|
|
1279
|
+
const beanAop = this.app.bean._getBean('a-aspectutils.service.aop');
|
|
1280
|
+
const aops = beanAop.findAopsMatched(beanOptions.beanFullName);
|
|
1281
|
+
if (aops) {
|
|
1282
|
+
chains = chains.concat(aops);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
// aop method
|
|
1286
|
+
if (!proxyDisable && beanOptions) {
|
|
1287
|
+
const beanAop = this.app.bean._getBean('a-aspectutils.service.aop');
|
|
1288
|
+
if (beanAop.hasAopMethods(beanOptions?.beanFullName)) {
|
|
1289
|
+
chains.push(SymbolProxyAopMethod);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
// magic self
|
|
1293
|
+
if (__hasMagicMethod(beanInstance)) {
|
|
1294
|
+
chains.push(SymbolProxyMagic);
|
|
1295
|
+
}
|
|
1296
|
+
// hold
|
|
1297
|
+
host[SymbolCacheAopChains][cacheKey] = chains;
|
|
1298
|
+
return chains;
|
|
1299
|
+
}
|
|
1300
|
+
_aopCacheHost() {
|
|
1301
|
+
if (!this.app) throw new Error('Perhaps missing await');
|
|
1302
|
+
return this.app;
|
|
1303
|
+
}
|
|
1304
|
+
_getAopChainsProp(beanFullName, beanInstance, methodName, methodNameMagic, methodType, prop) {
|
|
1305
|
+
const self = this;
|
|
1306
|
+
const chainsKey = `__aopChains_${methodName}__`;
|
|
1307
|
+
const beanOptions = appResource.getBean(beanFullName);
|
|
1308
|
+
const cacheKey = beanOptions?.beanFullName || beanFullName;
|
|
1309
|
+
const host = this._aopCacheHost();
|
|
1310
|
+
if (!host[SymbolCacheAopChainsKey]) host[SymbolCacheAopChainsKey] = {};
|
|
1311
|
+
if (!host[SymbolCacheAopChainsKey][cacheKey]) host[SymbolCacheAopChainsKey][cacheKey] = {};
|
|
1312
|
+
if (host[SymbolCacheAopChainsKey][cacheKey][chainsKey] !== undefined) return host[SymbolCacheAopChainsKey][cacheKey][chainsKey];
|
|
1313
|
+
const _aopChains = this._prepareAopChains(beanFullName, beanInstance);
|
|
1314
|
+
const chains = [];
|
|
1315
|
+
for (const aopKey of _aopChains) {
|
|
1316
|
+
if (aopKey === SymbolProxyMagic) {
|
|
1317
|
+
if (!__isLifeCycleMethod(methodName)) {
|
|
1318
|
+
chains.push([aopKey, methodName]);
|
|
1319
|
+
}
|
|
1320
|
+
} else if (aopKey === SymbolProxyAopMethod) {
|
|
1321
|
+
this._getAopChainsProp_aopMethods(chains, aopKey, beanFullName, methodType, prop);
|
|
1322
|
+
} else {
|
|
1323
|
+
// singleton
|
|
1324
|
+
const aopOuter = self.app.bean._getBean(aopKey);
|
|
1325
|
+
if (aopOuter[methodName]) {
|
|
1326
|
+
let fn;
|
|
1327
|
+
if (methodType === 'get') {
|
|
1328
|
+
fn = function ([receiver, _], next) {
|
|
1329
|
+
const aop = self.app.bean._getBean(aopKey);
|
|
1330
|
+
return aop[methodName](_patchAopNext([receiver, _], next), receiver);
|
|
1331
|
+
};
|
|
1332
|
+
} else if (methodType === 'set') {
|
|
1333
|
+
fn = function ([receiver, value], next) {
|
|
1334
|
+
const aop = self.app.bean._getBean(aopKey);
|
|
1335
|
+
return aop[methodName](value, _patchAopNext([receiver, value], next), receiver);
|
|
1336
|
+
};
|
|
1337
|
+
} else if (methodType === 'method') {
|
|
1338
|
+
fn = function ([receiver, args], next) {
|
|
1339
|
+
const aop = self.app.bean._getBean(aopKey);
|
|
1340
|
+
return aop[methodName](args, _patchAopNext([receiver, args], next), receiver);
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
chains.push([aopKey, fn]);
|
|
1344
|
+
}
|
|
1345
|
+
if (methodNameMagic && aopOuter[methodNameMagic]) {
|
|
1346
|
+
if (!__isLifeCycleMethod(methodName)) {
|
|
1347
|
+
let fn;
|
|
1348
|
+
if (methodType === 'get') {
|
|
1349
|
+
fn = function ([receiver, _], next) {
|
|
1350
|
+
const aop = self.app.bean._getBean(aopKey);
|
|
1351
|
+
return aop[methodNameMagic](prop, _patchAopNext([receiver, _], next), receiver);
|
|
1352
|
+
};
|
|
1353
|
+
} else if (methodType === 'set') {
|
|
1354
|
+
fn = function ([receiver, value], next) {
|
|
1355
|
+
const aop = self.app.bean._getBean(aopKey);
|
|
1356
|
+
return aop[methodNameMagic](prop, value, _patchAopNext([receiver, value], next), receiver);
|
|
1357
|
+
};
|
|
1358
|
+
} else if (methodType === 'method') {
|
|
1359
|
+
fn = function ([receiver, args], next) {
|
|
1360
|
+
const aop = self.app.bean._getBean(aopKey);
|
|
1361
|
+
return aop[methodNameMagic](prop, args, _patchAopNext([receiver, args], next), receiver);
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
chains.push([aopKey, fn]);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
let result;
|
|
1370
|
+
if (chains.length === 0) {
|
|
1371
|
+
result = null;
|
|
1372
|
+
} else {
|
|
1373
|
+
result = __composeForProp(chains);
|
|
1374
|
+
}
|
|
1375
|
+
host[SymbolCacheAopChainsKey][cacheKey][chainsKey] = result;
|
|
1376
|
+
return result;
|
|
1377
|
+
}
|
|
1378
|
+
_getAopChainsProp_aopMethods(chains, aopKey, beanFullName, methodType, prop) {
|
|
1379
|
+
const self = this;
|
|
1380
|
+
const beanAop = this.app.bean._getBean('a-aspectutils.service.aop');
|
|
1381
|
+
const aopMethods = beanAop.findAopMethodsMatched(beanFullName, prop);
|
|
1382
|
+
for (const aopMethod of aopMethods) {
|
|
1383
|
+
let fn;
|
|
1384
|
+
if (methodType === 'get') {
|
|
1385
|
+
fn = function ([receiver, _], next) {
|
|
1386
|
+
const beanInstance = self.app.bean._getBean(aopMethod.beanFullName);
|
|
1387
|
+
if (!beanInstance.get) throw new Error(`get property accessor not exists: ${aopMethod.onionName}`);
|
|
1388
|
+
return beanInstance.get(aopMethod.options, _patchAopNext([receiver, _], next), receiver, prop);
|
|
1389
|
+
};
|
|
1390
|
+
} else if (methodType === 'set') {
|
|
1391
|
+
fn = function ([receiver, value], next) {
|
|
1392
|
+
const beanInstance = self.app.bean._getBean(aopMethod.beanFullName);
|
|
1393
|
+
if (!beanInstance.set) throw new Error(`set property accessor not exists: ${aopMethod.onionName}`);
|
|
1394
|
+
return beanInstance.set(aopMethod.options, value, _patchAopNext([receiver, value], next), receiver, prop);
|
|
1395
|
+
};
|
|
1396
|
+
} else if (methodType === 'method') {
|
|
1397
|
+
fn = function ([receiver, args], next) {
|
|
1398
|
+
const beanInstance = self.app.bean._getBean(aopMethod.beanFullName);
|
|
1399
|
+
if (!beanInstance.execute) throw new Error(`execute method not exists: ${aopMethod.onionName}`);
|
|
1400
|
+
return beanInstance.execute(aopMethod.options, args, _patchAopNext([receiver, args], next), receiver, prop);
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1403
|
+
chains.push([aopKey, fn]);
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
function __composeForPropAdapter(_context, chain) {
|
|
1408
|
+
const [aopKey, fn] = chain;
|
|
1409
|
+
// SymbolProxyMagic
|
|
1410
|
+
if (aopKey === SymbolProxyMagic) return;
|
|
1411
|
+
// chain
|
|
1412
|
+
return {
|
|
1413
|
+
receiver: undefined,
|
|
1414
|
+
fn
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
function __composeForProp(chains) {
|
|
1418
|
+
return compose(chains, __composeForPropAdapter);
|
|
1419
|
+
}
|
|
1420
|
+
function _patchAopNext([receiver, context], next) {
|
|
1421
|
+
return (...args) => {
|
|
1422
|
+
context = args.length === 0 ? context : args[0];
|
|
1423
|
+
return next([receiver, context]);
|
|
1424
|
+
};
|
|
1425
|
+
}
|
|
1426
|
+
function __checkAopOfDescriptorInfo(descriptorInfo) {
|
|
1427
|
+
if (!descriptorInfo) return true;
|
|
1428
|
+
return !descriptorInfo.dynamic && !descriptorInfo.ofBeanBase;
|
|
1429
|
+
}
|
|
1430
|
+
function __getPropertyDescriptor(obj, prop) {
|
|
1431
|
+
// dynamic
|
|
1432
|
+
const descriptor = Object.getOwnPropertyDescriptor(obj, prop);
|
|
1433
|
+
if (descriptor) return {
|
|
1434
|
+
descriptor,
|
|
1435
|
+
dynamic: true
|
|
1436
|
+
};
|
|
1437
|
+
// static
|
|
1438
|
+
return __getPropertyDescriptorStatic(obj, prop);
|
|
1439
|
+
}
|
|
1440
|
+
function __getPropertyDescriptorStatic(obj, prop) {
|
|
1441
|
+
let proto = Object.getPrototypeOf(obj);
|
|
1442
|
+
let ofBeanBase = false;
|
|
1443
|
+
while (proto) {
|
|
1444
|
+
if (proto.constructor.name === BeanBase.name) {
|
|
1445
|
+
ofBeanBase = true;
|
|
1446
|
+
}
|
|
1447
|
+
const descriptor = Object.getOwnPropertyDescriptor(proto, prop);
|
|
1448
|
+
if (descriptor) return {
|
|
1449
|
+
descriptor,
|
|
1450
|
+
dynamic: false,
|
|
1451
|
+
ofBeanBase
|
|
1452
|
+
};
|
|
1453
|
+
proto = Object.getPrototypeOf(proto);
|
|
1454
|
+
}
|
|
1455
|
+
return null;
|
|
1456
|
+
}
|
|
1457
|
+
function __setPropertyValue(obj, prop, value) {
|
|
1458
|
+
Object.defineProperty(obj, prop, {
|
|
1459
|
+
enumerable: false,
|
|
1460
|
+
configurable: true,
|
|
1461
|
+
get() {
|
|
1462
|
+
return value;
|
|
1463
|
+
}
|
|
1464
|
+
});
|
|
1465
|
+
}
|
|
1466
|
+
function __hasMagicMethod(instance) {
|
|
1467
|
+
return !!instance.__get__ || !!instance.__set__;
|
|
1468
|
+
}
|
|
1469
|
+
function __isInnerMethod(prop) {
|
|
1470
|
+
return ['__get__', '__set__',
|
|
1471
|
+
// '__init__',
|
|
1472
|
+
// '__dispose__',
|
|
1473
|
+
'then', '__v_isShallow', '__v_isReadonly', '__v_raw'].includes(prop);
|
|
1474
|
+
}
|
|
1475
|
+
function __isLifeCycleMethod(prop) {
|
|
1476
|
+
return ['__init__', '__dispose__'].includes(prop);
|
|
1477
|
+
}
|
|
1478
|
+
function __methodTypeOfDescriptor(descriptorInfo) {
|
|
1479
|
+
if (!descriptorInfo) return null;
|
|
1480
|
+
const {
|
|
1481
|
+
descriptor,
|
|
1482
|
+
dynamic
|
|
1483
|
+
} = descriptorInfo;
|
|
1484
|
+
if (dynamic) return null;
|
|
1485
|
+
if (descriptor.get) return null;
|
|
1486
|
+
const methodType = descriptor.value?.constructor?.name;
|
|
1487
|
+
if (['Function', 'AsyncFunction'].includes(methodType)) {
|
|
1488
|
+
return methodType;
|
|
1489
|
+
}
|
|
1490
|
+
return null;
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
// same as _getBean if selector is undefined/null/'', as as to get the same bean instance
|
|
1494
|
+
// not use !selector which maybe is 0
|
|
1495
|
+
function __getSelectorKey(beanFullName, withSelector, selector) {
|
|
1496
|
+
if (!withSelector) return beanFullName;
|
|
1497
|
+
const isSelectorValid = !isNilOrEmptyString(selector);
|
|
1498
|
+
return !isSelectorValid ? beanFullName : `${beanFullName}#${selector}`;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
const BeanModuleScope$4 = Symbol('BeanScopeError#ModuleScope');
|
|
1502
|
+
const BeanErrorCode = Symbol('BeanScopeError#BeanErrorCode');
|
|
1503
|
+
class BeanScopeErrorImpl extends BeanSimple {
|
|
1504
|
+
constructor(moduleScope, errorCode) {
|
|
1505
|
+
super();
|
|
1506
|
+
this[BeanModuleScope$4] = void 0;
|
|
1507
|
+
this[BeanErrorCode] = void 0;
|
|
1508
|
+
this[BeanModuleScope$4] = moduleScope;
|
|
1509
|
+
this[BeanErrorCode] = errorCode;
|
|
1510
|
+
}
|
|
1511
|
+
throw(...args) {
|
|
1512
|
+
return this.app.meta.error.throw(this[BeanModuleScope$4], this[BeanErrorCode], ...args);
|
|
1513
|
+
}
|
|
1514
|
+
parseFail(...args) {
|
|
1515
|
+
return this.app.meta.error.parseFail(this[BeanModuleScope$4], this[BeanErrorCode], ...args);
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
const BeanModuleScope$3 = Symbol('BeanScopeError#ModuleScope');
|
|
1520
|
+
class BeanScopeError extends BeanSimple {
|
|
1521
|
+
constructor(moduleScope) {
|
|
1522
|
+
super();
|
|
1523
|
+
this[BeanModuleScope$3] = void 0;
|
|
1524
|
+
this.__instances = {};
|
|
1525
|
+
this[BeanModuleScope$3] = moduleScope;
|
|
1526
|
+
}
|
|
1527
|
+
__get__(prop) {
|
|
1528
|
+
if (!this.__instances[prop]) {
|
|
1529
|
+
this.__instances[prop] = this.bean._newBean(BeanScopeErrorImpl, this[BeanModuleScope$3], prop);
|
|
1530
|
+
}
|
|
1531
|
+
return this.__instances[prop];
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
class ErrorClass extends BeanSimple {
|
|
1536
|
+
constructor(ebErrors) {
|
|
1537
|
+
super();
|
|
1538
|
+
this.ebErrors = void 0;
|
|
1539
|
+
this.ebErrors = ebErrors;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
// data,code/message,args
|
|
1543
|
+
success(module, data, code, ...args) {
|
|
1544
|
+
const body = this.parseSuccess(module, code, ...args);
|
|
1545
|
+
this.ctx.response.status = 200;
|
|
1546
|
+
this.ctx.response.type = 'application/json';
|
|
1547
|
+
this.ctx.response.body = {
|
|
1548
|
+
code: 0,
|
|
1549
|
+
message: body.message,
|
|
1550
|
+
data
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
// code/message,args
|
|
1555
|
+
fail(module, code, ...args) {
|
|
1556
|
+
const body = this.parseFail(module, code, ...args);
|
|
1557
|
+
this.ctx.response.status = __calcStatus(body.code);
|
|
1558
|
+
this.ctx.response.type = 'application/json';
|
|
1559
|
+
this.ctx.response.body = {
|
|
1560
|
+
code: body.code,
|
|
1561
|
+
message: body.message
|
|
1562
|
+
}; // body maybe Error
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
// code/message,args
|
|
1566
|
+
throw(module, code, ...args) {
|
|
1567
|
+
const body = this.parseFail(module, code, ...args);
|
|
1568
|
+
const err = new Error();
|
|
1569
|
+
err.code = body.code;
|
|
1570
|
+
err.message = body.message;
|
|
1571
|
+
err.status = __calcStatus(body.code);
|
|
1572
|
+
throw err;
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
// code/message,args
|
|
1576
|
+
parseFail(module, code, ...args) {
|
|
1577
|
+
if (typeof code === 'object') return code;
|
|
1578
|
+
return this.parseCode(module, 500, code, ...args);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
// code/message,args
|
|
1582
|
+
parseSuccess(module, code, ...args) {
|
|
1583
|
+
return this.parseCode(module, 0, code, ...args);
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
// parseCode
|
|
1587
|
+
parseCode(module, codeDefault, code, ...args) {
|
|
1588
|
+
const ebError = this.ebErrors[module];
|
|
1589
|
+
|
|
1590
|
+
// '403'->403
|
|
1591
|
+
if (typeof code === 'string' && /^\d+$/.test(code)) {
|
|
1592
|
+
code = Number(code);
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
// convert from enum
|
|
1596
|
+
let text;
|
|
1597
|
+
if (ebError && code && typeof code === 'string') {
|
|
1598
|
+
text = code;
|
|
1599
|
+
code = ebError[code];
|
|
1600
|
+
}
|
|
1601
|
+
if (code === undefined || code === null || code === '') {
|
|
1602
|
+
code = codeDefault;
|
|
1603
|
+
}
|
|
1604
|
+
let message;
|
|
1605
|
+
if (typeof code === 'number' && code <= 1000) {
|
|
1606
|
+
message = this.app.meta.locale.getText(true, undefined, undefined, String(code), ...args);
|
|
1607
|
+
} else {
|
|
1608
|
+
message = this.app.meta.locale.getText(false, module, undefined, text || code, ...args);
|
|
1609
|
+
}
|
|
1610
|
+
code = __combineErrorCode(module, code);
|
|
1611
|
+
return {
|
|
1612
|
+
code,
|
|
1613
|
+
message
|
|
1614
|
+
};
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
function __combineErrorCode(module, code) {
|
|
1618
|
+
if (typeof code !== 'number' || code <= 1000) return code;
|
|
1619
|
+
return module ? `${module}:${code}` : code;
|
|
1620
|
+
}
|
|
1621
|
+
function __calcStatus(code) {
|
|
1622
|
+
return typeof code !== 'string' && code < 1000 ? code : 500;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
/* eslint-disable */
|
|
1626
|
+
const errorsInternal = {
|
|
1627
|
+
'0': 'Success',
|
|
1628
|
+
'1': 'Unknown Error',
|
|
1629
|
+
'100': 'Continue',
|
|
1630
|
+
'101': 'Switching Protocols',
|
|
1631
|
+
'102': 'Processing',
|
|
1632
|
+
'103': 'Early hints',
|
|
1633
|
+
'200': 'OK',
|
|
1634
|
+
'201': 'Created',
|
|
1635
|
+
'202': 'Accepted',
|
|
1636
|
+
'203': 'Non-Authoritative Information',
|
|
1637
|
+
'204': 'No Content',
|
|
1638
|
+
'205': 'Reset Content',
|
|
1639
|
+
'206': 'Partial Content',
|
|
1640
|
+
'207': 'Multi-Status',
|
|
1641
|
+
'208': 'Already Reported',
|
|
1642
|
+
'226': 'IM Used',
|
|
1643
|
+
'300': 'Multiple Choices',
|
|
1644
|
+
'301': 'Moved Permanently',
|
|
1645
|
+
'302': 'Found',
|
|
1646
|
+
'303': 'See Other',
|
|
1647
|
+
'304': 'Not Modified',
|
|
1648
|
+
'305': 'Use Proxy',
|
|
1649
|
+
'307': 'Temporary Redirect',
|
|
1650
|
+
'308': 'Permanent Redirect',
|
|
1651
|
+
'400': 'Bad Request',
|
|
1652
|
+
'401': 'Unauthorized',
|
|
1653
|
+
'402': 'Payment Required',
|
|
1654
|
+
'403': 'Forbidden',
|
|
1655
|
+
'404': 'Not Found',
|
|
1656
|
+
'405': 'Method Not Allowed',
|
|
1657
|
+
'406': 'Not Acceptable',
|
|
1658
|
+
'407': 'Proxy Authentication Required',
|
|
1659
|
+
'408': 'Request Timeout',
|
|
1660
|
+
'409': 'Conflict',
|
|
1661
|
+
'410': 'Gone',
|
|
1662
|
+
'411': 'Length Required',
|
|
1663
|
+
'412': 'Precondition Failed',
|
|
1664
|
+
'413': 'Payload Too Large',
|
|
1665
|
+
'414': 'URI Too Long',
|
|
1666
|
+
'415': 'Unsupported Media Type',
|
|
1667
|
+
'416': 'Range Not Satisfiable',
|
|
1668
|
+
'417': 'Expectation Failed',
|
|
1669
|
+
'418': "I'm a teapot",
|
|
1670
|
+
'421': 'Misdirected Request',
|
|
1671
|
+
'422': 'Unprocessable Entity',
|
|
1672
|
+
'423': 'Locked',
|
|
1673
|
+
'424': 'Failed Dependency',
|
|
1674
|
+
'425': 'Too Early',
|
|
1675
|
+
'426': 'Upgrade Required',
|
|
1676
|
+
'428': 'Precondition Required',
|
|
1677
|
+
'429': 'Too Many Requests',
|
|
1678
|
+
'431': 'Request Header Fields Too Large',
|
|
1679
|
+
'451': 'Unavailable For Legal Reasons',
|
|
1680
|
+
'500': 'Internal Server Error',
|
|
1681
|
+
'501': 'Not Implemented',
|
|
1682
|
+
'502': 'Bad Gateway',
|
|
1683
|
+
'503': 'Service Unavailable',
|
|
1684
|
+
'504': 'Gateway Timeout',
|
|
1685
|
+
'505': 'HTTP Version Not Supported',
|
|
1686
|
+
'506': 'Variant Also Negotiates',
|
|
1687
|
+
'507': 'Insufficient Storage',
|
|
1688
|
+
'508': 'Loop Detected',
|
|
1689
|
+
'509': 'Bandwidth Limit Exceeded',
|
|
1690
|
+
'510': 'Not Extended',
|
|
1691
|
+
'511': 'Network Authentication Required'
|
|
1692
|
+
};
|
|
1693
|
+
|
|
1694
|
+
const LocaleModuleNameSeparator = '::';
|
|
1695
|
+
|
|
1696
|
+
class AppLocale extends BeanSimple {
|
|
1697
|
+
get current() {
|
|
1698
|
+
return this.ctx.locale;
|
|
1699
|
+
}
|
|
1700
|
+
set current(value) {
|
|
1701
|
+
this.ctx.locale = value;
|
|
1702
|
+
}
|
|
1703
|
+
get tz() {
|
|
1704
|
+
return this.ctx.tz;
|
|
1705
|
+
}
|
|
1706
|
+
set tz(value) {
|
|
1707
|
+
this.ctx.tz = value;
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
/** @internal */
|
|
1711
|
+
createLocaleText(moduleScope) {
|
|
1712
|
+
const self = this;
|
|
1713
|
+
const getText = function (text, ...args) {
|
|
1714
|
+
return self.getText(false, moduleScope, undefined, text, ...args);
|
|
1715
|
+
};
|
|
1716
|
+
getText.locale = function (locale, text, ...args) {
|
|
1717
|
+
return self.getText(false, moduleScope, locale, text, ...args);
|
|
1718
|
+
};
|
|
1719
|
+
return getText;
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
/** @internal */
|
|
1723
|
+
createScopeLocaleText(moduleScope, text) {
|
|
1724
|
+
const self = this;
|
|
1725
|
+
const getText = function (...args) {
|
|
1726
|
+
return self.getText(false, moduleScope, undefined, text, ...args);
|
|
1727
|
+
};
|
|
1728
|
+
getText.locale = function (locale, ...args) {
|
|
1729
|
+
return self.getText(false, moduleScope, locale, text, ...args);
|
|
1730
|
+
};
|
|
1731
|
+
return getText;
|
|
1732
|
+
}
|
|
1733
|
+
getText(supportCustomMessage, moduleScope, locale, key, ...args) {
|
|
1734
|
+
if (!key) return key;
|
|
1735
|
+
if (typeof key !== 'string') throw new Error(`${key} should be string`);
|
|
1736
|
+
const pos = key.indexOf(LocaleModuleNameSeparator);
|
|
1737
|
+
if (pos > -1) {
|
|
1738
|
+
moduleScope = key.substring(0, pos);
|
|
1739
|
+
key = key.substring(pos + LocaleModuleNameSeparator.length);
|
|
1740
|
+
}
|
|
1741
|
+
return localeutil.getLocaleText(supportCustomMessage, moduleScope ? this.app.meta.localeModules[moduleScope] : undefined, this.app.meta.locales, locale || this.current, key, ...args);
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
const BeanModuleScope$2 = Symbol('BeanScopeLocale#ModuleScope');
|
|
1746
|
+
class BeanScopeLocale extends BeanSimple {
|
|
1747
|
+
constructor(moduleScope) {
|
|
1748
|
+
super();
|
|
1749
|
+
this[BeanModuleScope$2] = void 0;
|
|
1750
|
+
this.__instances = {};
|
|
1751
|
+
this[BeanModuleScope$2] = moduleScope;
|
|
1752
|
+
}
|
|
1753
|
+
__get__(prop) {
|
|
1754
|
+
if (!this.__instances[prop]) {
|
|
1755
|
+
this.__instances[prop] = this.app.meta.locale.createScopeLocaleText(this[BeanModuleScope$2], prop);
|
|
1756
|
+
}
|
|
1757
|
+
return this.__instances[prop];
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
function $localeScope(moduleName, key) {
|
|
1762
|
+
return `${moduleName}::${String(key)}`;
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
const BeanModuleScope$1 = Symbol('BeanScopeScene#ModuleScope');
|
|
1766
|
+
const BeanModuleScene = Symbol('BeanScopeScene#BeanModuleScene');
|
|
1767
|
+
class BeanScopeScene extends BeanSimple {
|
|
1768
|
+
constructor(moduleScope, scene) {
|
|
1769
|
+
super();
|
|
1770
|
+
this[BeanModuleScope$1] = void 0;
|
|
1771
|
+
this[BeanModuleScene] = void 0;
|
|
1772
|
+
this.__instances = {};
|
|
1773
|
+
this[BeanModuleScope$1] = moduleScope;
|
|
1774
|
+
this[BeanModuleScene] = scene;
|
|
1775
|
+
}
|
|
1776
|
+
__get__(prop) {
|
|
1777
|
+
if (!this.__instances[prop]) {
|
|
1778
|
+
const beanFullName = `${this[BeanModuleScope$1]}.${this[BeanModuleScene]}.${prop}`;
|
|
1779
|
+
this.__instances[prop] = this.bean._injectBeanInstanceProp(this, beanFullName, {});
|
|
1780
|
+
}
|
|
1781
|
+
return this.__instances[prop];
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
|
|
1785
|
+
const BeanModuleScope = Symbol('BeanScopeScene#ModuleScope');
|
|
1786
|
+
class BeanScopeUtil extends BeanSimple {
|
|
1787
|
+
constructor(moduleScope) {
|
|
1788
|
+
super();
|
|
1789
|
+
this[BeanModuleScope] = void 0;
|
|
1790
|
+
this[BeanModuleScope] = moduleScope;
|
|
1791
|
+
}
|
|
1792
|
+
combineApiPath(path, prefix, simplify) {
|
|
1793
|
+
return this.app.util.combineApiPath(path, this[BeanModuleScope], prefix, simplify);
|
|
1794
|
+
}
|
|
1795
|
+
combineResourceName(resourceName, simplify, simplifyProviderId) {
|
|
1796
|
+
return this.app.util.combineResourceName(resourceName, this[BeanModuleScope], simplify, simplifyProviderId);
|
|
1797
|
+
}
|
|
1798
|
+
combineStaticPath(path) {
|
|
1799
|
+
return this.app.util.combineStaticPath(path, this[BeanModuleScope]);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
const BeanModuleError = Symbol('BeanScopeBase#BeanModuleError');
|
|
1804
|
+
const BeanModuleLocale = Symbol('BeanScopeBase#BeanModuleLocale');
|
|
1805
|
+
const BeanModuleUtil = Symbol('BeanScopeBase#BeanModuleUtil');
|
|
1806
|
+
const BeanModuleModel = Symbol('BeanScopeBase#BeanModuleModel');
|
|
1807
|
+
const BeanModuleEntity = Symbol('BeanScopeBase#BeanModuleEntity');
|
|
1808
|
+
class BeanScopeBase extends BeanBaseSimple {
|
|
1809
|
+
constructor(...args) {
|
|
1810
|
+
super(...args);
|
|
1811
|
+
this[BeanModuleError] = void 0;
|
|
1812
|
+
this[BeanModuleLocale] = void 0;
|
|
1813
|
+
this[BeanModuleUtil] = void 0;
|
|
1814
|
+
this[BeanModuleModel] = void 0;
|
|
1815
|
+
this[BeanModuleEntity] = void 0;
|
|
1816
|
+
this.__onionMetaNames = void 0;
|
|
1817
|
+
this.__scenes = {};
|
|
1818
|
+
this.__metas = {};
|
|
1819
|
+
}
|
|
1820
|
+
get module() {
|
|
1821
|
+
return this.app.meta.modules[this[SymbolModuleBelong]];
|
|
1822
|
+
}
|
|
1823
|
+
get onionMetaNames() {
|
|
1824
|
+
if (!this.__onionMetaNames) {
|
|
1825
|
+
this.__onionMetaNames = {};
|
|
1826
|
+
const onionMetasMeta = getOnionMetasMeta(this.app.meta.modules);
|
|
1827
|
+
for (const metaName in onionMetasMeta) {
|
|
1828
|
+
const onionMetaMeta = onionMetasMeta[metaName];
|
|
1829
|
+
if (onionMetaMeta.scopeResource) {
|
|
1830
|
+
this.__onionMetaNames[metaName] = true;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
return this.__onionMetaNames;
|
|
1835
|
+
}
|
|
1836
|
+
__get__(prop) {
|
|
1837
|
+
const moduleBelong = this[SymbolModuleBelong];
|
|
1838
|
+
// error
|
|
1839
|
+
if (prop === 'error') {
|
|
1840
|
+
if (!this[BeanModuleError]) {
|
|
1841
|
+
this[BeanModuleError] = this.bean._newBean(BeanScopeError, moduleBelong);
|
|
1842
|
+
}
|
|
1843
|
+
return this[BeanModuleError];
|
|
1844
|
+
}
|
|
1845
|
+
// locale
|
|
1846
|
+
if (prop === 'locale') {
|
|
1847
|
+
if (!this[BeanModuleLocale]) {
|
|
1848
|
+
this[BeanModuleLocale] = this.bean._newBean(BeanScopeLocale, moduleBelong);
|
|
1849
|
+
}
|
|
1850
|
+
return this[BeanModuleLocale];
|
|
1851
|
+
}
|
|
1852
|
+
// config
|
|
1853
|
+
if (prop === 'config') {
|
|
1854
|
+
// app or ctx
|
|
1855
|
+
const config = this.ctx?.config ?? this.app.config;
|
|
1856
|
+
return config.modules[moduleBelong];
|
|
1857
|
+
}
|
|
1858
|
+
// constant
|
|
1859
|
+
if (prop === 'constant') {
|
|
1860
|
+
return this.app.meta.constants[moduleBelong];
|
|
1861
|
+
}
|
|
1862
|
+
// util
|
|
1863
|
+
if (prop === 'util') {
|
|
1864
|
+
if (!this[BeanModuleUtil]) {
|
|
1865
|
+
this[BeanModuleUtil] = this.bean._newBean(BeanScopeUtil, moduleBelong);
|
|
1866
|
+
}
|
|
1867
|
+
return this[BeanModuleUtil];
|
|
1868
|
+
}
|
|
1869
|
+
// model
|
|
1870
|
+
if (prop === 'model') {
|
|
1871
|
+
if (!this[BeanModuleModel]) {
|
|
1872
|
+
this[BeanModuleModel] = this.bean._newBean('a-orm.service.modelResolver', moduleBelong);
|
|
1873
|
+
}
|
|
1874
|
+
return this[BeanModuleModel];
|
|
1875
|
+
}
|
|
1876
|
+
// entity
|
|
1877
|
+
if (prop === 'entity') {
|
|
1878
|
+
if (!this[BeanModuleEntity]) {
|
|
1879
|
+
this[BeanModuleEntity] = this.bean._newBean('a-orm.service.entityResolver', moduleBelong);
|
|
1880
|
+
}
|
|
1881
|
+
return this[BeanModuleEntity];
|
|
1882
|
+
}
|
|
1883
|
+
// meta
|
|
1884
|
+
if (this.onionMetaNames[prop]) {
|
|
1885
|
+
if (!this.__metas[prop]) {
|
|
1886
|
+
this.__metas[prop] = this.bean._getBean(`${moduleBelong}.meta.${prop}`);
|
|
1887
|
+
}
|
|
1888
|
+
return this.__metas[prop];
|
|
1889
|
+
}
|
|
1890
|
+
// scene
|
|
1891
|
+
if (!this.__scenes[prop]) {
|
|
1892
|
+
this.__scenes[prop] = this.bean._newBean(BeanScopeScene, moduleBelong, prop);
|
|
1893
|
+
}
|
|
1894
|
+
return this.__scenes[prop];
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
class BeanScopeContainer extends BeanSimple {
|
|
1899
|
+
constructor(...args) {
|
|
1900
|
+
super(...args);
|
|
1901
|
+
this.__instances = {};
|
|
1902
|
+
}
|
|
1903
|
+
__get__(prop) {
|
|
1904
|
+
if (!this.__instances[prop]) {
|
|
1905
|
+
let moduleName = splitWords(prop, true, '-');
|
|
1906
|
+
if (!moduleName?.includes('-')) {
|
|
1907
|
+
moduleName = `a-${moduleName}`;
|
|
1908
|
+
}
|
|
1909
|
+
this.__instances[prop] = this.bean.scope(moduleName);
|
|
1910
|
+
}
|
|
1911
|
+
return this.__instances[prop];
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
class VonaAsyncLocalStorage extends AsyncLocalStorage {
|
|
1916
|
+
constructor(app) {
|
|
1917
|
+
super();
|
|
1918
|
+
this.app = void 0;
|
|
1919
|
+
this.app = app;
|
|
1920
|
+
}
|
|
1921
|
+
async run(store, callback, ...args) {
|
|
1922
|
+
if (store === this.app.currentContext) {
|
|
1923
|
+
return await callback(...args);
|
|
1924
|
+
}
|
|
1925
|
+
return super.run(store, async (...args) => {
|
|
1926
|
+
try {
|
|
1927
|
+
this.app.meta.ctxCounter.increment();
|
|
1928
|
+
return await callback(...args);
|
|
1929
|
+
} finally {
|
|
1930
|
+
await store.bean.dispose();
|
|
1931
|
+
this.app.meta.ctxCounter.decrement();
|
|
1932
|
+
}
|
|
1933
|
+
}, ...args);
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1936
|
+
|
|
1937
|
+
const BEAN = Symbol.for('Context#__bean');
|
|
1938
|
+
const INNERACCESS = Symbol.for('Context#__inneraccess');
|
|
1939
|
+
const CTXCALLER = Symbol.for('Context#__ctxcaller');
|
|
1940
|
+
const ONIONSDYNAMIC = Symbol.for('Context#__onionsdynamic');
|
|
1941
|
+
const contextBase = {
|
|
1942
|
+
get bean() {
|
|
1943
|
+
const self = cast(this);
|
|
1944
|
+
if (!self[BEAN]) {
|
|
1945
|
+
self[BEAN] = BeanContainer.create(self.app, self);
|
|
1946
|
+
}
|
|
1947
|
+
return self[BEAN];
|
|
1948
|
+
},
|
|
1949
|
+
get locale() {
|
|
1950
|
+
const self = cast(this);
|
|
1951
|
+
return self.__getLocale();
|
|
1952
|
+
},
|
|
1953
|
+
set locale(value) {
|
|
1954
|
+
const self = cast(this);
|
|
1955
|
+
self.__setLocale(value);
|
|
1956
|
+
},
|
|
1957
|
+
get tz() {
|
|
1958
|
+
const self = cast(this);
|
|
1959
|
+
return self.__getTz();
|
|
1960
|
+
},
|
|
1961
|
+
set tz(value) {
|
|
1962
|
+
const self = cast(this);
|
|
1963
|
+
self.__setTz(value);
|
|
1964
|
+
},
|
|
1965
|
+
get instanceName() {
|
|
1966
|
+
const self = cast(this);
|
|
1967
|
+
return self.__getInstanceName();
|
|
1968
|
+
},
|
|
1969
|
+
set instanceName(value) {
|
|
1970
|
+
const self = cast(this);
|
|
1971
|
+
self.__setInstanceName(value);
|
|
1972
|
+
},
|
|
1973
|
+
get config() {
|
|
1974
|
+
const self = cast(this);
|
|
1975
|
+
const serviceInstance = cast(self.app.bean._getBean('a-instance.service.instance'));
|
|
1976
|
+
return serviceInstance.getConfig(self.instanceName) || self.app.config;
|
|
1977
|
+
},
|
|
1978
|
+
get innerAccess() {
|
|
1979
|
+
return this[INNERACCESS];
|
|
1980
|
+
},
|
|
1981
|
+
set innerAccess(value) {
|
|
1982
|
+
this[INNERACCESS] = value;
|
|
1983
|
+
},
|
|
1984
|
+
get ctxCaller() {
|
|
1985
|
+
return this[CTXCALLER];
|
|
1986
|
+
},
|
|
1987
|
+
set ctxCaller(value) {
|
|
1988
|
+
this[CTXCALLER] = value;
|
|
1989
|
+
},
|
|
1990
|
+
getController() {
|
|
1991
|
+
const self = cast(this);
|
|
1992
|
+
return self.route?.controller;
|
|
1993
|
+
},
|
|
1994
|
+
getControllerPrototype() {
|
|
1995
|
+
const self = cast(this);
|
|
1996
|
+
const controller = self.getController();
|
|
1997
|
+
if (!controller) return undefined;
|
|
1998
|
+
return controller.prototype;
|
|
1999
|
+
},
|
|
2000
|
+
getControllerBean() {
|
|
2001
|
+
const self = cast(this);
|
|
2002
|
+
const beanFullName = self.getControllerBeanFullName();
|
|
2003
|
+
if (!beanFullName) return;
|
|
2004
|
+
return self.app.bean._getBean(beanFullName);
|
|
2005
|
+
},
|
|
2006
|
+
getControllerBeanFullName() {
|
|
2007
|
+
const self = cast(this);
|
|
2008
|
+
const controller = self.getController();
|
|
2009
|
+
if (!controller) return undefined;
|
|
2010
|
+
const beanOptions = appResource.getBean(controller);
|
|
2011
|
+
return beanOptions?.beanFullName;
|
|
2012
|
+
},
|
|
2013
|
+
getHandler() {
|
|
2014
|
+
const self = cast(this);
|
|
2015
|
+
return self.route?.actionDescriptor?.value;
|
|
2016
|
+
},
|
|
2017
|
+
getHandlerName() {
|
|
2018
|
+
const self = cast(this);
|
|
2019
|
+
return self.route?.action;
|
|
2020
|
+
},
|
|
2021
|
+
get onionsDynamic() {
|
|
2022
|
+
return this[ONIONSDYNAMIC];
|
|
2023
|
+
},
|
|
2024
|
+
set onionsDynamic(value) {
|
|
2025
|
+
this[ONIONSDYNAMIC] = value;
|
|
2026
|
+
},
|
|
2027
|
+
get acceptJSON() {
|
|
2028
|
+
const self = cast(this);
|
|
2029
|
+
if (self.path.endsWith('.json')) return true;
|
|
2030
|
+
if (self.response.type && self.response.type.includes('json')) return true;
|
|
2031
|
+
if (self.request.headers['content-type']?.includes('application/json') && self.accepts('json') === 'json') return true;
|
|
2032
|
+
if (self.accepts('html', 'text', 'json') === 'json') return true;
|
|
2033
|
+
return false;
|
|
2034
|
+
},
|
|
2035
|
+
redirect(url, status) {
|
|
2036
|
+
const self = cast(this);
|
|
2037
|
+
// checkOrigin
|
|
2038
|
+
if (!url.startsWith('/')) {
|
|
2039
|
+
const origin = cast(self.app.bean).security.checkOrigin(url, self.host);
|
|
2040
|
+
if (!origin) self.app.throw(403);
|
|
2041
|
+
}
|
|
2042
|
+
// throw
|
|
2043
|
+
status = status ?? 302;
|
|
2044
|
+
self.app.throw(status, url);
|
|
2045
|
+
}
|
|
2046
|
+
};
|
|
2047
|
+
|
|
2048
|
+
class CtxCounter {
|
|
2049
|
+
constructor() {
|
|
2050
|
+
this._ctxCounter = 0;
|
|
2051
|
+
}
|
|
2052
|
+
get current() {
|
|
2053
|
+
return this._ctxCounter;
|
|
2054
|
+
}
|
|
2055
|
+
increment() {
|
|
2056
|
+
return ++this._ctxCounter;
|
|
2057
|
+
}
|
|
2058
|
+
decrement() {
|
|
2059
|
+
return --this._ctxCounter;
|
|
2060
|
+
}
|
|
2061
|
+
async awaitUntilZero() {
|
|
2062
|
+
while (true) {
|
|
2063
|
+
if (this.current === 0) break;
|
|
2064
|
+
await sleep(200);
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
const SymbolHmrStateSave = Symbol('SymbolHmrStateSave');
|
|
2070
|
+
const SymbolHmrStateLoad = Symbol('SymbolHmrStateLoad');
|
|
2071
|
+
class AppHmr extends BeanSimple {
|
|
2072
|
+
constructor(...args) {
|
|
2073
|
+
super(...args);
|
|
2074
|
+
this.recordBeanInstances = {};
|
|
2075
|
+
this.recordBeanInstanceProps = {};
|
|
2076
|
+
}
|
|
2077
|
+
addBeanInstance(beanFullName, beanInstanceKey, args, withSelector) {
|
|
2078
|
+
if (!this.recordBeanInstances[beanFullName]) {
|
|
2079
|
+
this.recordBeanInstances[beanFullName] = [];
|
|
2080
|
+
}
|
|
2081
|
+
this.recordBeanInstances[beanFullName].push({
|
|
2082
|
+
beanInstanceKey,
|
|
2083
|
+
withSelector,
|
|
2084
|
+
args
|
|
2085
|
+
});
|
|
2086
|
+
}
|
|
2087
|
+
addBeanInstanceProp(beanInstance, prop, targetBeanFullName) {
|
|
2088
|
+
if (!this.recordBeanInstanceProps[targetBeanFullName]) {
|
|
2089
|
+
this.recordBeanInstanceProps[targetBeanFullName] = [];
|
|
2090
|
+
}
|
|
2091
|
+
this.recordBeanInstanceProps[targetBeanFullName].push({
|
|
2092
|
+
beanInstance,
|
|
2093
|
+
prop
|
|
2094
|
+
});
|
|
2095
|
+
}
|
|
2096
|
+
mutateBeanInstance(beanFullName, beanInstanceKey, args) {
|
|
2097
|
+
const beanInstances = this.recordBeanInstances[beanFullName];
|
|
2098
|
+
if (!beanInstances) return;
|
|
2099
|
+
const beanInstance = beanInstances.find(item => item.beanInstanceKey === beanInstanceKey);
|
|
2100
|
+
if (!beanInstance) return;
|
|
2101
|
+
beanInstance.args = args;
|
|
2102
|
+
}
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
const SymbolLoggerInstances = Symbol('SymbolLoggerInstances');
|
|
2106
|
+
class AppLogger extends BeanSimple {
|
|
2107
|
+
constructor(...args) {
|
|
2108
|
+
super(...args);
|
|
2109
|
+
this[SymbolLoggerInstances] = {};
|
|
2110
|
+
}
|
|
2111
|
+
async dispose() {
|
|
2112
|
+
for (const key in this[SymbolLoggerInstances]) {
|
|
2113
|
+
const logger = this[SymbolLoggerInstances][key];
|
|
2114
|
+
await _closeLogger(logger);
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2117
|
+
get(clientName) {
|
|
2118
|
+
clientName = clientName || 'default';
|
|
2119
|
+
if (!this[SymbolLoggerInstances][clientName]) {
|
|
2120
|
+
this[SymbolLoggerInstances][clientName] = this._createClient(clientName);
|
|
2121
|
+
}
|
|
2122
|
+
return this[SymbolLoggerInstances][clientName];
|
|
2123
|
+
}
|
|
2124
|
+
child(childName, clientName) {
|
|
2125
|
+
const logger = this.get(clientName);
|
|
2126
|
+
if (!childName) return logger;
|
|
2127
|
+
return logger.child({
|
|
2128
|
+
name: childName
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
2131
|
+
getLevel(clientName) {
|
|
2132
|
+
clientName = clientName || 'default';
|
|
2133
|
+
const envName = `LOGGER_CLIENT_${clientName.toUpperCase()}`;
|
|
2134
|
+
const level = this.app.meta.env[envName];
|
|
2135
|
+
if (level === 'false') return false;
|
|
2136
|
+
if (level === 'true' || !level) return 'info';
|
|
2137
|
+
return level;
|
|
2138
|
+
}
|
|
2139
|
+
setLevel(level, clientName) {
|
|
2140
|
+
clientName = clientName || 'default';
|
|
2141
|
+
const envName = `LOGGER_CLIENT_${clientName.toUpperCase()}`;
|
|
2142
|
+
this.app.meta.env[envName] = level.toString();
|
|
2143
|
+
}
|
|
2144
|
+
_createClient(clientName) {
|
|
2145
|
+
const configClient = this.app.config.logger.clients[clientName];
|
|
2146
|
+
if (!configClient) throw new Error(`logger client not found: ${clientName}`);
|
|
2147
|
+
const configNode = deepExtend({}, this._prepareConfigClient(clientName, this.app.config.logger.base), this._prepareConfigClient(clientName, configClient));
|
|
2148
|
+
const logger = Winston.createLogger(configNode);
|
|
2149
|
+
logger.on('error', err => {
|
|
2150
|
+
console.error(err);
|
|
2151
|
+
});
|
|
2152
|
+
return logger;
|
|
2153
|
+
}
|
|
2154
|
+
_prepareConfigClient(clientName, configClient) {
|
|
2155
|
+
if (typeof configClient !== 'function') return configClient;
|
|
2156
|
+
return configClient.call(this.app, {
|
|
2157
|
+
clientName,
|
|
2158
|
+
level: () => this.getLevel(clientName)
|
|
2159
|
+
}, Winston);
|
|
2160
|
+
}
|
|
2161
|
+
createTransportFile(fileName, clientInfo, options) {
|
|
2162
|
+
const dirname = this.app.config.logger.baseDir;
|
|
2163
|
+
if (!fse.existsSync(dirname)) {
|
|
2164
|
+
const [_, err] = catchErrorSync(() => {
|
|
2165
|
+
fse.ensureDirSync(dirname);
|
|
2166
|
+
});
|
|
2167
|
+
if (err) {
|
|
2168
|
+
throw new Error(`Failed to create logger dir: ${dirname}`);
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
const configRotate = this.app.config.logger.rotate.call(this, fileName, Winston, clientInfo);
|
|
2172
|
+
let optionsFile;
|
|
2173
|
+
if (configRotate.enable) {
|
|
2174
|
+
optionsFile = configRotate;
|
|
2175
|
+
} else {
|
|
2176
|
+
optionsFile = Object.assign({}, {
|
|
2177
|
+
filename: `${fileName}.log`
|
|
2178
|
+
}, configRotate);
|
|
2179
|
+
}
|
|
2180
|
+
const _options = deepExtend({
|
|
2181
|
+
dirname
|
|
2182
|
+
}, optionsFile, options);
|
|
2183
|
+
if (configRotate.enable) {
|
|
2184
|
+
const transport = new DailyRotateFile(_options);
|
|
2185
|
+
transport.on('error', err => {
|
|
2186
|
+
console.error(err);
|
|
2187
|
+
});
|
|
2188
|
+
return transport;
|
|
2189
|
+
} else {
|
|
2190
|
+
return new Winston.transports.File(_options);
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2194
|
+
async function _closeLogger(logger) {
|
|
2195
|
+
return new Promise(resolve => {
|
|
2196
|
+
if (logger.__closed__) return resolve(true);
|
|
2197
|
+
logger.end(() => {
|
|
2198
|
+
logger.__closed__ = true;
|
|
2199
|
+
resolve(true);
|
|
2200
|
+
});
|
|
2201
|
+
});
|
|
2202
|
+
}
|
|
2203
|
+
|
|
2204
|
+
const SymbolClosePromise = Symbol('SymbolClosePromise');
|
|
2205
|
+
class AppMeta extends BeanSimple {
|
|
2206
|
+
constructor(...args) {
|
|
2207
|
+
super(...args);
|
|
2208
|
+
this.env = void 0;
|
|
2209
|
+
this.ctxCounter = void 0;
|
|
2210
|
+
this.isProd = void 0;
|
|
2211
|
+
this.isTest = void 0;
|
|
2212
|
+
this.isDev = void 0;
|
|
2213
|
+
this.isLocal = void 0;
|
|
2214
|
+
this.error = void 0;
|
|
2215
|
+
this.logger = void 0;
|
|
2216
|
+
this.locale = void 0;
|
|
2217
|
+
this.hmr = void 0;
|
|
2218
|
+
this.text = void 0;
|
|
2219
|
+
this.scopeContainer = void 0;
|
|
2220
|
+
this.appMonkey = void 0;
|
|
2221
|
+
//
|
|
2222
|
+
this.resource = void 0;
|
|
2223
|
+
this.metadata = void 0;
|
|
2224
|
+
//
|
|
2225
|
+
this.modules = void 0;
|
|
2226
|
+
this.modulesArray = void 0;
|
|
2227
|
+
this.modulesMonkey = void 0;
|
|
2228
|
+
//
|
|
2229
|
+
this.constants = void 0;
|
|
2230
|
+
this.locales = void 0;
|
|
2231
|
+
this.localeModules = void 0;
|
|
2232
|
+
//
|
|
2233
|
+
this.hmrCacheLocaleModules = void 0;
|
|
2234
|
+
this.hmrCacheConfigModules = void 0;
|
|
2235
|
+
//
|
|
2236
|
+
this.appReady = void 0;
|
|
2237
|
+
this.appReadyInstances = void 0;
|
|
2238
|
+
//
|
|
2239
|
+
this.appStarted = void 0;
|
|
2240
|
+
this.appStartError = void 0;
|
|
2241
|
+
//
|
|
2242
|
+
this.appClose = void 0;
|
|
2243
|
+
this.appClosed = void 0;
|
|
2244
|
+
}
|
|
2245
|
+
__init__(env) {
|
|
2246
|
+
// env
|
|
2247
|
+
this.env = env;
|
|
2248
|
+
this._prepareEnv();
|
|
2249
|
+
|
|
2250
|
+
// ctxCounter
|
|
2251
|
+
this.ctxCounter = new CtxCounter();
|
|
2252
|
+
|
|
2253
|
+
// appMonkey
|
|
2254
|
+
this.appMonkey = this.app.options.AppMonkey ? new this.app.options.AppMonkey() : undefined;
|
|
2255
|
+
|
|
2256
|
+
// logger
|
|
2257
|
+
this.logger = this.bean._newBean(AppLogger);
|
|
2258
|
+
|
|
2259
|
+
// locale
|
|
2260
|
+
this.locale = this.bean._newBean(AppLocale);
|
|
2261
|
+
|
|
2262
|
+
// hmr
|
|
2263
|
+
if (process.env.META_MODE === 'dev') {
|
|
2264
|
+
this.hmr = this.bean._newBean(AppHmr);
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
// text
|
|
2268
|
+
this.text = this.locale.createLocaleText();
|
|
2269
|
+
|
|
2270
|
+
// scopeContainer
|
|
2271
|
+
this.scopeContainer = this.bean._newBean(BeanScopeContainer);
|
|
2272
|
+
|
|
2273
|
+
// resource
|
|
2274
|
+
this.resource = appResource;
|
|
2275
|
+
this.resource.app = this.app;
|
|
2276
|
+
|
|
2277
|
+
// metadata
|
|
2278
|
+
this.metadata = appMetadata;
|
|
2279
|
+
}
|
|
2280
|
+
_prepareEnv() {
|
|
2281
|
+
const mode = this.app.configMeta.mode;
|
|
2282
|
+
this.isProd = mode === 'prod';
|
|
2283
|
+
this.isTest = mode === 'test';
|
|
2284
|
+
this.isDev = mode === 'dev';
|
|
2285
|
+
this.isLocal = this.isTest || this.isDev;
|
|
2286
|
+
}
|
|
2287
|
+
async waitAppStarted() {
|
|
2288
|
+
return new Promise((resolve, reject) => {
|
|
2289
|
+
// check once
|
|
2290
|
+
if (this.appStarted) {
|
|
2291
|
+
resolve(true);
|
|
2292
|
+
}
|
|
2293
|
+
if (this.appStartError) {
|
|
2294
|
+
reject(this.appStartError);
|
|
2295
|
+
}
|
|
2296
|
+
// listen
|
|
2297
|
+
this.app.once(EnumAppEvent.AppStarted, () => {
|
|
2298
|
+
resolve(true);
|
|
2299
|
+
});
|
|
2300
|
+
this.app.once(EnumAppEvent.AppStartError, err => {
|
|
2301
|
+
reject(err);
|
|
2302
|
+
});
|
|
2303
|
+
});
|
|
2304
|
+
}
|
|
2305
|
+
async close() {
|
|
2306
|
+
if (!this[SymbolClosePromise]) {
|
|
2307
|
+
this[SymbolClosePromise] = this._closeInner();
|
|
2308
|
+
}
|
|
2309
|
+
return this[SymbolClosePromise];
|
|
2310
|
+
}
|
|
2311
|
+
async _closeInner() {
|
|
2312
|
+
// should not call disconnect, which will cause channel closed
|
|
2313
|
+
// cluster.worker?.disconnect();
|
|
2314
|
+
// close server
|
|
2315
|
+
if (this.app.server) {
|
|
2316
|
+
this.app.server.close();
|
|
2317
|
+
// maybe hang up using await
|
|
2318
|
+
// await promisify(this.app.server.close).call(this.app.server);
|
|
2319
|
+
}
|
|
2320
|
+
// appClose
|
|
2321
|
+
this.appClose = true;
|
|
2322
|
+
// hook: appClose
|
|
2323
|
+
await this.app.util.monkeyModule(this.app.meta.appMonkey, this.app.meta.modulesMonkey, 'appClose');
|
|
2324
|
+
// ctx counter
|
|
2325
|
+
await this.app.meta.ctxCounter.awaitUntilZero();
|
|
2326
|
+
// appClosed
|
|
2327
|
+
this.appClosed = true;
|
|
2328
|
+
// hook: appClosed
|
|
2329
|
+
await this.app.util.monkeyModule(this.app.meta.appMonkey, this.app.meta.modulesMonkey, 'appClosed');
|
|
2330
|
+
// container dispose
|
|
2331
|
+
await this.app.bean.dispose();
|
|
2332
|
+
// logger dispose
|
|
2333
|
+
await this.app.meta.logger.dispose();
|
|
2334
|
+
// log
|
|
2335
|
+
if (this.app.meta.env.LOGGER_DUMMY !== 'true') {
|
|
2336
|
+
const message = `App shutdown gracefully: ${process.pid}`;
|
|
2337
|
+
// eslint-disable-next-line
|
|
2338
|
+
console.log(chalk.cyan(message));
|
|
2339
|
+
}
|
|
2340
|
+
// need not call process.exit
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
class ResponseMock {
|
|
2345
|
+
constructor() {
|
|
2346
|
+
this._headers = {};
|
|
2347
|
+
}
|
|
2348
|
+
getHeader(field) {
|
|
2349
|
+
return this._headers[field];
|
|
2350
|
+
}
|
|
2351
|
+
setHeader(field, val) {
|
|
2352
|
+
this._headers[field] = val;
|
|
2353
|
+
}
|
|
2354
|
+
hasHeader(field) {
|
|
2355
|
+
return this._headers[field] !== undefined;
|
|
2356
|
+
}
|
|
2357
|
+
removeHeader(field) {
|
|
2358
|
+
delete this._headers[field];
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
class VonaApplication extends KoaApplication {
|
|
2363
|
+
constructor(options) {
|
|
2364
|
+
const env = options.env;
|
|
2365
|
+
const koaOptions = {
|
|
2366
|
+
env: cast(env).NODE_ENV,
|
|
2367
|
+
asyncLocalStorage: false
|
|
2368
|
+
};
|
|
2369
|
+
super(koaOptions);
|
|
2370
|
+
this.options = void 0;
|
|
2371
|
+
this.config = void 0;
|
|
2372
|
+
this.bean = void 0;
|
|
2373
|
+
this.util = void 0;
|
|
2374
|
+
this.meta = void 0;
|
|
2375
|
+
this.server = void 0;
|
|
2376
|
+
this.ctxStorage = void 0;
|
|
2377
|
+
this.options = options;
|
|
2378
|
+
this.bean = BeanContainer.create(this, undefined);
|
|
2379
|
+
this.util = this.bean._newBean(AppUtil);
|
|
2380
|
+
this.meta = this.bean._newBean(AppMeta, env);
|
|
2381
|
+
// asyncLocalStorage
|
|
2382
|
+
this.ctxStorage = new VonaAsyncLocalStorage(this);
|
|
2383
|
+
// app.context
|
|
2384
|
+
for (const key of Reflect.ownKeys(contextBase)) {
|
|
2385
|
+
const desc = Object.getOwnPropertyDescriptor(contextBase, key);
|
|
2386
|
+
Object.defineProperty(this.context, key, desc);
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
get name() {
|
|
2390
|
+
return this.options.name;
|
|
2391
|
+
}
|
|
2392
|
+
get projectPath() {
|
|
2393
|
+
return this.options.projectPath;
|
|
2394
|
+
}
|
|
2395
|
+
get configMeta() {
|
|
2396
|
+
return this.options.configMeta;
|
|
2397
|
+
}
|
|
2398
|
+
get ctx() {
|
|
2399
|
+
return this.currentContext;
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
/** get specific module's scope */
|
|
2403
|
+
|
|
2404
|
+
// scope<T>(moduleScope: string): T;
|
|
2405
|
+
scope(moduleScope) {
|
|
2406
|
+
return this.bean.scope(moduleScope);
|
|
2407
|
+
}
|
|
2408
|
+
createAnonymousContext(req, res) {
|
|
2409
|
+
let request;
|
|
2410
|
+
if (req) {
|
|
2411
|
+
request = req;
|
|
2412
|
+
} else {
|
|
2413
|
+
const host = `localhost:${this.meta.env.SERVER_LISTEN_PORT}`;
|
|
2414
|
+
request = {
|
|
2415
|
+
headers: {
|
|
2416
|
+
'host': host,
|
|
2417
|
+
'x-forwarded-for': host
|
|
2418
|
+
},
|
|
2419
|
+
query: {},
|
|
2420
|
+
querystring: '',
|
|
2421
|
+
host,
|
|
2422
|
+
hostname: 'localhost',
|
|
2423
|
+
protocol: 'http',
|
|
2424
|
+
secure: 'false',
|
|
2425
|
+
method: 'POST',
|
|
2426
|
+
url: '',
|
|
2427
|
+
path: '',
|
|
2428
|
+
socket: {
|
|
2429
|
+
remoteAddress: '127.0.0.1',
|
|
2430
|
+
remotePort: 7001
|
|
2431
|
+
}
|
|
2432
|
+
};
|
|
2433
|
+
}
|
|
2434
|
+
const response = res ?? new ResponseMock();
|
|
2435
|
+
return this.createContext(request, response);
|
|
2436
|
+
}
|
|
2437
|
+
async close(terminate) {
|
|
2438
|
+
await closeApp(terminate);
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
async function combineConfigDefault(app, configDefault, configDev, configProd, configTest) {
|
|
2443
|
+
let config = await configDefault(app);
|
|
2444
|
+
const mode = app.config.meta.mode;
|
|
2445
|
+
if (mode === 'dev' && configDev) {
|
|
2446
|
+
config = deepExtend(config, await configDev(app));
|
|
2447
|
+
} else if (mode === 'prod' && configProd) {
|
|
2448
|
+
config = deepExtend(config, await configProd(app));
|
|
2449
|
+
} else if (mode === 'test' && configTest) {
|
|
2450
|
+
config = deepExtend(config, await configTest(app));
|
|
2451
|
+
}
|
|
2452
|
+
return config;
|
|
2453
|
+
}
|
|
2454
|
+
function getLoggerPathPhysicalRoot(app) {
|
|
2455
|
+
const mode = app.configMeta.mode;
|
|
2456
|
+
let loggerDir;
|
|
2457
|
+
if (mode === 'test' || mode === 'dev') {
|
|
2458
|
+
loggerDir = path.join(app.projectPath, '.app/logs');
|
|
2459
|
+
} else {
|
|
2460
|
+
loggerDir = path.join(os.homedir(), 'vona', app.name, 'logs');
|
|
2461
|
+
}
|
|
2462
|
+
fse.ensureDirSync(loggerDir);
|
|
2463
|
+
return loggerDir;
|
|
2464
|
+
}
|
|
2465
|
+
function getPublicPathPhysicalRoot(app) {
|
|
2466
|
+
const mode = app.configMeta.mode;
|
|
2467
|
+
let publicDir;
|
|
2468
|
+
if (mode === 'test' || mode === 'dev') {
|
|
2469
|
+
publicDir = path.join(app.projectPath, '.app/public');
|
|
2470
|
+
} else {
|
|
2471
|
+
publicDir = path.join(os.homedir(), 'vona', app.name, 'public');
|
|
2472
|
+
}
|
|
2473
|
+
fse.ensureDirSync(publicDir);
|
|
2474
|
+
return publicDir;
|
|
2475
|
+
}
|
|
2476
|
+
function getRuntimePathPhysicalRoot(app) {
|
|
2477
|
+
const mode = app.config.meta.mode;
|
|
2478
|
+
let runtimeDir;
|
|
2479
|
+
if (mode === 'test' || mode === 'dev') {
|
|
2480
|
+
runtimeDir = path.join(app.options.projectPath, '.app/runtime');
|
|
2481
|
+
} else {
|
|
2482
|
+
runtimeDir = path.join(os.homedir(), 'vona', app.options.name, 'runtime');
|
|
2483
|
+
}
|
|
2484
|
+
fse.ensureDirSync(runtimeDir);
|
|
2485
|
+
return runtimeDir;
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
var enUs = {
|
|
2489
|
+
...errorsInternal,
|
|
2490
|
+
ValidationFailedDev: 'controller: %s, method: %s, argument: %d'
|
|
2491
|
+
};
|
|
2492
|
+
|
|
2493
|
+
var zhCn = {
|
|
2494
|
+
ValidationFailedDev: '控制器: %s, 方法: %s, 参数: %d',
|
|
2495
|
+
// http status
|
|
2496
|
+
0: '成功',
|
|
2497
|
+
1: '未知错误',
|
|
2498
|
+
100: '继续',
|
|
2499
|
+
101: '切换协议',
|
|
2500
|
+
102: '处理中',
|
|
2501
|
+
103: '早期线索',
|
|
2502
|
+
200: '成功',
|
|
2503
|
+
201: '已创建',
|
|
2504
|
+
202: '已接受',
|
|
2505
|
+
203: '非认证信息',
|
|
2506
|
+
204: '没有内容',
|
|
2507
|
+
205: '重置内容',
|
|
2508
|
+
206: '部分内容',
|
|
2509
|
+
207: '多状态',
|
|
2510
|
+
208: '已报告',
|
|
2511
|
+
226: 'IM_Used',
|
|
2512
|
+
300: '多选择',
|
|
2513
|
+
301: '永久转移',
|
|
2514
|
+
302: '已发现',
|
|
2515
|
+
303: '参考其他',
|
|
2516
|
+
304: '未变更',
|
|
2517
|
+
305: '使用代理',
|
|
2518
|
+
307: '临时转向',
|
|
2519
|
+
308: '永久转向',
|
|
2520
|
+
400: '无效请求',
|
|
2521
|
+
401: '未经认证',
|
|
2522
|
+
402: '需要支付',
|
|
2523
|
+
403: '访问被禁止',
|
|
2524
|
+
404: '未发现',
|
|
2525
|
+
405: '方法不允许',
|
|
2526
|
+
406: '不可接受',
|
|
2527
|
+
407: '需要代理认证',
|
|
2528
|
+
408: '请求超时',
|
|
2529
|
+
409: '冲突',
|
|
2530
|
+
410: '已失效',
|
|
2531
|
+
411: '需要指定长度',
|
|
2532
|
+
412: '条件不匹配',
|
|
2533
|
+
413: '载荷过大',
|
|
2534
|
+
414: 'URL地址太长',
|
|
2535
|
+
415: '不支持的媒体类型',
|
|
2536
|
+
416: '请求的范围不匹配',
|
|
2537
|
+
417: '期望值不匹配',
|
|
2538
|
+
418: '我是一个茶壶',
|
|
2539
|
+
421: '无效转向',
|
|
2540
|
+
422: '无法处理的内容',
|
|
2541
|
+
423: '已锁定',
|
|
2542
|
+
424: '依赖失败',
|
|
2543
|
+
425: '太早',
|
|
2544
|
+
426: '需要升级',
|
|
2545
|
+
428: '需要指定条件',
|
|
2546
|
+
429: '请求太多',
|
|
2547
|
+
431: '请求头部字段太大',
|
|
2548
|
+
451: '由于法律原因无法使用',
|
|
2549
|
+
500: '内部服务错误',
|
|
2550
|
+
501: '没有实现',
|
|
2551
|
+
502: '无效网关',
|
|
2552
|
+
503: '服务无法访问',
|
|
2553
|
+
504: '网关超时',
|
|
2554
|
+
505: 'HTTP版本不支持',
|
|
2555
|
+
506: '变量需要协商',
|
|
2556
|
+
507: '存储空间不足',
|
|
2557
|
+
508: '检测到无限循环',
|
|
2558
|
+
509: '超过带宽限制',
|
|
2559
|
+
510: '未扩展',
|
|
2560
|
+
511: '需要网络认证'
|
|
2561
|
+
};
|
|
2562
|
+
|
|
2563
|
+
var localesDefault = {
|
|
2564
|
+
'en-us': enUs,
|
|
2565
|
+
'zh-cn': zhCn
|
|
2566
|
+
};
|
|
2567
|
+
|
|
2568
|
+
const SymbolLoggerMessage = Symbol('SymbolLoggerMessage');
|
|
2569
|
+
const formatLoggerAxiosError = Winston.format((einfo, {
|
|
2570
|
+
stack,
|
|
2571
|
+
cause
|
|
2572
|
+
}) => {
|
|
2573
|
+
if (einfo instanceof Error && einfo.constructor.name.includes('AxiosError') || einfo.name === 'AxiosError') {
|
|
2574
|
+
const info = Object.assign({}, einfo, {
|
|
2575
|
+
level: einfo.level,
|
|
2576
|
+
[LEVEL]: einfo[LEVEL] || einfo.level,
|
|
2577
|
+
message: einfo.message,
|
|
2578
|
+
[MESSAGE]: einfo[MESSAGE] || einfo.message
|
|
2579
|
+
});
|
|
2580
|
+
if (stack) info.stack = einfo.stack;
|
|
2581
|
+
if (cause) info.cause = einfo.cause;
|
|
2582
|
+
info.message = `${info.message}: ${cast(info.config).url}`;
|
|
2583
|
+
info[MESSAGE] = `${info[MESSAGE]}: ${cast(info.config).url}`;
|
|
2584
|
+
delete info.config;
|
|
2585
|
+
delete info.request;
|
|
2586
|
+
delete info.response;
|
|
2587
|
+
return info;
|
|
2588
|
+
}
|
|
2589
|
+
return einfo;
|
|
2590
|
+
});
|
|
2591
|
+
const formatLoggerCtx = Winston.format((info, _opts) => {
|
|
2592
|
+
const app = useApp();
|
|
2593
|
+
if (!app.ctx || !app.ctx.method || !app.ctx.path) return info;
|
|
2594
|
+
info.method = app.ctx.method;
|
|
2595
|
+
info.path = app.ctx.path;
|
|
2596
|
+
return info;
|
|
2597
|
+
});
|
|
2598
|
+
const formatLoggerDummy = Winston.format(info => {
|
|
2599
|
+
const app = useApp();
|
|
2600
|
+
if (app.meta.env.LOGGER_DUMMY === 'true') return false;
|
|
2601
|
+
return info;
|
|
2602
|
+
});
|
|
2603
|
+
const formatLoggerFilter = Winston.format((info, opts) => {
|
|
2604
|
+
const level = typeof opts.level === 'function' ? opts.level() : opts.level;
|
|
2605
|
+
if (!level) return false;
|
|
2606
|
+
if (opts.strict) {
|
|
2607
|
+
if (Winston.config.npm.levels[info.level] === Winston.config.npm.levels[level]) return __formatLoggerFilterCheckInfo(info);
|
|
2608
|
+
return false;
|
|
2609
|
+
}
|
|
2610
|
+
if (Winston.config.npm.levels[info.level] <= Winston.config.npm.levels[level] || opts.silly && info.level === 'silly') return __formatLoggerFilterCheckInfo(info);
|
|
2611
|
+
return false;
|
|
2612
|
+
});
|
|
2613
|
+
const formatLoggerConsole = clientInfo => {
|
|
2614
|
+
return Winston.format.printf(({
|
|
2615
|
+
timestamp,
|
|
2616
|
+
level,
|
|
2617
|
+
stack,
|
|
2618
|
+
message,
|
|
2619
|
+
name,
|
|
2620
|
+
beanFullName,
|
|
2621
|
+
durationMs,
|
|
2622
|
+
...meta
|
|
2623
|
+
}) => {
|
|
2624
|
+
const textClientName = clientInfo.clientName === 'default' ? '' : ` ${chalk.cyan(`[${clientInfo.clientName}]`)}`;
|
|
2625
|
+
const textName = name ? ` ${chalk.cyan(`[${name}]`)}` : '';
|
|
2626
|
+
const textBeanFullName = beanFullName ? ` ${chalk.gray(`[${beanFullName}]`)}` : '';
|
|
2627
|
+
const textMeta = !isEmptyObject(meta) ? ` ${JSON.stringify(meta)}` : '';
|
|
2628
|
+
const textMessage = ` ${message}`;
|
|
2629
|
+
const textDurationMs = durationMs !== undefined ? ` ${chalk.cyan(`+${durationMs}ms`)}` : '';
|
|
2630
|
+
const textStack = stack ? `\n${stack}` : '';
|
|
2631
|
+
return `${timestamp} ${level}${textClientName}${textName}${textBeanFullName}${textMeta}${textMessage}${textDurationMs}${textStack}`;
|
|
2632
|
+
});
|
|
2633
|
+
};
|
|
2634
|
+
function __formatLoggerFilterCheckInfo(info) {
|
|
2635
|
+
if (typeof info.message === 'function') {
|
|
2636
|
+
if (info.message[SymbolLoggerMessage] === undefined) {
|
|
2637
|
+
info.message[SymbolLoggerMessage] = info.message();
|
|
2638
|
+
}
|
|
2639
|
+
info.message = info.message[SymbolLoggerMessage];
|
|
2640
|
+
}
|
|
2641
|
+
return info;
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
async function loadConfig (app, modules) {
|
|
2645
|
+
app.meta.hmrCacheConfigModules = deepExtend({}, app.config.modules);
|
|
2646
|
+
// load configs
|
|
2647
|
+
await loadConfigs();
|
|
2648
|
+
async function loadConfigs() {
|
|
2649
|
+
for (const key in modules) {
|
|
2650
|
+
const module = modules[key];
|
|
2651
|
+
// module config
|
|
2652
|
+
if (module.resource.config) {
|
|
2653
|
+
const configModule = await module.resource.config(app, app.options.env);
|
|
2654
|
+
// configNew is not used by now
|
|
2655
|
+
await app.util.monkeyModule(app.meta.appMonkey, app.meta.modulesMonkey, 'configLoaded', module, configModule);
|
|
2656
|
+
app.config.modules[module.info.relativeName] = deepExtend({}, configModule, app.config.modules[module.info.relativeName]);
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
function loadConstants (app, modules) {
|
|
2663
|
+
// all constants
|
|
2664
|
+
const ebConstants = app.meta.constants = {};
|
|
2665
|
+
|
|
2666
|
+
// load constants
|
|
2667
|
+
loadConstants();
|
|
2668
|
+
function loadConstants() {
|
|
2669
|
+
for (const key in modules) {
|
|
2670
|
+
const module = modules[key];
|
|
2671
|
+
const ebConstant = ebConstants[module.info.relativeName] = {};
|
|
2672
|
+
|
|
2673
|
+
// module constants
|
|
2674
|
+
if (module.resource.constants) deepExtend(ebConstant, module.resource.constants);
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
function loadErrors (app, modules) {
|
|
2680
|
+
// all errors
|
|
2681
|
+
const ebErrors = {};
|
|
2682
|
+
|
|
2683
|
+
// load errors
|
|
2684
|
+
loadErrors();
|
|
2685
|
+
|
|
2686
|
+
// patch Error
|
|
2687
|
+
patchError();
|
|
2688
|
+
function patchError() {
|
|
2689
|
+
// error
|
|
2690
|
+
app.meta.error = app.bean._newBean(ErrorClass, ebErrors);
|
|
2691
|
+
|
|
2692
|
+
// methods
|
|
2693
|
+
['success', 'fail', 'throw', 'parseFail', 'parseSuccess', 'parseCode'].forEach(key => {
|
|
2694
|
+
app[key] = function (...args) {
|
|
2695
|
+
return app.meta.error[key](undefined, ...args);
|
|
2696
|
+
};
|
|
2697
|
+
});
|
|
2698
|
+
}
|
|
2699
|
+
function loadErrors() {
|
|
2700
|
+
for (const key in modules) {
|
|
2701
|
+
const module = modules[key];
|
|
2702
|
+
const ebError = ebErrors[module.info.relativeName] = {};
|
|
2703
|
+
|
|
2704
|
+
// module errors
|
|
2705
|
+
if (module.resource.errors) deepExtend(ebError, module.resource.errors);
|
|
2706
|
+
}
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
|
|
2710
|
+
async function loadLocales (app, modules) {
|
|
2711
|
+
// all locales
|
|
2712
|
+
app.meta.locales = localesDefault;
|
|
2713
|
+
app.meta.localeModules = {};
|
|
2714
|
+
|
|
2715
|
+
// load locales
|
|
2716
|
+
await loadLocales();
|
|
2717
|
+
async function loadLocales() {
|
|
2718
|
+
const locales = (await app.options.locales()).locales;
|
|
2719
|
+
// project locales
|
|
2720
|
+
for (const locale in locales) {
|
|
2721
|
+
_initLocales(locale, locales[locale]);
|
|
2722
|
+
}
|
|
2723
|
+
// app cache
|
|
2724
|
+
app.meta.hmrCacheLocaleModules = deepExtend({}, app.meta.localeModules);
|
|
2725
|
+
// module locales
|
|
2726
|
+
for (const moduleName in modules) {
|
|
2727
|
+
const module = modules[moduleName];
|
|
2728
|
+
_registerLocales(moduleName, module.resource.locales);
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
function _initLocales(locale, locales) {
|
|
2732
|
+
if (!locales) return;
|
|
2733
|
+
if (!locales.modules) {
|
|
2734
|
+
// override
|
|
2735
|
+
app.meta.locales[locale] = Object.assign({}, app.meta.locales[locale], locales);
|
|
2736
|
+
} else {
|
|
2737
|
+
const moduleMap = locales.modules;
|
|
2738
|
+
for (const moduleName in moduleMap) {
|
|
2739
|
+
_registerLocale(moduleName, locale, moduleMap[moduleName]);
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
function _registerLocales(moduleName, locales) {
|
|
2744
|
+
if (!locales) return;
|
|
2745
|
+
for (const locale in locales) {
|
|
2746
|
+
_registerLocale(moduleName, locale, locales[locale]);
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
function _registerLocale(moduleName, locale, moduleLocales) {
|
|
2750
|
+
// locales: not override
|
|
2751
|
+
app.meta.locales[locale] = Object.assign({}, moduleLocales, app.meta.locales[locale]);
|
|
2752
|
+
// localeModules
|
|
2753
|
+
if (!app.meta.localeModules[moduleName]) app.meta.localeModules[moduleName] = {};
|
|
2754
|
+
app.meta.localeModules[moduleName][locale] = Object.assign({}, moduleLocales, app.meta.localeModules[moduleName][locale]);
|
|
2755
|
+
}
|
|
2756
|
+
}
|
|
2757
|
+
|
|
2758
|
+
class ModuleTools extends BeanSimple {
|
|
2759
|
+
async prepare() {
|
|
2760
|
+
const app = this.app;
|
|
2761
|
+
const modulesMeta = await app.options.modulesMeta();
|
|
2762
|
+
const modules = modulesMeta.modulesMeta.modules;
|
|
2763
|
+
const modulesArray = modulesMeta.modulesMeta.moduleNames.map(relativeName => modules[relativeName]);
|
|
2764
|
+
app.meta.modules = modules;
|
|
2765
|
+
app.meta.modulesArray = modulesArray;
|
|
2766
|
+
app.meta.modulesMonkey = {};
|
|
2767
|
+
return modules;
|
|
2768
|
+
}
|
|
2769
|
+
async load() {
|
|
2770
|
+
const app = this.app;
|
|
2771
|
+
// main / monkey
|
|
2772
|
+
for (const module of app.meta.modulesArray) {
|
|
2773
|
+
if (module.resource.Main) {
|
|
2774
|
+
module.mainInstance = app.bean._newBean(module.resource.Main, module);
|
|
2775
|
+
}
|
|
2776
|
+
if (module.resource.Monkey) {
|
|
2777
|
+
module.monkeyInstance = app.bean._newBean(module.resource.Monkey, module);
|
|
2778
|
+
app.meta.modulesMonkey[module.info.relativeName] = module;
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
}
|
|
2782
|
+
async monkey(monkeyName) {
|
|
2783
|
+
const app = this.app;
|
|
2784
|
+
for (const module of app.meta.modulesArray) {
|
|
2785
|
+
await app.util.monkeyModule(app.meta.appMonkey, app.meta.modulesMonkey, monkeyName, module);
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
|
|
2790
|
+
class ModuleLoader extends BeanSimple {
|
|
2791
|
+
async execute() {
|
|
2792
|
+
const app = this.app;
|
|
2793
|
+
// modules
|
|
2794
|
+
const moduleTools = app.bean._newBean(ModuleTools);
|
|
2795
|
+
// prepare
|
|
2796
|
+
const modules = await moduleTools.prepare();
|
|
2797
|
+
// load modules
|
|
2798
|
+
await moduleTools.load();
|
|
2799
|
+
// monkey modules
|
|
2800
|
+
await moduleTools.monkey('moduleLoading');
|
|
2801
|
+
await loadConfig(app, modules);
|
|
2802
|
+
await loadLocales(app, modules);
|
|
2803
|
+
loadErrors(app, modules);
|
|
2804
|
+
loadConstants(app, modules);
|
|
2805
|
+
|
|
2806
|
+
// monkey modules
|
|
2807
|
+
await moduleTools.monkey('moduleLoaded');
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
class Start {
|
|
2812
|
+
constructor(app) {
|
|
2813
|
+
this.app = void 0;
|
|
2814
|
+
this.app = app;
|
|
2815
|
+
}
|
|
2816
|
+
async start() {
|
|
2817
|
+
const app = this.app;
|
|
2818
|
+
try {
|
|
2819
|
+
await this._start_appConfig();
|
|
2820
|
+
await this._start_appLoad();
|
|
2821
|
+
await this._start_appStart();
|
|
2822
|
+
await this._start_appReady();
|
|
2823
|
+
await this._start_appStarted();
|
|
2824
|
+
} catch (err) {
|
|
2825
|
+
// record
|
|
2826
|
+
app.meta.appStartError = err;
|
|
2827
|
+
// event: appReadyError
|
|
2828
|
+
app.emit(EnumAppEvent.AppStartError, err);
|
|
2829
|
+
// throw exception
|
|
2830
|
+
throw err;
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
async _start_appLoad() {
|
|
2834
|
+
const app = this.app;
|
|
2835
|
+
// module loader
|
|
2836
|
+
const moduleLoader = app.bean._newBean(ModuleLoader);
|
|
2837
|
+
await moduleLoader.execute();
|
|
2838
|
+
}
|
|
2839
|
+
async _start_appStart() {
|
|
2840
|
+
const app = this.app;
|
|
2841
|
+
// hook: appStart
|
|
2842
|
+
await app.util.monkeyModule(app.meta.appMonkey, app.meta.modulesMonkey, 'appStart');
|
|
2843
|
+
}
|
|
2844
|
+
async _start_appReady() {
|
|
2845
|
+
const app = this.app;
|
|
2846
|
+
app.meta.appReady = true;
|
|
2847
|
+
app.meta.appReadyInstances = {};
|
|
2848
|
+
// hook: appReady
|
|
2849
|
+
await app.util.monkeyModule(app.meta.appMonkey, app.meta.modulesMonkey, 'appReady');
|
|
2850
|
+
}
|
|
2851
|
+
async _start_appStarted() {
|
|
2852
|
+
const app = this.app;
|
|
2853
|
+
app.meta.appStarted = true;
|
|
2854
|
+
// event: appStarted
|
|
2855
|
+
app.emit(EnumAppEvent.AppStarted);
|
|
2856
|
+
// hook: appStarted
|
|
2857
|
+
await app.util.monkeyModule(app.meta.appMonkey, app.meta.modulesMonkey, 'appStarted');
|
|
2858
|
+
}
|
|
2859
|
+
async _start_appConfig() {
|
|
2860
|
+
const app = this.app;
|
|
2861
|
+
// config
|
|
2862
|
+
const appConfig = await __prepareConfig(app);
|
|
2863
|
+
this.app.config = appConfig;
|
|
2864
|
+
this.app.keys = appConfig.server.keys;
|
|
2865
|
+
this.app.proxy = appConfig.proxy.enable;
|
|
2866
|
+
this.app.subdomainOffset = appConfig.server.subdomainOffset;
|
|
2867
|
+
this.app.proxyIpHeader = appConfig.proxy.ipHeaders;
|
|
2868
|
+
this.app.maxIpsCount = appConfig.proxy.maxIpsCount;
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
async function __prepareConfig(app) {
|
|
2872
|
+
const config = {};
|
|
2873
|
+
const configItems = (await app.options.config()).default;
|
|
2874
|
+
const configItemsPromise = [];
|
|
2875
|
+
for (const configItem of configItems) {
|
|
2876
|
+
configItemsPromise.push(configItem(app, app.options.env));
|
|
2877
|
+
}
|
|
2878
|
+
const configItemsRes = await Promise.all(configItemsPromise);
|
|
2879
|
+
for (const configItem of configItemsRes) {
|
|
2880
|
+
if (configItem) {
|
|
2881
|
+
deepExtend(config, configItem);
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
return config;
|
|
2885
|
+
}
|
|
2886
|
+
|
|
2887
|
+
async function createAppMaster(bootstrapOptions) {
|
|
2888
|
+
globalThis.__bootstrapOptions__ = bootstrapOptions;
|
|
2889
|
+
const {
|
|
2890
|
+
modulesMeta,
|
|
2891
|
+
locales,
|
|
2892
|
+
config,
|
|
2893
|
+
env,
|
|
2894
|
+
AppMonkey
|
|
2895
|
+
} = bootstrapOptions;
|
|
2896
|
+
globalThis.__app__ = __createApp({
|
|
2897
|
+
modulesMeta,
|
|
2898
|
+
locales,
|
|
2899
|
+
config,
|
|
2900
|
+
env,
|
|
2901
|
+
AppMonkey
|
|
2902
|
+
});
|
|
2903
|
+
}
|
|
2904
|
+
async function createApp(bootstrapOptions) {
|
|
2905
|
+
while (globalThis.__creating__) {
|
|
2906
|
+
await sleep(100);
|
|
2907
|
+
}
|
|
2908
|
+
try {
|
|
2909
|
+
globalThis.__creating__ = true;
|
|
2910
|
+
globalThis.__bootstrapOptions__ = bootstrapOptions;
|
|
2911
|
+
const {
|
|
2912
|
+
modulesMeta,
|
|
2913
|
+
locales,
|
|
2914
|
+
config,
|
|
2915
|
+
env,
|
|
2916
|
+
AppMonkey
|
|
2917
|
+
} = bootstrapOptions;
|
|
2918
|
+
if (!globalThis.__app__) {
|
|
2919
|
+
globalThis.__app__ = __createApp({
|
|
2920
|
+
modulesMeta,
|
|
2921
|
+
locales,
|
|
2922
|
+
config,
|
|
2923
|
+
env,
|
|
2924
|
+
AppMonkey
|
|
2925
|
+
});
|
|
2926
|
+
const start = new Start(globalThis.__app__);
|
|
2927
|
+
await start.start();
|
|
2928
|
+
}
|
|
2929
|
+
await globalThis.__app__.meta.waitAppStarted();
|
|
2930
|
+
return globalThis.__app__;
|
|
2931
|
+
} finally {
|
|
2932
|
+
globalThis.__creating__ = false;
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
function __createApp({
|
|
2936
|
+
modulesMeta,
|
|
2937
|
+
locales,
|
|
2938
|
+
config,
|
|
2939
|
+
env,
|
|
2940
|
+
AppMonkey
|
|
2941
|
+
}) {
|
|
2942
|
+
// patch zod, should before config
|
|
2943
|
+
zodEnhance();
|
|
2944
|
+
// env
|
|
2945
|
+
const env2 = prepareEnv(env);
|
|
2946
|
+
// appInfo
|
|
2947
|
+
const appInfo = prepareAppInfo(env2);
|
|
2948
|
+
// options
|
|
2949
|
+
const options = {
|
|
2950
|
+
name: appInfo.name,
|
|
2951
|
+
projectPath: appInfo.projectPath,
|
|
2952
|
+
configMeta: appInfo.configMeta,
|
|
2953
|
+
modulesMeta,
|
|
2954
|
+
locales,
|
|
2955
|
+
config,
|
|
2956
|
+
env: env2,
|
|
2957
|
+
AppMonkey
|
|
2958
|
+
};
|
|
2959
|
+
return new VonaApplication(options);
|
|
2960
|
+
}
|
|
2961
|
+
function prepareAppInfo(env) {
|
|
2962
|
+
return {
|
|
2963
|
+
name: env.APP_NAME,
|
|
2964
|
+
projectPath: process.cwd(),
|
|
2965
|
+
configMeta: {
|
|
2966
|
+
flavor: cast(env).META_FLAVOR,
|
|
2967
|
+
mode: cast(env).META_MODE
|
|
2968
|
+
}
|
|
2969
|
+
};
|
|
2970
|
+
}
|
|
2971
|
+
|
|
2972
|
+
function handleProcessWork() {
|
|
2973
|
+
process.once('SIGUSR2', async () => {
|
|
2974
|
+
// console.log('------------SIGUSR2');
|
|
2975
|
+
await closeApp(true);
|
|
2976
|
+
});
|
|
2977
|
+
process.once('SIGINT', async () => {
|
|
2978
|
+
// console.log('------------SIGINT');
|
|
2979
|
+
await closeApp(true);
|
|
2980
|
+
});
|
|
2981
|
+
process.on('uncaughtException', async err => {
|
|
2982
|
+
const app = useApp();
|
|
2983
|
+
if (!app) {
|
|
2984
|
+
console.error(err);
|
|
2985
|
+
process.kill(process.pid, 'SIGTERM');
|
|
2986
|
+
} else {
|
|
2987
|
+
const [logger] = catchErrorSync(() => {
|
|
2988
|
+
return app.meta.logger.get();
|
|
2989
|
+
});
|
|
2990
|
+
if (logger) {
|
|
2991
|
+
logger.error(err);
|
|
2992
|
+
} else {
|
|
2993
|
+
console.error(err);
|
|
2994
|
+
}
|
|
2995
|
+
if (!app.meta.appStarted) {
|
|
2996
|
+
await app.meta.logger.dispose();
|
|
2997
|
+
process.kill(process.pid, 'SIGTERM');
|
|
2998
|
+
}
|
|
2999
|
+
}
|
|
3000
|
+
});
|
|
3001
|
+
}
|
|
3002
|
+
function handleProcessMaster() {
|
|
3003
|
+
process.once('SIGUSR2', () => {
|
|
3004
|
+
// should not kill master self by manual
|
|
3005
|
+
// process.kill(process.pid, 'SIGTERM');
|
|
3006
|
+
});
|
|
3007
|
+
// should not kill master self by manual
|
|
3008
|
+
// process.once('SIGINT', () => {
|
|
3009
|
+
// process.kill(process.pid, 'SIGTERM');
|
|
3010
|
+
// });
|
|
3011
|
+
}
|
|
3012
|
+
|
|
3013
|
+
async function startCluster(workers, bootstrapOptions) {
|
|
3014
|
+
if (cluster.isPrimary) {
|
|
3015
|
+
handleProcessMaster();
|
|
3016
|
+
createAppMaster(bootstrapOptions);
|
|
3017
|
+
|
|
3018
|
+
// console.log(`Primary ${process.pid} is running`);
|
|
3019
|
+
|
|
3020
|
+
// Fork workers.
|
|
3021
|
+
for (let i = 0; i < workers; i++) {
|
|
3022
|
+
cluster.fork();
|
|
3023
|
+
}
|
|
3024
|
+
cluster.on('message', (worker, message) => {
|
|
3025
|
+
if (message === 'reload-worker') {
|
|
3026
|
+
worker.process.kill('SIGTERM');
|
|
3027
|
+
cluster.fork();
|
|
3028
|
+
}
|
|
3029
|
+
});
|
|
3030
|
+
cluster.on('exit', (_worker, _code, _signal) => {
|
|
3031
|
+
// console.log(`worker ${worker.process.pid} died`, code, signal);
|
|
3032
|
+
// should not kill master self by manual
|
|
3033
|
+
// master -> worker, rather than worker -> master
|
|
3034
|
+
// if (cluster.workers && Object.keys(cluster.workers).length === 0) {
|
|
3035
|
+
// process.kill(process.pid, 'SIGTERM');
|
|
3036
|
+
// }
|
|
3037
|
+
});
|
|
3038
|
+
} else {
|
|
3039
|
+
handleProcessWork();
|
|
3040
|
+
await createApp(bootstrapOptions);
|
|
3041
|
+
// console.log(`Worker ${process.pid} started`);
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
async function bootstrap(bootstrapOptions) {
|
|
3046
|
+
const env = prepareEnv(bootstrapOptions.env);
|
|
3047
|
+
const workers = Number.parseInt(env.SERVER_WORKERS);
|
|
3048
|
+
if (workers === 1 && process.env.META_MODE !== 'dev') {
|
|
3049
|
+
handleProcessWork();
|
|
3050
|
+
return await createApp(bootstrapOptions);
|
|
3051
|
+
}
|
|
3052
|
+
await startCluster(workers, bootstrapOptions);
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3055
|
+
function ExtendClass(classRef) {
|
|
3056
|
+
appHmrDeps.addBean(classRef);
|
|
3057
|
+
return classRef;
|
|
3058
|
+
}
|
|
3059
|
+
|
|
3060
|
+
function MixinClass(...classRefs) {
|
|
3061
|
+
appHmrDeps.addBeans(classRefs);
|
|
3062
|
+
class TargetClass {}
|
|
3063
|
+
copyMetadataOfClasses(TargetClass.prototype, classRefs.map(item => item.prototype));
|
|
3064
|
+
copyPropertiesOfClasses(TargetClass, classRefs);
|
|
3065
|
+
return TargetClass;
|
|
3066
|
+
}
|
|
3067
|
+
|
|
3068
|
+
function OmitClass(classRef, keys) {
|
|
3069
|
+
appHmrDeps.addBean(classRef);
|
|
3070
|
+
class TargetClass {}
|
|
3071
|
+
copyMetadataOfClasses(TargetClass.prototype, [classRef.prototype], (rules, key) => {
|
|
3072
|
+
if (!keys.includes(key)) {
|
|
3073
|
+
return rules[key];
|
|
3074
|
+
}
|
|
3075
|
+
});
|
|
3076
|
+
copyPropertiesOfClasses(TargetClass, [classRef], key => {
|
|
3077
|
+
return !keys.includes(key);
|
|
3078
|
+
});
|
|
3079
|
+
return TargetClass;
|
|
3080
|
+
}
|
|
3081
|
+
|
|
3082
|
+
function PartialClass(classRef, keys) {
|
|
3083
|
+
appHmrDeps.addBean(classRef);
|
|
3084
|
+
class TargetClass {}
|
|
3085
|
+
copyMetadataOfClasses(TargetClass.prototype, [classRef.prototype], (rules, key, metadataKeyOptions) => {
|
|
3086
|
+
const schema = rules[key];
|
|
3087
|
+
if (keys && !keys.includes(key)) return schema;
|
|
3088
|
+
if (metadataKeyOptions?.partialClass) {
|
|
3089
|
+
return metadataKeyOptions?.partialClass(schema);
|
|
3090
|
+
}
|
|
3091
|
+
return schema;
|
|
3092
|
+
});
|
|
3093
|
+
copyPropertiesOfClasses(TargetClass, [classRef]);
|
|
3094
|
+
return TargetClass;
|
|
3095
|
+
}
|
|
3096
|
+
|
|
3097
|
+
function PickClassInner(classTarget, classRef, keys) {
|
|
3098
|
+
copyMetadataOfClasses(classTarget.prototype, [classRef.prototype], (rules, key) => {
|
|
3099
|
+
if (!keys || keys.includes(key)) {
|
|
3100
|
+
return rules[key];
|
|
3101
|
+
}
|
|
3102
|
+
});
|
|
3103
|
+
copyPropertiesOfClasses(classTarget, [classRef], key => {
|
|
3104
|
+
return !keys || keys.includes(key);
|
|
3105
|
+
});
|
|
3106
|
+
return classTarget;
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
function PickClass(classRef, keys) {
|
|
3110
|
+
appHmrDeps.addBean(classRef);
|
|
3111
|
+
class TargetClass {}
|
|
3112
|
+
return PickClassInner(TargetClass, classRef, keys);
|
|
3113
|
+
}
|
|
3114
|
+
|
|
3115
|
+
const $Class = {
|
|
3116
|
+
extend: ExtendClass,
|
|
3117
|
+
mixin: MixinClass,
|
|
3118
|
+
omit: OmitClass,
|
|
3119
|
+
partial: PartialClass,
|
|
3120
|
+
pick: PickClass
|
|
3121
|
+
};
|
|
3122
|
+
|
|
3123
|
+
function zodExtendOpenApi() {
|
|
3124
|
+
extendZodWithOpenApi(z);
|
|
3125
|
+
const openapiOriginal = z.ZodType.prototype.openapi;
|
|
3126
|
+
z.ZodType.prototype.openapi = function (...args) {
|
|
3127
|
+
// refId
|
|
3128
|
+
if (typeof args[0] === 'string') return openapiOriginal.call(this, ...args);
|
|
3129
|
+
const refId = ZodMetadata.getRefId(this);
|
|
3130
|
+
if (!refId) return openapiOriginal.call(this, ...args);
|
|
3131
|
+
// metadata
|
|
3132
|
+
const metadata = args[0];
|
|
3133
|
+
if (isEmptyObject(metadata)) {
|
|
3134
|
+
return this;
|
|
3135
|
+
// return openapiOriginal.call(this, ...args);
|
|
3136
|
+
}
|
|
3137
|
+
const options = args[1];
|
|
3138
|
+
// refId: update
|
|
3139
|
+
const refIdNew = `${refId}_${hashkey(metadata)}`;
|
|
3140
|
+
const metadataOld = ZodMetadata.getOpenapiMetadata(this);
|
|
3141
|
+
const metadataNew = deepExtend({}, metadataOld, metadata);
|
|
3142
|
+
return openapiOriginal.call(this, refIdNew, metadataNew, options);
|
|
3143
|
+
};
|
|
3144
|
+
}
|
|
3145
|
+
|
|
3146
|
+
function $customKey(key) {
|
|
3147
|
+
return key;
|
|
3148
|
+
}
|
|
3149
|
+
|
|
3150
|
+
async function retry(options, fn) {
|
|
3151
|
+
return new Promise((resolve, reject) => {
|
|
3152
|
+
const operation = Retry.operation(options);
|
|
3153
|
+
operation.attempt(currentAttempt => {
|
|
3154
|
+
fn(currentAttempt).then(data => resolve(data)).catch(err => {
|
|
3155
|
+
if (operation.retry(err)) return;
|
|
3156
|
+
reject(err);
|
|
3157
|
+
});
|
|
3158
|
+
});
|
|
3159
|
+
});
|
|
3160
|
+
}
|
|
3161
|
+
|
|
3162
|
+
function getSqlite3DatabaseNameDefault(app) {
|
|
3163
|
+
const mode = app.configMeta.mode;
|
|
3164
|
+
if (mode !== 'prod') return '';
|
|
3165
|
+
const dbPath = path.join(os.homedir(), 'vona', app.name, 'sqlite3');
|
|
3166
|
+
fse.ensureDirSync(dbPath);
|
|
3167
|
+
return path.join(dbPath, `${app.name}.db`);
|
|
3168
|
+
}
|
|
3169
|
+
|
|
3170
|
+
// string/true/false
|
|
3171
|
+
function getSqlite3NativeBinding(_app, nativeBinding) {
|
|
3172
|
+
nativeBinding = prepareNativeBinding(nativeBinding);
|
|
3173
|
+
if (!nativeBinding) return nativeBinding;
|
|
3174
|
+
const nativeBindingPath = path.isAbsolute(nativeBinding) ? nativeBinding : path.join(import.meta.dirname, nativeBinding);
|
|
3175
|
+
const require = createRequire(import.meta.url);
|
|
3176
|
+
const addon = require(nativeBindingPath);
|
|
3177
|
+
return addon;
|
|
3178
|
+
}
|
|
3179
|
+
async function copySqlite3NativeBinding(projectPath, outDir, env) {
|
|
3180
|
+
// dest
|
|
3181
|
+
const nativeBinding = prepareNativeBinding(env.DATABASE_CLIENT_SQLITE3_NATIVEBINDING);
|
|
3182
|
+
if (!nativeBinding || path.isAbsolute(nativeBinding)) return;
|
|
3183
|
+
const fileDest = path.join(outDir, nativeBinding);
|
|
3184
|
+
// src
|
|
3185
|
+
const require = createRequire(pathToHref(path.join(projectPath, '/')));
|
|
3186
|
+
const modulePath = require.resolve('better-sqlite3/package.json');
|
|
3187
|
+
const fileSrc = path.join(path.dirname(modulePath), 'build/Release/better_sqlite3.node');
|
|
3188
|
+
// copy
|
|
3189
|
+
await fse.copy(fileSrc, fileDest);
|
|
3190
|
+
}
|
|
3191
|
+
function prepareNativeBinding(nativeBinding) {
|
|
3192
|
+
if (!nativeBinding || nativeBinding === 'false') return null;
|
|
3193
|
+
return nativeBinding === 'true' ? 'node/better_sqlite3.node' : nativeBinding;
|
|
3194
|
+
}
|
|
3195
|
+
|
|
3196
|
+
zodExtendOpenApi();
|
|
3197
|
+
|
|
3198
|
+
export { $Class, $customKey, $localeScope, AppHmr, AppHmrDeps, AppLocale, AppLogger, AppMeta, AppMetadata, AppResource, AppUtil, BeanAopBase, BeanAopMethodBase, BeanBase, BeanBaseSimple, BeanContainer, BeanInfo, BeanScopeBase, BeanScopeContainer, BeanScopeError, BeanScopeErrorImpl, BeanScopeLocale, BeanScopeScene, BeanScopeUtil, BeanSimple, EnumAppEvent, ErrorClass, LocaleModuleNameSeparator, PickClassInner, ProxyDisable, SymbolBeanContainerInstances, SymbolBeanFullName, SymbolBeanInstanceKey, SymbolBeanInstancePropsLazy, SymbolCacheAopChains, SymbolCacheAopChainsKey, SymbolDecoratorBeanFullName, SymbolDecoratorBeanInfo, SymbolDecoratorProxyDisable, SymbolDecoratorUse, SymbolDecoratorVirtual, SymbolHmrStateLoad, SymbolHmrStateSave, SymbolMappedClassMetadataKeys, SymbolModuleBelong, SymbolModuleName, Use, Virtual, VonaApplication, __prepareInjectSelectorInfo, appHmrDeps, appMetadata, appResource, beanFullNameFromOnionName, bootstrap, cast, closeApp, combineConfigDefault, combineFilePathSafe, compose, copyMetadataOfClasses, copyProperties, copyPropertiesOfClasses, copySqlite3NativeBinding, createApp, createAppMaster, createBeanDecorator, createGeneralApp, createHash, deepExtend, disposeInstance, errorsInternal, filterHeaders, formatLoggerAxiosError, formatLoggerConsole, formatLoggerCtx, formatLoggerDummy, formatLoggerFilter, functionNoop, getLoggerPathPhysicalRoot, getMappedClassMetadataKeys, getPublicPathPhysicalRoot, getRuntimePathPhysicalRoot, getSqlite3DatabaseNameDefault, getSqlite3NativeBinding, handleProcessMaster, handleProcessWork, instanceDesp, loadJSONFile, localeDefault, onionNameFromBeanFullName, pathToHref, polyfillDispose, prepareEnv, registerMappedClassMetadataKey, requireDynamic, retry, saveJSONFile, setMappedClassMetadataKeys, useApp, usePrepareArg, usePrepareArgs, uuidv4 };
|