koatty 3.10.4-0 → 3.10.4-2
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/.vscode/settings.json +5 -0
- package/CHANGELOG.md +4 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +982 -985
- package/dist/index.mjs +977 -980
- package/dist/package.json +19 -15
- package/package.json +19 -15
package/dist/index.js
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
/*!
|
2
2
|
* @Author: richen
|
3
|
-
* @Date: 2023-12-
|
3
|
+
* @Date: 2023-12-15 00:18:46
|
4
4
|
* @License: BSD (3-Clause)
|
5
5
|
* @Copyright (c) - <richenlin(at)gmail.com>
|
6
6
|
* @HomePage: https://koatty.org/
|
7
7
|
*/
|
8
8
|
'use strict';
|
9
9
|
|
10
|
-
require('reflect-metadata');
|
11
10
|
var koatty_core = require('koatty_core');
|
12
11
|
var path = require('path');
|
13
12
|
var koatty_loader = require('koatty_loader');
|
@@ -18,6 +17,7 @@ var koatty_exception = require('koatty_exception');
|
|
18
17
|
var koatty_container = require('koatty_container');
|
19
18
|
var koatty_trace = require('koatty_trace');
|
20
19
|
var koatty_serve = require('koatty_serve');
|
20
|
+
require('reflect-metadata');
|
21
21
|
|
22
22
|
function _interopNamespaceDefault(e) {
|
23
23
|
var n = Object.create(null);
|
@@ -38,129 +38,129 @@ function _interopNamespaceDefault(e) {
|
|
38
38
|
|
39
39
|
var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path);
|
40
40
|
|
41
|
-
/*
|
42
|
-
* @Description: framework logger
|
43
|
-
* @Usage:
|
44
|
-
* @Author: richen
|
45
|
-
* @Date: 2023-12-09 21:56:32
|
46
|
-
* @LastEditTime: 2023-12-09 23:02:27
|
47
|
-
* @License: BSD (3-Clause)
|
48
|
-
* @Copyright (c): <richenlin(at)gmail.com>
|
49
|
-
*/
|
50
|
-
// Logger
|
51
|
-
const Logger = koatty_logger.DefaultLogger;
|
52
|
-
/**
|
53
|
-
* SetLogger
|
54
|
-
*
|
55
|
-
* @export
|
56
|
-
* @param {{
|
57
|
-
* logLevel?: LogLevelType;
|
58
|
-
* logFilePath?: string;
|
59
|
-
* sensFields?: string[];
|
60
|
-
* }} config
|
61
|
-
*/
|
62
|
-
function SetLogger(app, config) {
|
63
|
-
if (config.logLevel) {
|
64
|
-
koatty_logger.DefaultLogger.setLevel(config.logLevel);
|
65
|
-
}
|
66
|
-
if (config.logFilePath && !app.silent) {
|
67
|
-
koatty_lib.Helper.define(app, "logsPath", config.logFilePath);
|
68
|
-
process.env.LOGS_PATH = config.logFilePath;
|
69
|
-
koatty_logger.DefaultLogger.setLogFilePath(config.logFilePath);
|
70
|
-
}
|
71
|
-
if (config.sensFields) {
|
72
|
-
koatty_logger.DefaultLogger.setSensFields(config.sensFields);
|
73
|
-
}
|
41
|
+
/*
|
42
|
+
* @Description: framework logger
|
43
|
+
* @Usage:
|
44
|
+
* @Author: richen
|
45
|
+
* @Date: 2023-12-09 21:56:32
|
46
|
+
* @LastEditTime: 2023-12-09 23:02:27
|
47
|
+
* @License: BSD (3-Clause)
|
48
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
49
|
+
*/
|
50
|
+
// Logger
|
51
|
+
const Logger = koatty_logger.DefaultLogger;
|
52
|
+
/**
|
53
|
+
* SetLogger
|
54
|
+
*
|
55
|
+
* @export
|
56
|
+
* @param {{
|
57
|
+
* logLevel?: LogLevelType;
|
58
|
+
* logFilePath?: string;
|
59
|
+
* sensFields?: string[];
|
60
|
+
* }} config
|
61
|
+
*/
|
62
|
+
function SetLogger(app, config) {
|
63
|
+
if (config.logLevel) {
|
64
|
+
koatty_logger.DefaultLogger.setLevel(config.logLevel);
|
65
|
+
}
|
66
|
+
if (config.logFilePath && !app.silent) {
|
67
|
+
koatty_lib.Helper.define(app, "logsPath", config.logFilePath);
|
68
|
+
process.env.LOGS_PATH = config.logFilePath;
|
69
|
+
koatty_logger.DefaultLogger.setLogFilePath(config.logFilePath);
|
70
|
+
}
|
71
|
+
if (config.sensFields) {
|
72
|
+
koatty_logger.DefaultLogger.setSensFields(config.sensFields);
|
73
|
+
}
|
74
74
|
}
|
75
75
|
|
76
|
-
/*
|
77
|
-
* @Description: framework helper
|
78
|
-
* @Usage:
|
79
|
-
* @Author: richen
|
80
|
-
* @Date: 2023-12-09 21:56:32
|
81
|
-
* @LastEditTime: 2023-12-09 23:01:56
|
82
|
-
* @License: BSD (3-Clause)
|
83
|
-
* @Copyright (c): <richenlin(at)gmail.com>
|
84
|
-
*/
|
85
|
-
/**
|
86
|
-
* Check class file
|
87
|
-
* name should be always the same as class name
|
88
|
-
* class must be unique
|
89
|
-
*
|
90
|
-
* @export
|
91
|
-
* @param {string} fileName
|
92
|
-
* @param {string} xpath
|
93
|
-
* @param {*} target
|
94
|
-
* @param {Set<unknown>} [exSet]
|
95
|
-
* @returns {*}
|
96
|
-
*/
|
97
|
-
function checkClass(fileName, xpath, target, exSet) {
|
98
|
-
if (koatty_lib.Helper.isClass(target) && target.name != fileName) { // export default class name{}
|
99
|
-
throw Error(`The file(${xpath}) name should be always the same as class name.`);
|
100
|
-
}
|
101
|
-
if (target["__esModule"]) {
|
102
|
-
if (target.name === undefined) { // export class name{}
|
103
|
-
const keys = Object.keys(target);
|
104
|
-
if (keys[0] != fileName && koatty_lib.Helper.isClass(target[keys[0]])) {
|
105
|
-
throw Error(`The file(${xpath}) name should be always the same as class name.`);
|
106
|
-
}
|
107
|
-
}
|
108
|
-
else if (target.name != fileName) { // export default class {}
|
109
|
-
throw Error(`The file(${xpath}) name should be always the same as class name.`);
|
110
|
-
}
|
111
|
-
}
|
112
|
-
if (!exSet) {
|
113
|
-
return;
|
114
|
-
}
|
115
|
-
if (exSet.has(fileName)) {
|
116
|
-
throw new Error(`A same class already exists. at \`${xpath}\`.`);
|
117
|
-
}
|
118
|
-
exSet.add(fileName);
|
119
|
-
return;
|
120
|
-
}
|
121
|
-
/**
|
122
|
-
* Format api interface data format
|
123
|
-
*
|
124
|
-
* @private
|
125
|
-
* @param {Error | string | ApiInput} msg 待处理的接口数据信息|接口msg
|
126
|
-
* @param {*} data 待返回的数据
|
127
|
-
* @param {number} defaultCode 默认错误码
|
128
|
-
* @returns {ApiOutput} 格式化之后的接口数据
|
129
|
-
* @memberof BaseController
|
130
|
-
*/
|
131
|
-
function formatApiData(msg, data, defaultCode) {
|
132
|
-
let obj = {
|
133
|
-
code: defaultCode,
|
134
|
-
message: '',
|
135
|
-
data: null,
|
136
|
-
};
|
137
|
-
if (koatty_lib.Helper.isError(msg)) {
|
138
|
-
const { code, message } = msg;
|
139
|
-
obj.code = code || defaultCode;
|
140
|
-
obj.message = message;
|
141
|
-
}
|
142
|
-
else if (koatty_lib.Helper.isObject(msg)) {
|
143
|
-
obj = { ...obj, ...msg };
|
144
|
-
}
|
145
|
-
else {
|
146
|
-
obj.message = msg;
|
147
|
-
obj.data = data;
|
148
|
-
}
|
149
|
-
return obj;
|
76
|
+
/*
|
77
|
+
* @Description: framework helper
|
78
|
+
* @Usage:
|
79
|
+
* @Author: richen
|
80
|
+
* @Date: 2023-12-09 21:56:32
|
81
|
+
* @LastEditTime: 2023-12-09 23:01:56
|
82
|
+
* @License: BSD (3-Clause)
|
83
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
84
|
+
*/
|
85
|
+
/**
|
86
|
+
* Check class file
|
87
|
+
* name should be always the same as class name
|
88
|
+
* class must be unique
|
89
|
+
*
|
90
|
+
* @export
|
91
|
+
* @param {string} fileName
|
92
|
+
* @param {string} xpath
|
93
|
+
* @param {*} target
|
94
|
+
* @param {Set<unknown>} [exSet]
|
95
|
+
* @returns {*}
|
96
|
+
*/
|
97
|
+
function checkClass(fileName, xpath, target, exSet) {
|
98
|
+
if (koatty_lib.Helper.isClass(target) && target.name != fileName) { // export default class name{}
|
99
|
+
throw Error(`The file(${xpath}) name should be always the same as class name.`);
|
100
|
+
}
|
101
|
+
if (target["__esModule"]) {
|
102
|
+
if (target.name === undefined) { // export class name{}
|
103
|
+
const keys = Object.keys(target);
|
104
|
+
if (keys[0] != fileName && koatty_lib.Helper.isClass(target[keys[0]])) {
|
105
|
+
throw Error(`The file(${xpath}) name should be always the same as class name.`);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
else if (target.name != fileName) { // export default class {}
|
109
|
+
throw Error(`The file(${xpath}) name should be always the same as class name.`);
|
110
|
+
}
|
111
|
+
}
|
112
|
+
if (!exSet) {
|
113
|
+
return;
|
114
|
+
}
|
115
|
+
if (exSet.has(fileName)) {
|
116
|
+
throw new Error(`A same class already exists. at \`${xpath}\`.`);
|
117
|
+
}
|
118
|
+
exSet.add(fileName);
|
119
|
+
return;
|
120
|
+
}
|
121
|
+
/**
|
122
|
+
* Format api interface data format
|
123
|
+
*
|
124
|
+
* @private
|
125
|
+
* @param {Error | string | ApiInput} msg 待处理的接口数据信息|接口msg
|
126
|
+
* @param {*} data 待返回的数据
|
127
|
+
* @param {number} defaultCode 默认错误码
|
128
|
+
* @returns {ApiOutput} 格式化之后的接口数据
|
129
|
+
* @memberof BaseController
|
130
|
+
*/
|
131
|
+
function formatApiData(msg, data, defaultCode) {
|
132
|
+
let obj = {
|
133
|
+
code: defaultCode,
|
134
|
+
message: '',
|
135
|
+
data: null,
|
136
|
+
};
|
137
|
+
if (koatty_lib.Helper.isError(msg)) {
|
138
|
+
const { code, message } = msg;
|
139
|
+
obj.code = code || defaultCode;
|
140
|
+
obj.message = message;
|
141
|
+
}
|
142
|
+
else if (koatty_lib.Helper.isObject(msg)) {
|
143
|
+
obj = { ...obj, ...msg };
|
144
|
+
}
|
145
|
+
else {
|
146
|
+
obj.message = msg;
|
147
|
+
obj.data = data;
|
148
|
+
}
|
149
|
+
return obj;
|
150
150
|
}
|
151
151
|
|
152
|
-
/*
|
153
|
-
* @Description: framework constants
|
154
|
-
* @Usage:
|
155
|
-
* @Author: richen
|
156
|
-
* @Date: 2023-12-09 21:56:32
|
157
|
-
* @LastEditTime: 2023-12-09 23:00:13
|
158
|
-
* @License: BSD (3-Clause)
|
159
|
-
* @Copyright (c): <richenlin(at)gmail.com>
|
160
|
-
*/
|
161
|
-
const COMPONENT_SCAN = 'COMPONENT_SCAN';
|
162
|
-
const CONFIGURATION_SCAN = 'CONFIGURATION_SCAN';
|
163
|
-
// tslint:disable: no-irregular-whitespace
|
152
|
+
/*
|
153
|
+
* @Description: framework constants
|
154
|
+
* @Usage:
|
155
|
+
* @Author: richen
|
156
|
+
* @Date: 2023-12-09 21:56:32
|
157
|
+
* @LastEditTime: 2023-12-09 23:00:13
|
158
|
+
* @License: BSD (3-Clause)
|
159
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
160
|
+
*/
|
161
|
+
const COMPONENT_SCAN = 'COMPONENT_SCAN';
|
162
|
+
const CONFIGURATION_SCAN = 'CONFIGURATION_SCAN';
|
163
|
+
// tslint:disable: no-irregular-whitespace
|
164
164
|
const LOGO = `
|
165
165
|
|
166
166
|
┬┌─┌─┐┌─┐┌┬┐┌┬┐┬ ┬
|
@@ -170,881 +170,878 @@ const LOGO = `
|
|
170
170
|
https://github.com/koatty
|
171
171
|
`;
|
172
172
|
|
173
|
-
/*
|
174
|
-
* @Description: base controller
|
175
|
-
* @Usage:
|
176
|
-
* @Author: richen
|
177
|
-
* @Date: 2023-12-09 21:56:32
|
178
|
-
* @LastEditTime: 2023-12-09 23:03:09
|
179
|
-
* @License: BSD (3-Clause)
|
180
|
-
* @Copyright (c): <richenlin(at)gmail.com>
|
181
|
-
*/
|
182
|
-
/**
|
183
|
-
* Base controller
|
184
|
-
*
|
185
|
-
* @export
|
186
|
-
* @class BaseController
|
187
|
-
* @implements {IController}
|
188
|
-
*/
|
189
|
-
class BaseController {
|
190
|
-
/**
|
191
|
-
* instance of BaseController.
|
192
|
-
* @param {Koatty} app
|
193
|
-
* @param {KoattyContext} ctx
|
194
|
-
* @memberof BaseController
|
195
|
-
*/
|
196
|
-
constructor(ctx, ...arg) {
|
197
|
-
this.ctx = ctx;
|
198
|
-
this.init(arg);
|
199
|
-
}
|
200
|
-
/**
|
201
|
-
* init
|
202
|
-
*
|
203
|
-
* @memberof BaseController
|
204
|
-
*/
|
205
|
-
init(...arg) {
|
206
|
-
}
|
207
|
-
/**
|
208
|
-
* Response to normalize json format content for success
|
209
|
-
*
|
210
|
-
* @param {(string | ApiInput)} msg 待处理的message消息
|
211
|
-
* @param {*} [data] 待处理的数据
|
212
|
-
* @param {number} [code=200] 错误码,默认0
|
213
|
-
* @returns {*}
|
214
|
-
* @memberof BaseController
|
215
|
-
*/
|
216
|
-
ok(msg, data, code = 0) {
|
217
|
-
const obj = formatApiData(msg, data, code);
|
218
|
-
return Promise.resolve(obj);
|
219
|
-
}
|
220
|
-
/**
|
221
|
-
* Response to normalize json format content for fail
|
222
|
-
*
|
223
|
-
* @param {(string | ApiInput)} msg
|
224
|
-
* @param {*} [data]
|
225
|
-
* @param {number} [code=1]
|
226
|
-
* @returns {*}
|
227
|
-
* @memberof BaseController
|
228
|
-
*/
|
229
|
-
fail(msg, data, code = 1) {
|
230
|
-
const obj = formatApiData(msg, data, code);
|
231
|
-
this.ctx.body = obj.data;
|
232
|
-
this.ctx.throw(obj.message, obj.code, 200);
|
233
|
-
}
|
234
|
-
}
|
235
|
-
// const properties = ["constructor", "init"];
|
236
|
-
// export const BaseController = new Proxy(Base, {
|
237
|
-
// set(target, key, value, receiver) {
|
238
|
-
// if (Reflect.get(target, key, receiver) === undefined) {
|
239
|
-
// return Reflect.set(target, key, value, receiver);
|
240
|
-
// } else if (key === "init") {
|
241
|
-
// return Reflect.set(target, key, value, receiver);
|
242
|
-
// } else {
|
243
|
-
// throw Error("Cannot redefine getter-only property");
|
244
|
-
// }
|
245
|
-
// },
|
246
|
-
// deleteProperty(target, key) {
|
247
|
-
// throw Error("Cannot delete getter-only property");
|
248
|
-
// },
|
249
|
-
// construct(target, args, newTarget) {
|
250
|
-
// Reflect.ownKeys(target.prototype).map((n) => {
|
251
|
-
// if (newTarget.prototype.hasOwnProperty(n) && !properties.includes(Helper.toString(n))) {
|
252
|
-
// throw Error(`Cannot override the final method "${Helper.toString(n)}"`);
|
253
|
-
// }
|
254
|
-
// });
|
255
|
-
// return Reflect.construct(target, args, newTarget);
|
256
|
-
// }
|
173
|
+
/*
|
174
|
+
* @Description: base controller
|
175
|
+
* @Usage:
|
176
|
+
* @Author: richen
|
177
|
+
* @Date: 2023-12-09 21:56:32
|
178
|
+
* @LastEditTime: 2023-12-09 23:03:09
|
179
|
+
* @License: BSD (3-Clause)
|
180
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
181
|
+
*/
|
182
|
+
/**
|
183
|
+
* Base controller
|
184
|
+
*
|
185
|
+
* @export
|
186
|
+
* @class BaseController
|
187
|
+
* @implements {IController}
|
188
|
+
*/
|
189
|
+
class BaseController {
|
190
|
+
/**
|
191
|
+
* instance of BaseController.
|
192
|
+
* @param {Koatty} app
|
193
|
+
* @param {KoattyContext} ctx
|
194
|
+
* @memberof BaseController
|
195
|
+
*/
|
196
|
+
constructor(ctx, ...arg) {
|
197
|
+
this.ctx = ctx;
|
198
|
+
this.init(arg);
|
199
|
+
}
|
200
|
+
/**
|
201
|
+
* init
|
202
|
+
*
|
203
|
+
* @memberof BaseController
|
204
|
+
*/
|
205
|
+
init(...arg) {
|
206
|
+
}
|
207
|
+
/**
|
208
|
+
* Response to normalize json format content for success
|
209
|
+
*
|
210
|
+
* @param {(string | ApiInput)} msg 待处理的message消息
|
211
|
+
* @param {*} [data] 待处理的数据
|
212
|
+
* @param {number} [code=200] 错误码,默认0
|
213
|
+
* @returns {*}
|
214
|
+
* @memberof BaseController
|
215
|
+
*/
|
216
|
+
ok(msg, data, code = 0) {
|
217
|
+
const obj = formatApiData(msg, data, code);
|
218
|
+
return Promise.resolve(obj);
|
219
|
+
}
|
220
|
+
/**
|
221
|
+
* Response to normalize json format content for fail
|
222
|
+
*
|
223
|
+
* @param {(string | ApiInput)} msg
|
224
|
+
* @param {*} [data]
|
225
|
+
* @param {number} [code=1]
|
226
|
+
* @returns {*}
|
227
|
+
* @memberof BaseController
|
228
|
+
*/
|
229
|
+
fail(msg, data, code = 1) {
|
230
|
+
const obj = formatApiData(msg, data, code);
|
231
|
+
this.ctx.body = obj.data;
|
232
|
+
this.ctx.throw(obj.message, obj.code, 200);
|
233
|
+
}
|
234
|
+
}
|
235
|
+
// const properties = ["constructor", "init"];
|
236
|
+
// export const BaseController = new Proxy(Base, {
|
237
|
+
// set(target, key, value, receiver) {
|
238
|
+
// if (Reflect.get(target, key, receiver) === undefined) {
|
239
|
+
// return Reflect.set(target, key, value, receiver);
|
240
|
+
// } else if (key === "init") {
|
241
|
+
// return Reflect.set(target, key, value, receiver);
|
242
|
+
// } else {
|
243
|
+
// throw Error("Cannot redefine getter-only property");
|
244
|
+
// }
|
245
|
+
// },
|
246
|
+
// deleteProperty(target, key) {
|
247
|
+
// throw Error("Cannot delete getter-only property");
|
248
|
+
// },
|
249
|
+
// construct(target, args, newTarget) {
|
250
|
+
// Reflect.ownKeys(target.prototype).map((n) => {
|
251
|
+
// if (newTarget.prototype.hasOwnProperty(n) && !properties.includes(Helper.toString(n))) {
|
252
|
+
// throw Error(`Cannot override the final method "${Helper.toString(n)}"`);
|
253
|
+
// }
|
254
|
+
// });
|
255
|
+
// return Reflect.construct(target, args, newTarget);
|
256
|
+
// }
|
257
257
|
// });
|
258
258
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
259
|
+
function TraceHandler(app) {
|
260
|
+
const timeout = (app.config('http_timeout') || 10) * 1000;
|
261
|
+
const encoding = app.config('encoding') || 'utf-8';
|
262
|
+
const openTrace = app.config("open_trace") || false;
|
263
|
+
const asyncHooks = app.config("async_hooks") || false;
|
264
|
+
const options = {
|
265
|
+
RequestIdHeaderName: app.config('trace_header') || 'X-Request-Id',
|
266
|
+
RequestIdName: app.config('trace_id') || "requestId",
|
267
|
+
IdFactory: undefined,
|
268
|
+
Timeout: timeout,
|
269
|
+
Encoding: encoding,
|
270
|
+
OpenTrace: openTrace,
|
271
|
+
AsyncHooks: asyncHooks,
|
272
|
+
};
|
273
|
+
app.use(koatty_trace.Trace(options, app));
|
272
274
|
}
|
273
275
|
|
274
|
-
/*
|
275
|
-
* @Description: framework loader
|
276
|
-
* @Usage:
|
277
|
-
* @Author: richen
|
278
|
-
* @Date: 2023-12-09 22:55:49
|
279
|
-
* @LastEditTime: 2023-12-
|
280
|
-
* @License: BSD (3-Clause)
|
281
|
-
* @Copyright (c): <richenlin(at)gmail.com>
|
282
|
-
*/
|
283
|
-
/**
|
284
|
-
*
|
285
|
-
*/
|
286
|
-
class Loader {
|
287
|
-
/**
|
288
|
-
* initialize env
|
289
|
-
*
|
290
|
-
* @static
|
291
|
-
* @param {Koatty} app
|
292
|
-
* @memberof Loader
|
293
|
-
*/
|
294
|
-
static initialize(app) {
|
295
|
-
const env = (process.execArgv ?? []).join(",");
|
296
|
-
if (env.indexOf('ts-node') > -1 || env.indexOf('--debug') > -1) {
|
297
|
-
app.appDebug = true;
|
298
|
-
}
|
299
|
-
// app.env
|
300
|
-
app.env = process.env.KOATTY_ENV || process.env.NODE_ENV;
|
301
|
-
if ((env.indexOf('--production') > -1) || ((app.env ?? '').indexOf('pro') > -1)) {
|
302
|
-
app.appDebug = false;
|
303
|
-
}
|
304
|
-
if (app.appDebug) {
|
305
|
-
app.env = 'development';
|
306
|
-
process.env.NODE_ENV = 'development';
|
307
|
-
process.env.APP_DEBUG = 'true';
|
308
|
-
Logger.setLevel("debug");
|
309
|
-
}
|
310
|
-
else {
|
311
|
-
app.env = 'production';
|
312
|
-
process.env.NODE_ENV = 'production';
|
313
|
-
Logger.setLevel("info");
|
314
|
-
}
|
315
|
-
// define path
|
316
|
-
const rootPath = app.rootPath || process.cwd();
|
317
|
-
const appPath = app.appPath || path__namespace.resolve(rootPath, env.indexOf('ts-node') > -1 ? 'src' : 'dist');
|
318
|
-
const koattyPath = path__namespace.resolve(__dirname, '..');
|
319
|
-
koatty_lib.Helper.define(app, 'rootPath', rootPath);
|
320
|
-
koatty_lib.Helper.define(app, 'appPath', appPath);
|
321
|
-
koatty_lib.Helper.define(app, 'koattyPath', koattyPath);
|
322
|
-
//
|
323
|
-
if (koatty_lib.Helper.isEmpty(app.name)) {
|
324
|
-
const pkg = koatty_lib.Helper.safeRequire(`${path__namespace.dirname(appPath)}/package.json`);
|
325
|
-
if (pkg.name) {
|
326
|
-
app.name = pkg.name;
|
327
|
-
app.version = app.version || pkg.version;
|
328
|
-
}
|
329
|
-
}
|
330
|
-
process.env.ROOT_PATH = rootPath;
|
331
|
-
process.env.APP_PATH = appPath;
|
332
|
-
process.env.KOATTY_PATH = koattyPath;
|
333
|
-
// Compatible with old version, will be deprecated
|
334
|
-
koatty_lib.Helper.define(app, 'prevent', koatty_exception.prevent);
|
335
|
-
koatty_lib.Helper.define(app, 'thinkPath', koattyPath);
|
336
|
-
process.env.THINK_PATH = koattyPath;
|
337
|
-
}
|
338
|
-
/**
|
339
|
-
* Get component metadata
|
340
|
-
*
|
341
|
-
* @static
|
342
|
-
* @param {Koatty} app
|
343
|
-
* @param {*} target
|
344
|
-
* @returns {*} {any[]}
|
345
|
-
* @memberof Loader
|
346
|
-
*/
|
347
|
-
static GetComponentMetas(app, target) {
|
348
|
-
let componentMetas = [];
|
349
|
-
const componentMeta = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, COMPONENT_SCAN, target);
|
350
|
-
if (componentMeta) {
|
351
|
-
if (koatty_lib.Helper.isArray(componentMeta)) {
|
352
|
-
componentMetas = componentMeta;
|
353
|
-
}
|
354
|
-
else {
|
355
|
-
componentMetas.push(componentMeta);
|
356
|
-
}
|
357
|
-
}
|
358
|
-
if (componentMetas.length < 1) {
|
359
|
-
componentMetas = [app.appPath];
|
360
|
-
}
|
361
|
-
return componentMetas;
|
362
|
-
}
|
363
|
-
/**
|
364
|
-
* Load all bean, excepted config/*、App.ts
|
365
|
-
*
|
366
|
-
* @static
|
367
|
-
* @param {Koatty} app
|
368
|
-
* @param {*} target
|
369
|
-
* @memberof Loader
|
370
|
-
*/
|
371
|
-
static CheckAllComponents(app, target) {
|
372
|
-
// component metadata
|
373
|
-
const componentMetas = Loader.GetComponentMetas(app, target);
|
374
|
-
// configuration metadata
|
375
|
-
const configurationMetas = Loader.GetConfigurationMetas(app, target);
|
376
|
-
const exSet = new Set();
|
377
|
-
koatty_loader.Load(componentMetas, '', (fileName, xpath, xTarget) => {
|
378
|
-
checkClass(fileName, xpath, xTarget, exSet);
|
379
|
-
}, ['**/**.js', '**/**.ts', '!**/**.d.ts'], [...configurationMetas, `${target.name || '.no'}.ts`]);
|
380
|
-
exSet.clear();
|
381
|
-
}
|
382
|
-
/**
|
383
|
-
* Get configuration metadata
|
384
|
-
*
|
385
|
-
* @static
|
386
|
-
* @param {Koatty} app
|
387
|
-
* @param {*} target
|
388
|
-
* @returns {*} {any[]}
|
389
|
-
* @memberof Loader
|
390
|
-
*/
|
391
|
-
static GetConfigurationMetas(app, target) {
|
392
|
-
const confMeta = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, CONFIGURATION_SCAN, target);
|
393
|
-
let configurationMetas = [];
|
394
|
-
if (confMeta) {
|
395
|
-
if (koatty_lib.Helper.isArray(confMeta)) {
|
396
|
-
configurationMetas = confMeta;
|
397
|
-
}
|
398
|
-
else {
|
399
|
-
configurationMetas.push(confMeta);
|
400
|
-
}
|
401
|
-
}
|
402
|
-
return configurationMetas;
|
403
|
-
}
|
404
|
-
/**
|
405
|
-
* Set Logger level
|
406
|
-
*
|
407
|
-
* @static
|
408
|
-
* @param {Koatty} app
|
409
|
-
* @memberof Loader
|
410
|
-
*/
|
411
|
-
static SetLogger(app) {
|
412
|
-
const data = app.getMetaData('_configs') || [];
|
413
|
-
const configs = data[0] || {};
|
414
|
-
//Logger
|
415
|
-
if (configs.config) {
|
416
|
-
const opt = configs.config;
|
417
|
-
let logLevel = "debug", logFilePath = "", sensFields = [];
|
418
|
-
if (app.env === "production") {
|
419
|
-
logLevel = "info";
|
420
|
-
}
|
421
|
-
if (opt.logs_level) {
|
422
|
-
logLevel = (opt.logs_level).toLowerCase();
|
423
|
-
}
|
424
|
-
if (opt.logs_path) {
|
425
|
-
logFilePath = opt.logs_path;
|
426
|
-
}
|
427
|
-
if (opt.sens_fields) {
|
428
|
-
sensFields = opt.sens_fields;
|
429
|
-
}
|
430
|
-
SetLogger(app, { logLevel, logFilePath, sensFields });
|
431
|
-
}
|
432
|
-
}
|
433
|
-
/**
|
434
|
-
* Load app event hook funcs
|
435
|
-
*
|
436
|
-
* @static
|
437
|
-
* @param {Koatty} app
|
438
|
-
* @param {*} target
|
439
|
-
* @memberof Loader
|
440
|
-
*/
|
441
|
-
static LoadAppEventHooks(app, target) {
|
442
|
-
const eventFuncs = new Map();
|
443
|
-
for (const event of koatty_core.AppEventArr) {
|
444
|
-
let funcs;
|
445
|
-
switch (event) {
|
446
|
-
case "appBoot" /* AppEvent.appBoot */:
|
447
|
-
funcs = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, "appBoot" /* AppEvent.appBoot */, target);
|
448
|
-
if (koatty_lib.Helper.isArray(funcs)) {
|
449
|
-
eventFuncs.set("appBoot" /* AppEvent.appBoot */, funcs);
|
450
|
-
}
|
451
|
-
break;
|
452
|
-
case "appReady" /* AppEvent.appReady */:
|
453
|
-
funcs = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, "appReady" /* AppEvent.appReady */, target);
|
454
|
-
if (koatty_lib.Helper.isArray(funcs)) {
|
455
|
-
eventFuncs.set("appReady" /* AppEvent.appReady */, funcs);
|
456
|
-
}
|
457
|
-
break;
|
458
|
-
case "appStart" /* AppEvent.appStart */:
|
459
|
-
funcs = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, "appStart" /* AppEvent.appStart */, target);
|
460
|
-
if (koatty_lib.Helper.isArray(funcs)) {
|
461
|
-
eventFuncs.set("appStart" /* AppEvent.appStart */, funcs);
|
462
|
-
}
|
463
|
-
break;
|
464
|
-
case "appStop" /* AppEvent.appStop */:
|
465
|
-
funcs = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, "appStop" /* AppEvent.appStop */, target);
|
466
|
-
if (koatty_lib.Helper.isArray(funcs)) {
|
467
|
-
eventFuncs.set("appStop" /* AppEvent.appStop */, funcs);
|
468
|
-
}
|
469
|
-
break;
|
470
|
-
}
|
471
|
-
}
|
472
|
-
// loop event emit
|
473
|
-
for (const [event, funcs] of eventFuncs) {
|
474
|
-
for (const func of funcs) {
|
475
|
-
app.once(event, () => func(app));
|
476
|
-
}
|
477
|
-
}
|
478
|
-
}
|
479
|
-
/**
|
480
|
-
* Load configuration
|
481
|
-
*
|
482
|
-
* @static
|
483
|
-
* @param {Koatty} app
|
484
|
-
* @param {string[]} [loadPath]
|
485
|
-
* @memberof Loader
|
486
|
-
*/
|
487
|
-
static LoadConfigs(app, loadPath) {
|
488
|
-
const frameConfig = {};
|
489
|
-
// Logger.Debug(`Load configuration path: ${app.thinkPath}/config`);
|
490
|
-
koatty_loader.Load(["./config"], app.koattyPath, function (name, path, exp) {
|
491
|
-
frameConfig[name] = exp;
|
492
|
-
});
|
493
|
-
if (koatty_lib.Helper.isArray(loadPath)) {
|
494
|
-
loadPath = loadPath.length > 0 ? loadPath : ["./config"];
|
495
|
-
}
|
496
|
-
let appConfig = koatty_config.LoadConfigs(loadPath, app.appPath);
|
497
|
-
appConfig = koatty_lib.Helper.extend(frameConfig, appConfig, true);
|
498
|
-
app.setMetaData("_configs", appConfig);
|
499
|
-
}
|
500
|
-
/**
|
501
|
-
* Load middlewares
|
502
|
-
* [async]
|
503
|
-
* @static
|
504
|
-
* @param {*} app
|
505
|
-
* @param {(string | string[])} [loadPath]
|
506
|
-
* @memberof Loader
|
507
|
-
*/
|
508
|
-
static async LoadMiddlewares(app, loadPath) {
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
//Mount
|
516
|
-
//
|
517
|
-
|
518
|
-
|
519
|
-
appMiddleware.
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
const
|
527
|
-
//de-duplication
|
528
|
-
const appMList = new Set(
|
529
|
-
middlewareConfList.forEach((item) => {
|
530
|
-
appMList.add(item);
|
531
|
-
});
|
532
|
-
//Automatically call middleware
|
533
|
-
for (const key of appMList) {
|
534
|
-
const handle = koatty_container.IOCContainer.get(key, "MIDDLEWARE");
|
535
|
-
if (!handle) {
|
536
|
-
Logger.Error(`Middleware ${key} load error.`);
|
537
|
-
continue;
|
538
|
-
}
|
539
|
-
if (!koatty_lib.Helper.isFunction(handle.run)) {
|
540
|
-
Logger.Error(`
|
541
|
-
continue;
|
542
|
-
}
|
543
|
-
if (middlewareConf.config[key] === false) {
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
//
|
616
|
-
//
|
617
|
-
//
|
618
|
-
//
|
619
|
-
//
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
// load plugin
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
}
|
663
|
-
|
664
|
-
|
665
|
-
continue;
|
666
|
-
}
|
667
|
-
// sync exec
|
668
|
-
await handle.run(pluginsConf.config[key] ?? {}, app);
|
669
|
-
}
|
670
|
-
}
|
276
|
+
/*
|
277
|
+
* @Description: framework loader
|
278
|
+
* @Usage:
|
279
|
+
* @Author: richen
|
280
|
+
* @Date: 2023-12-09 22:55:49
|
281
|
+
* @LastEditTime: 2023-12-14 23:10:33
|
282
|
+
* @License: BSD (3-Clause)
|
283
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
284
|
+
*/
|
285
|
+
/**
|
286
|
+
*
|
287
|
+
*/
|
288
|
+
class Loader {
|
289
|
+
/**
|
290
|
+
* initialize env
|
291
|
+
*
|
292
|
+
* @static
|
293
|
+
* @param {Koatty} app
|
294
|
+
* @memberof Loader
|
295
|
+
*/
|
296
|
+
static initialize(app) {
|
297
|
+
const env = (process.execArgv ?? []).join(",");
|
298
|
+
if (env.indexOf('ts-node') > -1 || env.indexOf('--debug') > -1) {
|
299
|
+
app.appDebug = true;
|
300
|
+
}
|
301
|
+
// app.env
|
302
|
+
app.env = process.env.KOATTY_ENV || process.env.NODE_ENV;
|
303
|
+
if ((env.indexOf('--production') > -1) || ((app.env ?? '').indexOf('pro') > -1)) {
|
304
|
+
app.appDebug = false;
|
305
|
+
}
|
306
|
+
if (app.appDebug) {
|
307
|
+
app.env = 'development';
|
308
|
+
process.env.NODE_ENV = 'development';
|
309
|
+
process.env.APP_DEBUG = 'true';
|
310
|
+
Logger.setLevel("debug");
|
311
|
+
}
|
312
|
+
else {
|
313
|
+
app.env = 'production';
|
314
|
+
process.env.NODE_ENV = 'production';
|
315
|
+
Logger.setLevel("info");
|
316
|
+
}
|
317
|
+
// define path
|
318
|
+
const rootPath = app.rootPath || process.cwd();
|
319
|
+
const appPath = app.appPath || path__namespace.resolve(rootPath, env.indexOf('ts-node') > -1 ? 'src' : 'dist');
|
320
|
+
const koattyPath = path__namespace.resolve(__dirname, '..');
|
321
|
+
koatty_lib.Helper.define(app, 'rootPath', rootPath);
|
322
|
+
koatty_lib.Helper.define(app, 'appPath', appPath);
|
323
|
+
koatty_lib.Helper.define(app, 'koattyPath', koattyPath);
|
324
|
+
//
|
325
|
+
if (koatty_lib.Helper.isEmpty(app.name)) {
|
326
|
+
const pkg = koatty_lib.Helper.safeRequire(`${path__namespace.dirname(appPath)}/package.json`);
|
327
|
+
if (pkg.name) {
|
328
|
+
app.name = pkg.name;
|
329
|
+
app.version = app.version || pkg.version;
|
330
|
+
}
|
331
|
+
}
|
332
|
+
process.env.ROOT_PATH = rootPath;
|
333
|
+
process.env.APP_PATH = appPath;
|
334
|
+
process.env.KOATTY_PATH = koattyPath;
|
335
|
+
// Compatible with old version, will be deprecated
|
336
|
+
koatty_lib.Helper.define(app, 'prevent', koatty_exception.prevent);
|
337
|
+
koatty_lib.Helper.define(app, 'thinkPath', koattyPath);
|
338
|
+
process.env.THINK_PATH = koattyPath;
|
339
|
+
}
|
340
|
+
/**
|
341
|
+
* Get component metadata
|
342
|
+
*
|
343
|
+
* @static
|
344
|
+
* @param {Koatty} app
|
345
|
+
* @param {*} target
|
346
|
+
* @returns {*} {any[]}
|
347
|
+
* @memberof Loader
|
348
|
+
*/
|
349
|
+
static GetComponentMetas(app, target) {
|
350
|
+
let componentMetas = [];
|
351
|
+
const componentMeta = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, COMPONENT_SCAN, target);
|
352
|
+
if (componentMeta) {
|
353
|
+
if (koatty_lib.Helper.isArray(componentMeta)) {
|
354
|
+
componentMetas = componentMeta;
|
355
|
+
}
|
356
|
+
else {
|
357
|
+
componentMetas.push(componentMeta);
|
358
|
+
}
|
359
|
+
}
|
360
|
+
if (componentMetas.length < 1) {
|
361
|
+
componentMetas = [app.appPath];
|
362
|
+
}
|
363
|
+
return componentMetas;
|
364
|
+
}
|
365
|
+
/**
|
366
|
+
* Load all bean, excepted config/*、App.ts
|
367
|
+
*
|
368
|
+
* @static
|
369
|
+
* @param {Koatty} app
|
370
|
+
* @param {*} target
|
371
|
+
* @memberof Loader
|
372
|
+
*/
|
373
|
+
static CheckAllComponents(app, target) {
|
374
|
+
// component metadata
|
375
|
+
const componentMetas = Loader.GetComponentMetas(app, target);
|
376
|
+
// configuration metadata
|
377
|
+
const configurationMetas = Loader.GetConfigurationMetas(app, target);
|
378
|
+
const exSet = new Set();
|
379
|
+
koatty_loader.Load(componentMetas, '', (fileName, xpath, xTarget) => {
|
380
|
+
checkClass(fileName, xpath, xTarget, exSet);
|
381
|
+
}, ['**/**.js', '**/**.ts', '!**/**.d.ts'], [...configurationMetas, `${target.name || '.no'}.ts`]);
|
382
|
+
exSet.clear();
|
383
|
+
}
|
384
|
+
/**
|
385
|
+
* Get configuration metadata
|
386
|
+
*
|
387
|
+
* @static
|
388
|
+
* @param {Koatty} app
|
389
|
+
* @param {*} target
|
390
|
+
* @returns {*} {any[]}
|
391
|
+
* @memberof Loader
|
392
|
+
*/
|
393
|
+
static GetConfigurationMetas(app, target) {
|
394
|
+
const confMeta = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, CONFIGURATION_SCAN, target);
|
395
|
+
let configurationMetas = [];
|
396
|
+
if (confMeta) {
|
397
|
+
if (koatty_lib.Helper.isArray(confMeta)) {
|
398
|
+
configurationMetas = confMeta;
|
399
|
+
}
|
400
|
+
else {
|
401
|
+
configurationMetas.push(confMeta);
|
402
|
+
}
|
403
|
+
}
|
404
|
+
return configurationMetas;
|
405
|
+
}
|
406
|
+
/**
|
407
|
+
* Set Logger level
|
408
|
+
*
|
409
|
+
* @static
|
410
|
+
* @param {Koatty} app
|
411
|
+
* @memberof Loader
|
412
|
+
*/
|
413
|
+
static SetLogger(app) {
|
414
|
+
const data = app.getMetaData('_configs') || [];
|
415
|
+
const configs = data[0] || {};
|
416
|
+
//Logger
|
417
|
+
if (configs.config) {
|
418
|
+
const opt = configs.config;
|
419
|
+
let logLevel = "debug", logFilePath = "", sensFields = [];
|
420
|
+
if (app.env === "production") {
|
421
|
+
logLevel = "info";
|
422
|
+
}
|
423
|
+
if (opt.logs_level) {
|
424
|
+
logLevel = (opt.logs_level).toLowerCase();
|
425
|
+
}
|
426
|
+
if (opt.logs_path) {
|
427
|
+
logFilePath = opt.logs_path;
|
428
|
+
}
|
429
|
+
if (opt.sens_fields) {
|
430
|
+
sensFields = opt.sens_fields;
|
431
|
+
}
|
432
|
+
SetLogger(app, { logLevel, logFilePath, sensFields });
|
433
|
+
}
|
434
|
+
}
|
435
|
+
/**
|
436
|
+
* Load app event hook funcs
|
437
|
+
*
|
438
|
+
* @static
|
439
|
+
* @param {Koatty} app
|
440
|
+
* @param {*} target
|
441
|
+
* @memberof Loader
|
442
|
+
*/
|
443
|
+
static LoadAppEventHooks(app, target) {
|
444
|
+
const eventFuncs = new Map();
|
445
|
+
for (const event of koatty_core.AppEventArr) {
|
446
|
+
let funcs;
|
447
|
+
switch (event) {
|
448
|
+
case "appBoot" /* AppEvent.appBoot */:
|
449
|
+
funcs = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, "appBoot" /* AppEvent.appBoot */, target);
|
450
|
+
if (koatty_lib.Helper.isArray(funcs)) {
|
451
|
+
eventFuncs.set("appBoot" /* AppEvent.appBoot */, funcs);
|
452
|
+
}
|
453
|
+
break;
|
454
|
+
case "appReady" /* AppEvent.appReady */:
|
455
|
+
funcs = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, "appReady" /* AppEvent.appReady */, target);
|
456
|
+
if (koatty_lib.Helper.isArray(funcs)) {
|
457
|
+
eventFuncs.set("appReady" /* AppEvent.appReady */, funcs);
|
458
|
+
}
|
459
|
+
break;
|
460
|
+
case "appStart" /* AppEvent.appStart */:
|
461
|
+
funcs = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, "appStart" /* AppEvent.appStart */, target);
|
462
|
+
if (koatty_lib.Helper.isArray(funcs)) {
|
463
|
+
eventFuncs.set("appStart" /* AppEvent.appStart */, funcs);
|
464
|
+
}
|
465
|
+
break;
|
466
|
+
case "appStop" /* AppEvent.appStop */:
|
467
|
+
funcs = koatty_container.IOCContainer.getClassMetadata(koatty_container.TAGGED_CLS, "appStop" /* AppEvent.appStop */, target);
|
468
|
+
if (koatty_lib.Helper.isArray(funcs)) {
|
469
|
+
eventFuncs.set("appStop" /* AppEvent.appStop */, funcs);
|
470
|
+
}
|
471
|
+
break;
|
472
|
+
}
|
473
|
+
}
|
474
|
+
// loop event emit
|
475
|
+
for (const [event, funcs] of eventFuncs) {
|
476
|
+
for (const func of funcs) {
|
477
|
+
app.once(event, () => func(app));
|
478
|
+
}
|
479
|
+
}
|
480
|
+
}
|
481
|
+
/**
|
482
|
+
* Load configuration
|
483
|
+
*
|
484
|
+
* @static
|
485
|
+
* @param {Koatty} app
|
486
|
+
* @param {string[]} [loadPath]
|
487
|
+
* @memberof Loader
|
488
|
+
*/
|
489
|
+
static LoadConfigs(app, loadPath) {
|
490
|
+
const frameConfig = {};
|
491
|
+
// Logger.Debug(`Load configuration path: ${app.thinkPath}/config`);
|
492
|
+
koatty_loader.Load(["./config"], app.koattyPath, function (name, path, exp) {
|
493
|
+
frameConfig[name] = exp;
|
494
|
+
});
|
495
|
+
if (koatty_lib.Helper.isArray(loadPath)) {
|
496
|
+
loadPath = loadPath.length > 0 ? loadPath : ["./config"];
|
497
|
+
}
|
498
|
+
let appConfig = koatty_config.LoadConfigs(loadPath, app.appPath);
|
499
|
+
appConfig = koatty_lib.Helper.extend(frameConfig, appConfig, true);
|
500
|
+
app.setMetaData("_configs", appConfig);
|
501
|
+
}
|
502
|
+
/**
|
503
|
+
* Load middlewares
|
504
|
+
* [async]
|
505
|
+
* @static
|
506
|
+
* @param {*} app
|
507
|
+
* @param {(string | string[])} [loadPath]
|
508
|
+
* @memberof Loader
|
509
|
+
*/
|
510
|
+
static async LoadMiddlewares(app, loadPath) {
|
511
|
+
// Error handling middleware
|
512
|
+
TraceHandler(app);
|
513
|
+
let middlewareConf = app.config(undefined, "middleware");
|
514
|
+
if (koatty_lib.Helper.isEmpty(middlewareConf)) {
|
515
|
+
middlewareConf = { config: {}, list: [] };
|
516
|
+
}
|
517
|
+
//Mount default middleware
|
518
|
+
// Load(loadPath || ["./middleware"], app.koattyPath);
|
519
|
+
//Mount application middleware
|
520
|
+
// const middleware: any = {};
|
521
|
+
const appMiddleware = koatty_container.IOCContainer.listClass("MIDDLEWARE") ?? [];
|
522
|
+
appMiddleware.forEach((item) => {
|
523
|
+
item.id = (item.id ?? "").replace("MIDDLEWARE:", "");
|
524
|
+
if (item.id && koatty_lib.Helper.isClass(item.target)) {
|
525
|
+
koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "MIDDLEWARE", args: [] });
|
526
|
+
}
|
527
|
+
});
|
528
|
+
const middlewareConfList = middlewareConf.list;
|
529
|
+
//de-duplication
|
530
|
+
const appMList = new Set([]);
|
531
|
+
middlewareConfList.forEach((item) => {
|
532
|
+
appMList.add(item);
|
533
|
+
});
|
534
|
+
//Automatically call middleware
|
535
|
+
for (const key of appMList) {
|
536
|
+
const handle = koatty_container.IOCContainer.get(key, "MIDDLEWARE");
|
537
|
+
if (!handle) {
|
538
|
+
Logger.Error(`Middleware ${key} load error.`);
|
539
|
+
continue;
|
540
|
+
}
|
541
|
+
if (!koatty_lib.Helper.isFunction(handle.run)) {
|
542
|
+
Logger.Error(`The middleware ${key} must implements interface 'IMiddleware'.`);
|
543
|
+
continue;
|
544
|
+
}
|
545
|
+
if (middlewareConf.config[key] === false) {
|
546
|
+
Logger.Warn(`The middleware ${key} has been loaded but not executed.`);
|
547
|
+
continue;
|
548
|
+
}
|
549
|
+
Logger.Debug(`Load middleware: ${key}`);
|
550
|
+
const result = await handle.run(middlewareConf.config[key] || {}, app);
|
551
|
+
if (koatty_lib.Helper.isFunction(result)) {
|
552
|
+
if (result.length < 3) {
|
553
|
+
app.use(result);
|
554
|
+
}
|
555
|
+
else {
|
556
|
+
app.useExp(result);
|
557
|
+
}
|
558
|
+
}
|
559
|
+
}
|
560
|
+
}
|
561
|
+
/**
|
562
|
+
* Load controllers
|
563
|
+
*
|
564
|
+
* @static
|
565
|
+
* @param {*} app
|
566
|
+
* @memberof Loader
|
567
|
+
*/
|
568
|
+
static LoadControllers(app) {
|
569
|
+
const controllerList = koatty_container.IOCContainer.listClass("CONTROLLER");
|
570
|
+
const controllers = [];
|
571
|
+
controllerList.forEach((item) => {
|
572
|
+
item.id = (item.id ?? "").replace("CONTROLLER:", "");
|
573
|
+
if (item.id && koatty_lib.Helper.isClass(item.target)) {
|
574
|
+
Logger.Debug(`Load controller: ${item.id}`);
|
575
|
+
// registering to IOC
|
576
|
+
koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "CONTROLLER", args: [] });
|
577
|
+
const ctl = koatty_container.IOCContainer.getInsByClass(item.target);
|
578
|
+
if (!(ctl instanceof BaseController)) {
|
579
|
+
throw new Error(`class ${item.id} does not inherit from BaseController`);
|
580
|
+
}
|
581
|
+
controllers.push(item.id);
|
582
|
+
}
|
583
|
+
});
|
584
|
+
return controllers;
|
585
|
+
}
|
586
|
+
/**
|
587
|
+
* Load services
|
588
|
+
*
|
589
|
+
* @static
|
590
|
+
* @param {*} app
|
591
|
+
* @memberof Loader
|
592
|
+
*/
|
593
|
+
static LoadServices(app) {
|
594
|
+
const serviceList = koatty_container.IOCContainer.listClass("SERVICE");
|
595
|
+
serviceList.forEach((item) => {
|
596
|
+
item.id = (item.id ?? "").replace("SERVICE:", "");
|
597
|
+
if (item.id && koatty_lib.Helper.isClass(item.target)) {
|
598
|
+
Logger.Debug(`Load service: ${item.id}`);
|
599
|
+
// registering to IOC
|
600
|
+
koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "SERVICE", args: [] });
|
601
|
+
}
|
602
|
+
});
|
603
|
+
}
|
604
|
+
/**
|
605
|
+
* Load components
|
606
|
+
*
|
607
|
+
* @static
|
608
|
+
* @param {*} app
|
609
|
+
* @memberof Loader
|
610
|
+
*/
|
611
|
+
// public static LoadComponents(app: Koatty) {
|
612
|
+
// const componentList = IOCContainer.listClass("COMPONENT");
|
613
|
+
// componentList.forEach((item: ComponentItem) => {
|
614
|
+
// item.id = (item.id ?? "").replace("COMPONENT:", "");
|
615
|
+
// if (item.id && !(item.id).endsWith("Plugin") && Helper.isClass(item.target)) {
|
616
|
+
// Logger.Debug(`Load component: ${item.id}`);
|
617
|
+
// // registering to IOC
|
618
|
+
// IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
|
619
|
+
// }
|
620
|
+
// });
|
621
|
+
// }
|
622
|
+
/**
|
623
|
+
* Load components
|
624
|
+
*
|
625
|
+
* @static
|
626
|
+
* @param {*} app
|
627
|
+
* @memberof Loader
|
628
|
+
*/
|
629
|
+
static async LoadComponents(app) {
|
630
|
+
const componentList = koatty_container.IOCContainer.listClass("COMPONENT");
|
631
|
+
const pluginList = [];
|
632
|
+
componentList.forEach(async (item) => {
|
633
|
+
item.id = (item.id ?? "").replace("COMPONENT:", "");
|
634
|
+
if (koatty_lib.Helper.isClass(item.target)) {
|
635
|
+
if (item.id && (item.id).endsWith("Plugin")) {
|
636
|
+
pluginList.push(item.id);
|
637
|
+
}
|
638
|
+
// registering to IOC
|
639
|
+
koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
|
640
|
+
}
|
641
|
+
});
|
642
|
+
// load plugin config
|
643
|
+
let pluginsConf = app.config(undefined, "plugin");
|
644
|
+
if (koatty_lib.Helper.isEmpty(pluginsConf)) {
|
645
|
+
pluginsConf = { config: {}, list: [] };
|
646
|
+
}
|
647
|
+
const pluginConfList = pluginsConf.list ?? [];
|
648
|
+
// load plugin list
|
649
|
+
for (const key of pluginConfList) {
|
650
|
+
const handle = koatty_container.IOCContainer.get(key, "COMPONENT");
|
651
|
+
if (!handle) {
|
652
|
+
Logger.Error(`Plugin ${key} load error.`);
|
653
|
+
continue;
|
654
|
+
}
|
655
|
+
if (!koatty_lib.Helper.isFunction(handle.run)) {
|
656
|
+
Logger.Error(`Plugin ${key} must be implements method 'run'.`);
|
657
|
+
continue;
|
658
|
+
}
|
659
|
+
if (pluginsConf.config[key] === false) {
|
660
|
+
Logger.Warn(`Plugin ${key} already loaded but not effective.`);
|
661
|
+
continue;
|
662
|
+
}
|
663
|
+
// sync exec
|
664
|
+
await handle.run(pluginsConf.config[key] ?? {}, app);
|
665
|
+
}
|
666
|
+
}
|
671
667
|
}
|
672
668
|
|
673
|
-
var version = "3.10.4-
|
669
|
+
var version = "3.10.4-2";
|
674
670
|
var engines = {
|
675
671
|
node: ">12.0.0"
|
676
672
|
};
|
677
673
|
|
678
|
-
/*
|
679
|
-
* @Description: framework runtime checker
|
680
|
-
* @Usage:
|
681
|
-
* @Author: richen
|
682
|
-
* @Date: 2023-12-09 21:56:32
|
683
|
-
* @LastEditTime: 2023-12-09 23:01:22
|
684
|
-
* @License: BSD (3-Clause)
|
685
|
-
* @Copyright (c): <richenlin(at)gmail.com>
|
686
|
-
*/
|
687
|
-
const KOATTY_VERSION = version;
|
688
|
-
const ENGINES_VERSION = engines.node.slice(1) || '12.0.0';
|
689
|
-
/**
|
690
|
-
* check node version
|
691
|
-
* @return {void} []
|
692
|
-
*/
|
693
|
-
function checkRuntime() {
|
694
|
-
let nodeEngines = ENGINES_VERSION;
|
695
|
-
nodeEngines = nodeEngines.slice(0, nodeEngines.lastIndexOf('.'));
|
696
|
-
let nodeVersion = process.version;
|
697
|
-
if (nodeVersion[0] === 'v') {
|
698
|
-
nodeVersion = nodeVersion.slice(1);
|
699
|
-
}
|
700
|
-
nodeVersion = nodeVersion.slice(0, nodeVersion.lastIndexOf('.'));
|
701
|
-
if (koatty_lib.Helper.toNumber(nodeEngines) > koatty_lib.Helper.toNumber(nodeVersion)) {
|
702
|
-
Logger.Error(`Koatty need node version > ${nodeEngines}, current version is ${nodeVersion}, please upgrade it.`);
|
703
|
-
process.exit(-1);
|
704
|
-
}
|
705
|
-
}
|
706
|
-
/**
|
707
|
-
* unittest running environment detection
|
708
|
-
* only support jest
|
709
|
-
* @returns {boolean}
|
710
|
-
*/
|
711
|
-
const checkUTRuntime = () => {
|
712
|
-
let isUTRuntime = false;
|
713
|
-
// UT运行环境判断,暂时先只判断jest
|
714
|
-
const argv = JSON.stringify(process.argv[1]);
|
715
|
-
if (argv.indexOf('jest') > -1) {
|
716
|
-
isUTRuntime = true;
|
717
|
-
}
|
718
|
-
return isUTRuntime;
|
674
|
+
/*
|
675
|
+
* @Description: framework runtime checker
|
676
|
+
* @Usage:
|
677
|
+
* @Author: richen
|
678
|
+
* @Date: 2023-12-09 21:56:32
|
679
|
+
* @LastEditTime: 2023-12-09 23:01:22
|
680
|
+
* @License: BSD (3-Clause)
|
681
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
682
|
+
*/
|
683
|
+
const KOATTY_VERSION = version;
|
684
|
+
const ENGINES_VERSION = engines.node.slice(1) || '12.0.0';
|
685
|
+
/**
|
686
|
+
* check node version
|
687
|
+
* @return {void} []
|
688
|
+
*/
|
689
|
+
function checkRuntime() {
|
690
|
+
let nodeEngines = ENGINES_VERSION;
|
691
|
+
nodeEngines = nodeEngines.slice(0, nodeEngines.lastIndexOf('.'));
|
692
|
+
let nodeVersion = process.version;
|
693
|
+
if (nodeVersion[0] === 'v') {
|
694
|
+
nodeVersion = nodeVersion.slice(1);
|
695
|
+
}
|
696
|
+
nodeVersion = nodeVersion.slice(0, nodeVersion.lastIndexOf('.'));
|
697
|
+
if (koatty_lib.Helper.toNumber(nodeEngines) > koatty_lib.Helper.toNumber(nodeVersion)) {
|
698
|
+
Logger.Error(`Koatty need node version > ${nodeEngines}, current version is ${nodeVersion}, please upgrade it.`);
|
699
|
+
process.exit(-1);
|
700
|
+
}
|
701
|
+
}
|
702
|
+
/**
|
703
|
+
* unittest running environment detection
|
704
|
+
* only support jest
|
705
|
+
* @returns {boolean}
|
706
|
+
*/
|
707
|
+
const checkUTRuntime = () => {
|
708
|
+
let isUTRuntime = false;
|
709
|
+
// UT运行环境判断,暂时先只判断jest
|
710
|
+
const argv = JSON.stringify(process.argv[1]);
|
711
|
+
if (argv.indexOf('jest') > -1) {
|
712
|
+
isUTRuntime = true;
|
713
|
+
}
|
714
|
+
return isUTRuntime;
|
719
715
|
};
|
720
716
|
|
721
|
-
/*
|
722
|
-
* @Description: framework bootstrap
|
723
|
-
* @Usage:
|
724
|
-
* @Author: richen
|
725
|
-
* @Date: 2023-12-09 21:56:32
|
726
|
-
* @LastEditTime: 2023-12-
|
727
|
-
* @License: BSD (3-Clause)
|
728
|
-
* @Copyright (c): <richenlin(at)gmail.com>
|
729
|
-
*/
|
730
|
-
/**
|
731
|
-
* execute bootstrap
|
732
|
-
*
|
733
|
-
* @param {*} target
|
734
|
-
* @param {Function} bootFunc
|
735
|
-
* @param {boolean} [isInitiative=false] Whether to actively execute app instantiation,
|
736
|
-
* mainly for unittest scenarios, you need to actively obtain app instances
|
737
|
-
* @returns {Promise<void>}
|
738
|
-
*/
|
739
|
-
const executeBootstrap = async function (target, bootFunc, isInitiative = false) {
|
740
|
-
// checked runtime
|
741
|
-
checkRuntime();
|
742
|
-
// unittest running environment
|
743
|
-
const isUTRuntime = checkUTRuntime();
|
744
|
-
if (!isInitiative && isUTRuntime) {
|
745
|
-
return;
|
746
|
-
}
|
747
|
-
const app = Reflect.construct(target, []);
|
748
|
-
// unittest does not print startup logs
|
749
|
-
if (isUTRuntime) {
|
750
|
-
app.silent = true;
|
751
|
-
Logger.enable(false);
|
752
|
-
}
|
753
|
-
try {
|
754
|
-
!app.silent && Logger.Log("Koatty", LOGO);
|
755
|
-
if (!(app instanceof koatty_core.Koatty)) {
|
756
|
-
throw new Error(`class ${target.name} does not inherit from Koatty`);
|
757
|
-
}
|
758
|
-
// Initialize env
|
759
|
-
Loader.initialize(app);
|
760
|
-
// exec bootFunc
|
761
|
-
if (koatty_lib.Helper.isFunction(bootFunc)) {
|
762
|
-
Logger.Log('Koatty', '', 'Execute bootFunc ...');
|
763
|
-
await bootFunc(app);
|
764
|
-
}
|
765
|
-
// Set IOCContainer.app
|
766
|
-
koatty_container.IOCContainer.setApp(app);
|
767
|
-
Logger.Log('Koatty', '', 'ComponentScan ...');
|
768
|
-
// Check all bean
|
769
|
-
Loader.CheckAllComponents(app, target);
|
770
|
-
// Load configuration
|
771
|
-
Logger.Log('Koatty', '', 'Load Configurations ...');
|
772
|
-
// configuration metadata
|
773
|
-
const configurationMetas = Loader.GetConfigurationMetas(app, target);
|
774
|
-
Loader.LoadConfigs(app, configurationMetas);
|
775
|
-
// Load App event hooks
|
776
|
-
Loader.LoadAppEventHooks(app, target);
|
777
|
-
Logger.Log('Koatty', '', 'Emit App Boot ...');
|
778
|
-
await asyncEvent(app, "appBoot" /* AppEvent.appBoot */);
|
779
|
-
// Load Components
|
780
|
-
Logger.Log('Koatty', '', 'Load Components ...');
|
781
|
-
await Loader.LoadComponents(app);
|
782
|
-
// Load Middleware
|
783
|
-
Logger.Log('Koatty', '', 'Load Middlewares ...');
|
784
|
-
await Loader.LoadMiddlewares(app);
|
785
|
-
// Load Services
|
786
|
-
Logger.Log('Koatty', '', 'Load Services ...');
|
787
|
-
Loader.LoadServices(app);
|
788
|
-
// Load Controllers
|
789
|
-
Logger.Log('Koatty', '', 'Load Controllers ...');
|
790
|
-
const controllers = Loader.LoadControllers(app);
|
791
|
-
// Create Server
|
792
|
-
// app.server = newServe(app);
|
793
|
-
koatty_lib.Helper.define(app, "server", koatty_serve.NewServe(app));
|
794
|
-
// Create router
|
795
|
-
// app.router = newRouter(app);
|
796
|
-
koatty_lib.Helper.define(app, "router", koatty_serve.NewRouter(app));
|
797
|
-
// Emit app ready event
|
798
|
-
Logger.Log('Koatty', '', 'Emit App Ready ...');
|
799
|
-
await asyncEvent(app, "appReady" /* AppEvent.appReady */);
|
800
|
-
// Load Routers
|
801
|
-
Logger.Log('Koatty', '', 'Load Routers ...');
|
802
|
-
app.router.LoadRouter(controllers);
|
803
|
-
if (!isUTRuntime) {
|
804
|
-
// Start Server
|
805
|
-
app.listen(listenCallback);
|
806
|
-
}
|
807
|
-
return app;
|
808
|
-
}
|
809
|
-
catch (err) {
|
810
|
-
Logger.Error(err);
|
811
|
-
process.exit();
|
812
|
-
}
|
813
|
-
};
|
814
|
-
/**
|
815
|
-
* Listening callback function
|
816
|
-
*
|
817
|
-
* @param {Koatty} app
|
818
|
-
* @returns {*}
|
819
|
-
*/
|
820
|
-
const listenCallback = (app) => {
|
821
|
-
const options = app.server.options;
|
822
|
-
Logger.Log('Koatty', '', '====================================');
|
823
|
-
Logger.Log("Koatty", "", `Nodejs Version: ${process.version}`);
|
824
|
-
Logger.Log("Koatty", "", `Koatty Version: v${KOATTY_VERSION}`);
|
825
|
-
Logger.Log("Koatty", "", `App Environment: ${app.env}`);
|
826
|
-
Logger.Log('Koatty', '', `Server Protocol: ${(options.protocol).toUpperCase()}`);
|
827
|
-
Logger.Log("Koatty", "", `Server running at ${options.protocol === "http2" ? "https" : options.protocol}://${options.hostname || '127.0.0.1'}:${options.port}/`);
|
828
|
-
Logger.Log("Koatty", "", "====================================");
|
829
|
-
// binding event "appStop"
|
830
|
-
Logger.Log('Koatty', '', 'Bind App Stop event ...');
|
831
|
-
koatty_serve.BindProcessEvent(app, 'appStop');
|
832
|
-
// tslint:disable-next-line: no-unused-expression
|
833
|
-
app.appDebug && Logger.Warn(`Running in debug mode.`);
|
834
|
-
// Set Logger
|
835
|
-
Loader.SetLogger(app);
|
836
|
-
};
|
837
|
-
/**
|
838
|
-
* Execute event as async
|
839
|
-
*
|
840
|
-
* @param {Koatty} event
|
841
|
-
* @param {string} eventName
|
842
|
-
*/
|
843
|
-
const asyncEvent = async function (event, eventName) {
|
844
|
-
const ls = event.listeners(eventName);
|
845
|
-
// eslint-disable-next-line no-restricted-syntax
|
846
|
-
for await (const func of ls) {
|
847
|
-
if (koatty_lib.Helper.isFunction(func)) {
|
848
|
-
func();
|
849
|
-
}
|
850
|
-
}
|
851
|
-
return event.removeAllListeners(eventName);
|
852
|
-
};
|
853
|
-
/**
|
854
|
-
* Bootstrap application
|
855
|
-
*
|
856
|
-
* @export
|
857
|
-
* @param {Function} [bootFunc]
|
858
|
-
* @returns {ClassDecorator}
|
859
|
-
*/
|
860
|
-
function Bootstrap(bootFunc) {
|
861
|
-
return function (target) {
|
862
|
-
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
863
|
-
throw new Error(`class does not inherit from Koatty`);
|
864
|
-
}
|
865
|
-
executeBootstrap(target, bootFunc);
|
866
|
-
};
|
867
|
-
}
|
868
|
-
/**
|
869
|
-
* Actively perform dependency injection
|
870
|
-
* Parse the decorator, return the instantiated app.
|
871
|
-
* @export ExecBootStrap
|
872
|
-
* @param {Function} [bootFunc] callback function
|
873
|
-
* @returns
|
874
|
-
*/
|
875
|
-
function ExecBootStrap(bootFunc) {
|
876
|
-
return async (target) => {
|
877
|
-
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
878
|
-
throw new Error(`class ${target.name} does not inherit from Koatty`);
|
879
|
-
}
|
880
|
-
return await executeBootstrap(target, bootFunc, true);
|
881
|
-
};
|
882
|
-
}
|
883
|
-
/**
|
884
|
-
* Define project scan path
|
885
|
-
*
|
886
|
-
* @export
|
887
|
-
* @param {(string | string[])} [scanPath]
|
888
|
-
* @returns {ClassDecorator}
|
889
|
-
*/
|
890
|
-
function ComponentScan(scanPath) {
|
891
|
-
return (target) => {
|
892
|
-
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
893
|
-
throw new Error(`class does not inherit from Koatty`);
|
894
|
-
}
|
895
|
-
scanPath = scanPath ?? '';
|
896
|
-
koatty_container.IOCContainer.saveClassMetadata(koatty_container.TAGGED_CLS, COMPONENT_SCAN, scanPath, target);
|
897
|
-
};
|
898
|
-
}
|
899
|
-
/**
|
900
|
-
* Define project configuration scan path
|
901
|
-
*
|
902
|
-
* @export
|
903
|
-
* @param {(string | string[])} [scanPath]
|
904
|
-
* @returns {ClassDecorator}
|
905
|
-
*/
|
906
|
-
function ConfigurationScan(scanPath) {
|
907
|
-
return (target) => {
|
908
|
-
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
909
|
-
throw new Error(`class does not inherit from Koatty`);
|
910
|
-
}
|
911
|
-
scanPath = scanPath ?? '';
|
912
|
-
koatty_container.IOCContainer.saveClassMetadata(koatty_container.TAGGED_CLS, CONFIGURATION_SCAN, scanPath, target);
|
913
|
-
};
|
914
|
-
}
|
915
|
-
/**
|
916
|
-
* @description: bind App event hook func
|
917
|
-
* example:
|
918
|
-
* export function TestDecorator(): ClassDecorator {
|
919
|
-
* return (target: Function) => {
|
920
|
-
* BindEventHook(AppEvent.appBoot, (app: Koatty) => {
|
921
|
-
* // todo
|
922
|
-
* return Promise.resolve();
|
923
|
-
* }, target)
|
924
|
-
* }
|
925
|
-
* }
|
926
|
-
* @param {AppEvent} eventName
|
927
|
-
* @param {EventHookFunc} eventFunc
|
928
|
-
* @param {any} target
|
929
|
-
* @return {*}
|
930
|
-
*/
|
931
|
-
function BindEventHook(eventName, eventFunc, target) {
|
932
|
-
koatty_container.IOCContainer.attachClassMetadata(koatty_container.TAGGED_CLS, eventName, eventFunc, target);
|
717
|
+
/*
|
718
|
+
* @Description: framework bootstrap
|
719
|
+
* @Usage:
|
720
|
+
* @Author: richen
|
721
|
+
* @Date: 2023-12-09 21:56:32
|
722
|
+
* @LastEditTime: 2023-12-14 23:06:45
|
723
|
+
* @License: BSD (3-Clause)
|
724
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
725
|
+
*/
|
726
|
+
/**
|
727
|
+
* execute bootstrap
|
728
|
+
*
|
729
|
+
* @param {*} target
|
730
|
+
* @param {Function} bootFunc
|
731
|
+
* @param {boolean} [isInitiative=false] Whether to actively execute app instantiation,
|
732
|
+
* mainly for unittest scenarios, you need to actively obtain app instances
|
733
|
+
* @returns {Promise<void>}
|
734
|
+
*/
|
735
|
+
const executeBootstrap = async function (target, bootFunc, isInitiative = false) {
|
736
|
+
// checked runtime
|
737
|
+
checkRuntime();
|
738
|
+
// unittest running environment
|
739
|
+
const isUTRuntime = checkUTRuntime();
|
740
|
+
if (!isInitiative && isUTRuntime) {
|
741
|
+
return;
|
742
|
+
}
|
743
|
+
const app = Reflect.construct(target, []);
|
744
|
+
// unittest does not print startup logs
|
745
|
+
if (isUTRuntime) {
|
746
|
+
app.silent = true;
|
747
|
+
Logger.enable(false);
|
748
|
+
}
|
749
|
+
try {
|
750
|
+
!app.silent && Logger.Log("Koatty", LOGO);
|
751
|
+
if (!(app instanceof koatty_core.Koatty)) {
|
752
|
+
throw new Error(`class ${target.name} does not inherit from Koatty`);
|
753
|
+
}
|
754
|
+
// Initialize env
|
755
|
+
Loader.initialize(app);
|
756
|
+
// exec bootFunc
|
757
|
+
if (koatty_lib.Helper.isFunction(bootFunc)) {
|
758
|
+
Logger.Log('Koatty', '', 'Execute bootFunc ...');
|
759
|
+
await bootFunc(app);
|
760
|
+
}
|
761
|
+
// Set IOCContainer.app
|
762
|
+
koatty_container.IOCContainer.setApp(app);
|
763
|
+
Logger.Log('Koatty', '', 'ComponentScan ...');
|
764
|
+
// Check all bean
|
765
|
+
Loader.CheckAllComponents(app, target);
|
766
|
+
// Load configuration
|
767
|
+
Logger.Log('Koatty', '', 'Load Configurations ...');
|
768
|
+
// configuration metadata
|
769
|
+
const configurationMetas = Loader.GetConfigurationMetas(app, target);
|
770
|
+
Loader.LoadConfigs(app, configurationMetas);
|
771
|
+
// Load App event hooks
|
772
|
+
Loader.LoadAppEventHooks(app, target);
|
773
|
+
Logger.Log('Koatty', '', 'Emit App Boot ...');
|
774
|
+
await asyncEvent(app, "appBoot" /* AppEvent.appBoot */);
|
775
|
+
// Load Components
|
776
|
+
Logger.Log('Koatty', '', 'Load Components ...');
|
777
|
+
await Loader.LoadComponents(app);
|
778
|
+
// Load Middleware
|
779
|
+
Logger.Log('Koatty', '', 'Load Middlewares ...');
|
780
|
+
await Loader.LoadMiddlewares(app);
|
781
|
+
// Load Services
|
782
|
+
Logger.Log('Koatty', '', 'Load Services ...');
|
783
|
+
Loader.LoadServices(app);
|
784
|
+
// Load Controllers
|
785
|
+
Logger.Log('Koatty', '', 'Load Controllers ...');
|
786
|
+
const controllers = Loader.LoadControllers(app);
|
787
|
+
// Create Server
|
788
|
+
// app.server = newServe(app);
|
789
|
+
koatty_lib.Helper.define(app, "server", koatty_serve.NewServe(app));
|
790
|
+
// Create router
|
791
|
+
// app.router = newRouter(app);
|
792
|
+
koatty_lib.Helper.define(app, "router", koatty_serve.NewRouter(app));
|
793
|
+
// Emit app ready event
|
794
|
+
Logger.Log('Koatty', '', 'Emit App Ready ...');
|
795
|
+
await asyncEvent(app, "appReady" /* AppEvent.appReady */);
|
796
|
+
// Load Routers
|
797
|
+
Logger.Log('Koatty', '', 'Load Routers ...');
|
798
|
+
app.router.LoadRouter(controllers);
|
799
|
+
if (!isUTRuntime) {
|
800
|
+
// Start Server
|
801
|
+
app.listen(listenCallback);
|
802
|
+
}
|
803
|
+
return app;
|
804
|
+
}
|
805
|
+
catch (err) {
|
806
|
+
Logger.Error(err);
|
807
|
+
process.exit();
|
808
|
+
}
|
809
|
+
};
|
810
|
+
/**
|
811
|
+
* Listening callback function
|
812
|
+
*
|
813
|
+
* @param {Koatty} app
|
814
|
+
* @returns {*}
|
815
|
+
*/
|
816
|
+
const listenCallback = (app) => {
|
817
|
+
const options = app.server.options;
|
818
|
+
Logger.Log('Koatty', '', '====================================');
|
819
|
+
Logger.Log("Koatty", "", `Nodejs Version: ${process.version}`);
|
820
|
+
Logger.Log("Koatty", "", `Koatty Version: v${KOATTY_VERSION}`);
|
821
|
+
Logger.Log("Koatty", "", `App Environment: ${app.env}`);
|
822
|
+
Logger.Log('Koatty', '', `Server Protocol: ${(options.protocol).toUpperCase()}`);
|
823
|
+
Logger.Log("Koatty", "", `Server running at ${options.protocol === "http2" ? "https" : options.protocol}://${options.hostname || '127.0.0.1'}:${options.port}/`);
|
824
|
+
Logger.Log("Koatty", "", "====================================");
|
825
|
+
// binding event "appStop"
|
826
|
+
Logger.Log('Koatty', '', 'Bind App Stop event ...');
|
827
|
+
koatty_serve.BindProcessEvent(app, 'appStop');
|
828
|
+
// tslint:disable-next-line: no-unused-expression
|
829
|
+
app.appDebug && Logger.Warn(`Running in debug mode.`);
|
830
|
+
// Set Logger
|
831
|
+
Loader.SetLogger(app);
|
832
|
+
};
|
833
|
+
/**
|
834
|
+
* Execute event as async
|
835
|
+
*
|
836
|
+
* @param {Koatty} event
|
837
|
+
* @param {string} eventName
|
838
|
+
*/
|
839
|
+
const asyncEvent = async function (event, eventName) {
|
840
|
+
const ls = event.listeners(eventName);
|
841
|
+
// eslint-disable-next-line no-restricted-syntax
|
842
|
+
for await (const func of ls) {
|
843
|
+
if (koatty_lib.Helper.isFunction(func)) {
|
844
|
+
func();
|
845
|
+
}
|
846
|
+
}
|
847
|
+
return event.removeAllListeners(eventName);
|
848
|
+
};
|
849
|
+
/**
|
850
|
+
* Bootstrap application
|
851
|
+
*
|
852
|
+
* @export
|
853
|
+
* @param {Function} [bootFunc]
|
854
|
+
* @returns {ClassDecorator}
|
855
|
+
*/
|
856
|
+
function Bootstrap(bootFunc) {
|
857
|
+
return function (target) {
|
858
|
+
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
859
|
+
throw new Error(`class does not inherit from Koatty`);
|
860
|
+
}
|
861
|
+
executeBootstrap(target, bootFunc);
|
862
|
+
};
|
863
|
+
}
|
864
|
+
/**
|
865
|
+
* Actively perform dependency injection
|
866
|
+
* Parse the decorator, return the instantiated app.
|
867
|
+
* @export ExecBootStrap
|
868
|
+
* @param {Function} [bootFunc] callback function
|
869
|
+
* @returns
|
870
|
+
*/
|
871
|
+
function ExecBootStrap(bootFunc) {
|
872
|
+
return async (target) => {
|
873
|
+
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
874
|
+
throw new Error(`class ${target.name} does not inherit from Koatty`);
|
875
|
+
}
|
876
|
+
return await executeBootstrap(target, bootFunc, true);
|
877
|
+
};
|
878
|
+
}
|
879
|
+
/**
|
880
|
+
* Define project scan path
|
881
|
+
*
|
882
|
+
* @export
|
883
|
+
* @param {(string | string[])} [scanPath]
|
884
|
+
* @returns {ClassDecorator}
|
885
|
+
*/
|
886
|
+
function ComponentScan(scanPath) {
|
887
|
+
return (target) => {
|
888
|
+
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
889
|
+
throw new Error(`class does not inherit from Koatty`);
|
890
|
+
}
|
891
|
+
scanPath = scanPath ?? '';
|
892
|
+
koatty_container.IOCContainer.saveClassMetadata(koatty_container.TAGGED_CLS, COMPONENT_SCAN, scanPath, target);
|
893
|
+
};
|
894
|
+
}
|
895
|
+
/**
|
896
|
+
* Define project configuration scan path
|
897
|
+
*
|
898
|
+
* @export
|
899
|
+
* @param {(string | string[])} [scanPath]
|
900
|
+
* @returns {ClassDecorator}
|
901
|
+
*/
|
902
|
+
function ConfigurationScan(scanPath) {
|
903
|
+
return (target) => {
|
904
|
+
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
905
|
+
throw new Error(`class does not inherit from Koatty`);
|
906
|
+
}
|
907
|
+
scanPath = scanPath ?? '';
|
908
|
+
koatty_container.IOCContainer.saveClassMetadata(koatty_container.TAGGED_CLS, CONFIGURATION_SCAN, scanPath, target);
|
909
|
+
};
|
910
|
+
}
|
911
|
+
/**
|
912
|
+
* @description: bind App event hook func
|
913
|
+
* example:
|
914
|
+
* export function TestDecorator(): ClassDecorator {
|
915
|
+
* return (target: Function) => {
|
916
|
+
* BindEventHook(AppEvent.appBoot, (app: Koatty) => {
|
917
|
+
* // todo
|
918
|
+
* return Promise.resolve();
|
919
|
+
* }, target)
|
920
|
+
* }
|
921
|
+
* }
|
922
|
+
* @param {AppEvent} eventName
|
923
|
+
* @param {EventHookFunc} eventFunc
|
924
|
+
* @param {any} target
|
925
|
+
* @return {*}
|
926
|
+
*/
|
927
|
+
function BindEventHook(eventName, eventFunc, target) {
|
928
|
+
koatty_container.IOCContainer.attachClassMetadata(koatty_container.TAGGED_CLS, eventName, eventFunc, target);
|
933
929
|
}
|
934
930
|
|
935
|
-
/*
|
936
|
-
* @Description: component interface
|
937
|
-
* @Usage:
|
938
|
-
* @Author: richen
|
939
|
-
* @Date: 2023-12-09 21:56:32
|
940
|
-
* @LastEditTime: 2023-12-09 23:03:33
|
941
|
-
* @License: BSD (3-Clause)
|
942
|
-
* @Copyright (c): <richenlin(at)gmail.com>
|
943
|
-
*/
|
944
|
-
|
945
|
-
|
946
|
-
*
|
947
|
-
*
|
948
|
-
* @
|
949
|
-
* @
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
koatty_container.IOCContainer.
|
955
|
-
|
956
|
-
}
|
957
|
-
|
958
|
-
|
959
|
-
*
|
960
|
-
*
|
961
|
-
* @
|
962
|
-
* @
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
koatty_container.IOCContainer.
|
968
|
-
koatty_container.IOCContainer.
|
969
|
-
|
970
|
-
}
|
971
|
-
|
972
|
-
|
973
|
-
*
|
974
|
-
*
|
975
|
-
* @
|
976
|
-
* @
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
koatty_container.IOCContainer.
|
982
|
-
|
983
|
-
}
|
984
|
-
|
985
|
-
|
986
|
-
*
|
987
|
-
*
|
988
|
-
* @
|
989
|
-
* @
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
koatty_container.IOCContainer.
|
995
|
-
|
996
|
-
}
|
997
|
-
|
998
|
-
|
999
|
-
*
|
1000
|
-
*
|
1001
|
-
* @
|
1002
|
-
* @
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
931
|
+
/*
|
932
|
+
* @Description: component interface
|
933
|
+
* @Usage:
|
934
|
+
* @Author: richen
|
935
|
+
* @Date: 2023-12-09 21:56:32
|
936
|
+
* @LastEditTime: 2023-12-09 23:03:33
|
937
|
+
* @License: BSD (3-Clause)
|
938
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
939
|
+
*/
|
940
|
+
// tslint:disable-next-line: no-import-side-effect
|
941
|
+
/**
|
942
|
+
* Indicates that an decorated class is a "component".
|
943
|
+
*
|
944
|
+
* @export
|
945
|
+
* @param {string} [identifier] component name
|
946
|
+
* @returns {ClassDecorator}
|
947
|
+
*/
|
948
|
+
function Component(identifier) {
|
949
|
+
return (target) => {
|
950
|
+
identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
|
951
|
+
koatty_container.IOCContainer.saveClass("COMPONENT", target, identifier);
|
952
|
+
};
|
953
|
+
}
|
954
|
+
/**
|
955
|
+
* Indicates that an decorated class is a "controller".
|
956
|
+
*
|
957
|
+
* @export
|
958
|
+
* @param {string} [path] controller router path
|
959
|
+
* @returns {ClassDecorator}
|
960
|
+
*/
|
961
|
+
function Controller(path = "") {
|
962
|
+
return (target) => {
|
963
|
+
const identifier = koatty_container.IOCContainer.getIdentifier(target);
|
964
|
+
koatty_container.IOCContainer.saveClass("CONTROLLER", target, identifier);
|
965
|
+
koatty_container.IOCContainer.savePropertyData(koatty_serve.CONTROLLER_ROUTER, path, target, identifier);
|
966
|
+
};
|
967
|
+
}
|
968
|
+
/**
|
969
|
+
* Indicates that an decorated class is a "middleware".
|
970
|
+
*
|
971
|
+
* @export
|
972
|
+
* @param {string} [identifier] class name
|
973
|
+
* @returns {ClassDecorator}
|
974
|
+
*/
|
975
|
+
function Middleware(identifier) {
|
976
|
+
return (target) => {
|
977
|
+
identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
|
978
|
+
koatty_container.IOCContainer.saveClass("MIDDLEWARE", target, identifier);
|
979
|
+
};
|
980
|
+
}
|
981
|
+
/**
|
982
|
+
* Indicates that an decorated class is a "service".
|
983
|
+
*
|
984
|
+
* @export
|
985
|
+
* @param {string} [identifier] class name
|
986
|
+
* @returns {ClassDecorator}
|
987
|
+
*/
|
988
|
+
function Service(identifier) {
|
989
|
+
return (target) => {
|
990
|
+
identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
|
991
|
+
koatty_container.IOCContainer.saveClass("SERVICE", target, identifier);
|
992
|
+
};
|
993
|
+
}
|
994
|
+
/**
|
995
|
+
* Indicates that an decorated class is a "plugin".
|
996
|
+
*
|
997
|
+
* @export
|
998
|
+
* @param {string} [identifier] class name
|
999
|
+
* @returns {ClassDecorator}
|
1000
|
+
*/
|
1001
|
+
function Plugin(identifier) {
|
1002
|
+
return (target) => {
|
1003
|
+
identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
|
1004
|
+
//
|
1005
|
+
if (!identifier.endsWith("Plugin")) {
|
1006
|
+
throw Error("Plugin class name must be 'Plugin' suffix.");
|
1007
|
+
}
|
1008
|
+
koatty_container.IOCContainer.saveClass("COMPONENT", target, `${identifier}`);
|
1009
|
+
};
|
1013
1010
|
}
|
1014
1011
|
|
1015
|
-
/*
|
1016
|
-
* @Description: base service
|
1017
|
-
* @Usage:
|
1018
|
-
* @Author: richen
|
1019
|
-
* @Date: 2023-12-09 21:56:32
|
1020
|
-
* @LastEditTime: 2023-12-09 23:03:23
|
1021
|
-
* @License: BSD (3-Clause)
|
1022
|
-
* @Copyright (c): <richenlin(at)gmail.com>
|
1023
|
-
*/
|
1024
|
-
/**
|
1025
|
-
* Base service
|
1026
|
-
*
|
1027
|
-
* @export
|
1028
|
-
* @class Base
|
1029
|
-
*/
|
1030
|
-
class BaseService {
|
1031
|
-
/**
|
1032
|
-
* instance of BaseController.
|
1033
|
-
* @param {Koatty} app
|
1034
|
-
* @param {KoattyContext} ctx
|
1035
|
-
* @memberof BaseController
|
1036
|
-
*/
|
1037
|
-
constructor(...arg) {
|
1038
|
-
this.init(arg);
|
1039
|
-
}
|
1040
|
-
/**
|
1041
|
-
* init
|
1042
|
-
*
|
1043
|
-
* @protected
|
1044
|
-
* @memberof BaseController
|
1045
|
-
*/
|
1046
|
-
init(...arg) {
|
1047
|
-
}
|
1012
|
+
/*
|
1013
|
+
* @Description: base service
|
1014
|
+
* @Usage:
|
1015
|
+
* @Author: richen
|
1016
|
+
* @Date: 2023-12-09 21:56:32
|
1017
|
+
* @LastEditTime: 2023-12-09 23:03:23
|
1018
|
+
* @License: BSD (3-Clause)
|
1019
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
1020
|
+
*/
|
1021
|
+
/**
|
1022
|
+
* Base service
|
1023
|
+
*
|
1024
|
+
* @export
|
1025
|
+
* @class Base
|
1026
|
+
*/
|
1027
|
+
class BaseService {
|
1028
|
+
/**
|
1029
|
+
* instance of BaseController.
|
1030
|
+
* @param {Koatty} app
|
1031
|
+
* @param {KoattyContext} ctx
|
1032
|
+
* @memberof BaseController
|
1033
|
+
*/
|
1034
|
+
constructor(...arg) {
|
1035
|
+
this.init(arg);
|
1036
|
+
}
|
1037
|
+
/**
|
1038
|
+
* init
|
1039
|
+
*
|
1040
|
+
* @protected
|
1041
|
+
* @memberof BaseController
|
1042
|
+
*/
|
1043
|
+
init(...arg) {
|
1044
|
+
}
|
1048
1045
|
}
|
1049
1046
|
|
1050
1047
|
Object.defineProperty(exports, 'Config', {
|
@@ -1073,31 +1070,31 @@ exports.Middleware = Middleware;
|
|
1073
1070
|
exports.Plugin = Plugin;
|
1074
1071
|
exports.Service = Service;
|
1075
1072
|
Object.keys(koatty_core).forEach(function (k) {
|
1076
|
-
if (k !== 'default' && !
|
1073
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
1077
1074
|
enumerable: true,
|
1078
1075
|
get: function () { return koatty_core[k]; }
|
1079
1076
|
});
|
1080
1077
|
});
|
1081
1078
|
Object.keys(koatty_exception).forEach(function (k) {
|
1082
|
-
if (k !== 'default' && !
|
1079
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
1083
1080
|
enumerable: true,
|
1084
1081
|
get: function () { return koatty_exception[k]; }
|
1085
1082
|
});
|
1086
1083
|
});
|
1087
1084
|
Object.keys(koatty_container).forEach(function (k) {
|
1088
|
-
if (k !== 'default' && !
|
1085
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
1089
1086
|
enumerable: true,
|
1090
1087
|
get: function () { return koatty_container[k]; }
|
1091
1088
|
});
|
1092
1089
|
});
|
1093
1090
|
Object.keys(koatty_trace).forEach(function (k) {
|
1094
|
-
if (k !== 'default' && !
|
1091
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
1095
1092
|
enumerable: true,
|
1096
1093
|
get: function () { return koatty_trace[k]; }
|
1097
1094
|
});
|
1098
1095
|
});
|
1099
1096
|
Object.keys(koatty_serve).forEach(function (k) {
|
1100
|
-
if (k !== 'default' && !
|
1097
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
1101
1098
|
enumerable: true,
|
1102
1099
|
get: function () { return koatty_serve[k]; }
|
1103
1100
|
});
|