koatty 3.10.4-1 → 3.10.4-3
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/CHANGELOG.md +10 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +978 -985
- package/dist/index.mjs +973 -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-16 14:47:37
|
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,874 @@ 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
|
+
async 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(await 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
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
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
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
}
|
659
|
-
|
660
|
-
|
661
|
-
continue;
|
662
|
-
}
|
663
|
-
if (pluginsConf.config[key] === false) {
|
664
|
-
Logger.Warn(`Plugin ${key} already loaded but not effective.`);
|
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-16 14:46:25
|
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 tracing middleware
|
512
|
+
await 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
|
+
throw Error(`Middleware ${key} load error.`);
|
539
|
+
}
|
540
|
+
if (!koatty_lib.Helper.isFunction(handle.run)) {
|
541
|
+
throw Error(`The middleware ${key} must implements interface 'IMiddleware'.`);
|
542
|
+
}
|
543
|
+
if (middlewareConf.config[key] === false) {
|
544
|
+
Logger.Warn(`The middleware ${key} has been loaded but not executed.`);
|
545
|
+
continue;
|
546
|
+
}
|
547
|
+
Logger.Debug(`Load middleware: ${key}`);
|
548
|
+
const result = await handle.run(middlewareConf.config[key] || {}, app);
|
549
|
+
if (koatty_lib.Helper.isFunction(result)) {
|
550
|
+
if (result.length < 3) {
|
551
|
+
app.use(result);
|
552
|
+
}
|
553
|
+
else {
|
554
|
+
app.useExp(result);
|
555
|
+
}
|
556
|
+
}
|
557
|
+
}
|
558
|
+
}
|
559
|
+
/**
|
560
|
+
* Load controllers
|
561
|
+
*
|
562
|
+
* @static
|
563
|
+
* @param {*} app
|
564
|
+
* @memberof Loader
|
565
|
+
*/
|
566
|
+
static LoadControllers(app) {
|
567
|
+
const controllerList = koatty_container.IOCContainer.listClass("CONTROLLER");
|
568
|
+
const controllers = [];
|
569
|
+
controllerList.forEach((item) => {
|
570
|
+
item.id = (item.id ?? "").replace("CONTROLLER:", "");
|
571
|
+
if (item.id && koatty_lib.Helper.isClass(item.target)) {
|
572
|
+
Logger.Debug(`Load controller: ${item.id}`);
|
573
|
+
// registering to IOC
|
574
|
+
koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "CONTROLLER", args: [] });
|
575
|
+
const ctl = koatty_container.IOCContainer.getInsByClass(item.target);
|
576
|
+
if (!(ctl instanceof BaseController)) {
|
577
|
+
throw Error(`Controller class ${item.id} does not inherit from BaseController`);
|
578
|
+
}
|
579
|
+
controllers.push(item.id);
|
580
|
+
}
|
581
|
+
});
|
582
|
+
return controllers;
|
583
|
+
}
|
584
|
+
/**
|
585
|
+
* Load services
|
586
|
+
*
|
587
|
+
* @static
|
588
|
+
* @param {*} app
|
589
|
+
* @memberof Loader
|
590
|
+
*/
|
591
|
+
static LoadServices(app) {
|
592
|
+
const serviceList = koatty_container.IOCContainer.listClass("SERVICE");
|
593
|
+
serviceList.forEach((item) => {
|
594
|
+
item.id = (item.id ?? "").replace("SERVICE:", "");
|
595
|
+
if (item.id && koatty_lib.Helper.isClass(item.target)) {
|
596
|
+
Logger.Debug(`Load service: ${item.id}`);
|
597
|
+
// registering to IOC
|
598
|
+
koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "SERVICE", args: [] });
|
599
|
+
}
|
600
|
+
});
|
601
|
+
}
|
602
|
+
/**
|
603
|
+
* Load components
|
604
|
+
*
|
605
|
+
* @static
|
606
|
+
* @param {*} app
|
607
|
+
* @memberof Loader
|
608
|
+
*/
|
609
|
+
// public static LoadComponents(app: Koatty) {
|
610
|
+
// const componentList = IOCContainer.listClass("COMPONENT");
|
611
|
+
// componentList.forEach((item: ComponentItem) => {
|
612
|
+
// item.id = (item.id ?? "").replace("COMPONENT:", "");
|
613
|
+
// if (item.id && !(item.id).endsWith("Plugin") && Helper.isClass(item.target)) {
|
614
|
+
// Logger.Debug(`Load component: ${item.id}`);
|
615
|
+
// // registering to IOC
|
616
|
+
// IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
|
617
|
+
// }
|
618
|
+
// });
|
619
|
+
// }
|
620
|
+
/**
|
621
|
+
* Load components
|
622
|
+
*
|
623
|
+
* @static
|
624
|
+
* @param {*} app
|
625
|
+
* @memberof Loader
|
626
|
+
*/
|
627
|
+
static async LoadComponents(app) {
|
628
|
+
const componentList = koatty_container.IOCContainer.listClass("COMPONENT");
|
629
|
+
const pluginList = [];
|
630
|
+
componentList.forEach(async (item) => {
|
631
|
+
item.id = (item.id ?? "").replace("COMPONENT:", "");
|
632
|
+
if (koatty_lib.Helper.isClass(item.target)) {
|
633
|
+
if (item.id && (item.id).endsWith("Plugin")) {
|
634
|
+
pluginList.push(item.id);
|
635
|
+
}
|
636
|
+
// registering to IOC
|
637
|
+
koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
|
638
|
+
}
|
639
|
+
});
|
640
|
+
// load plugin config
|
641
|
+
let pluginsConf = app.config(undefined, "plugin");
|
642
|
+
if (koatty_lib.Helper.isEmpty(pluginsConf)) {
|
643
|
+
pluginsConf = { config: {}, list: [] };
|
644
|
+
}
|
645
|
+
const pluginConfList = pluginsConf.list ?? [];
|
646
|
+
// load plugin list
|
647
|
+
for (const key of pluginConfList) {
|
648
|
+
const handle = koatty_container.IOCContainer.get(key, "COMPONENT");
|
649
|
+
if (!handle) {
|
650
|
+
throw Error(`Plugin ${key} load error.`);
|
651
|
+
}
|
652
|
+
if (!koatty_lib.Helper.isFunction(handle.run)) {
|
653
|
+
throw Error(`Plugin ${key} must implements interface 'IPlugin'.`);
|
654
|
+
}
|
655
|
+
if (pluginsConf.config[key] === false) {
|
656
|
+
Logger.Warn(`Plugin ${key} already loaded but not effective.`);
|
657
|
+
continue;
|
658
|
+
}
|
659
|
+
// sync exec
|
660
|
+
await handle.run(pluginsConf.config[key] ?? {}, app);
|
661
|
+
}
|
662
|
+
}
|
671
663
|
}
|
672
664
|
|
673
|
-
var version = "3.10.4-
|
665
|
+
var version = "3.10.4-3";
|
674
666
|
var engines = {
|
675
667
|
node: ">12.0.0"
|
676
668
|
};
|
677
669
|
|
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;
|
670
|
+
/*
|
671
|
+
* @Description: framework runtime checker
|
672
|
+
* @Usage:
|
673
|
+
* @Author: richen
|
674
|
+
* @Date: 2023-12-09 21:56:32
|
675
|
+
* @LastEditTime: 2023-12-09 23:01:22
|
676
|
+
* @License: BSD (3-Clause)
|
677
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
678
|
+
*/
|
679
|
+
const KOATTY_VERSION = version;
|
680
|
+
const ENGINES_VERSION = engines.node.slice(1) || '12.0.0';
|
681
|
+
/**
|
682
|
+
* check node version
|
683
|
+
* @return {void} []
|
684
|
+
*/
|
685
|
+
function checkRuntime() {
|
686
|
+
let nodeEngines = ENGINES_VERSION;
|
687
|
+
nodeEngines = nodeEngines.slice(0, nodeEngines.lastIndexOf('.'));
|
688
|
+
let nodeVersion = process.version;
|
689
|
+
if (nodeVersion[0] === 'v') {
|
690
|
+
nodeVersion = nodeVersion.slice(1);
|
691
|
+
}
|
692
|
+
nodeVersion = nodeVersion.slice(0, nodeVersion.lastIndexOf('.'));
|
693
|
+
if (koatty_lib.Helper.toNumber(nodeEngines) > koatty_lib.Helper.toNumber(nodeVersion)) {
|
694
|
+
Logger.Error(`Koatty need node version > ${nodeEngines}, current version is ${nodeVersion}, please upgrade it.`);
|
695
|
+
process.exit(-1);
|
696
|
+
}
|
697
|
+
}
|
698
|
+
/**
|
699
|
+
* unittest running environment detection
|
700
|
+
* only support jest
|
701
|
+
* @returns {boolean}
|
702
|
+
*/
|
703
|
+
const checkUTRuntime = () => {
|
704
|
+
let isUTRuntime = false;
|
705
|
+
// UT运行环境判断,暂时先只判断jest
|
706
|
+
const argv = JSON.stringify(process.argv[1]);
|
707
|
+
if (argv.indexOf('jest') > -1) {
|
708
|
+
isUTRuntime = true;
|
709
|
+
}
|
710
|
+
return isUTRuntime;
|
719
711
|
};
|
720
712
|
|
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);
|
713
|
+
/*
|
714
|
+
* @Description: framework bootstrap
|
715
|
+
* @Usage:
|
716
|
+
* @Author: richen
|
717
|
+
* @Date: 2023-12-09 21:56:32
|
718
|
+
* @LastEditTime: 2023-12-14 23:06:45
|
719
|
+
* @License: BSD (3-Clause)
|
720
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
721
|
+
*/
|
722
|
+
/**
|
723
|
+
* execute bootstrap
|
724
|
+
*
|
725
|
+
* @param {*} target
|
726
|
+
* @param {Function} bootFunc
|
727
|
+
* @param {boolean} [isInitiative=false] Whether to actively execute app instantiation,
|
728
|
+
* mainly for unittest scenarios, you need to actively obtain app instances
|
729
|
+
* @returns {Promise<void>}
|
730
|
+
*/
|
731
|
+
const executeBootstrap = async function (target, bootFunc, isInitiative = false) {
|
732
|
+
// checked runtime
|
733
|
+
checkRuntime();
|
734
|
+
// unittest running environment
|
735
|
+
const isUTRuntime = checkUTRuntime();
|
736
|
+
if (!isInitiative && isUTRuntime) {
|
737
|
+
return;
|
738
|
+
}
|
739
|
+
const app = Reflect.construct(target, []);
|
740
|
+
// unittest does not print startup logs
|
741
|
+
if (isUTRuntime) {
|
742
|
+
app.silent = true;
|
743
|
+
Logger.enable(false);
|
744
|
+
}
|
745
|
+
try {
|
746
|
+
!app.silent && Logger.Log("Koatty", LOGO);
|
747
|
+
if (!(app instanceof koatty_core.Koatty)) {
|
748
|
+
throw new Error(`class ${target.name} does not inherit from Koatty`);
|
749
|
+
}
|
750
|
+
// Initialize env
|
751
|
+
Loader.initialize(app);
|
752
|
+
// exec bootFunc
|
753
|
+
if (koatty_lib.Helper.isFunction(bootFunc)) {
|
754
|
+
Logger.Log('Koatty', '', 'Execute bootFunc ...');
|
755
|
+
await bootFunc(app);
|
756
|
+
}
|
757
|
+
// Set IOCContainer.app
|
758
|
+
koatty_container.IOCContainer.setApp(app);
|
759
|
+
Logger.Log('Koatty', '', 'ComponentScan ...');
|
760
|
+
// Check all bean
|
761
|
+
Loader.CheckAllComponents(app, target);
|
762
|
+
// Load configuration
|
763
|
+
Logger.Log('Koatty', '', 'Load Configurations ...');
|
764
|
+
// configuration metadata
|
765
|
+
const configurationMetas = Loader.GetConfigurationMetas(app, target);
|
766
|
+
Loader.LoadConfigs(app, configurationMetas);
|
767
|
+
// Load App event hooks
|
768
|
+
Loader.LoadAppEventHooks(app, target);
|
769
|
+
Logger.Log('Koatty', '', 'Emit App Boot ...');
|
770
|
+
await asyncEvent(app, "appBoot" /* AppEvent.appBoot */);
|
771
|
+
// Load Components
|
772
|
+
Logger.Log('Koatty', '', 'Load Components ...');
|
773
|
+
await Loader.LoadComponents(app);
|
774
|
+
// Load Middleware
|
775
|
+
Logger.Log('Koatty', '', 'Load Middlewares ...');
|
776
|
+
await Loader.LoadMiddlewares(app);
|
777
|
+
// Load Services
|
778
|
+
Logger.Log('Koatty', '', 'Load Services ...');
|
779
|
+
Loader.LoadServices(app);
|
780
|
+
// Load Controllers
|
781
|
+
Logger.Log('Koatty', '', 'Load Controllers ...');
|
782
|
+
const controllers = Loader.LoadControllers(app);
|
783
|
+
// Create Server
|
784
|
+
// app.server = newServe(app);
|
785
|
+
koatty_lib.Helper.define(app, "server", koatty_serve.NewServe(app));
|
786
|
+
// Create router
|
787
|
+
// app.router = newRouter(app);
|
788
|
+
koatty_lib.Helper.define(app, "router", koatty_serve.NewRouter(app));
|
789
|
+
// Emit app ready event
|
790
|
+
Logger.Log('Koatty', '', 'Emit App Ready ...');
|
791
|
+
await asyncEvent(app, "appReady" /* AppEvent.appReady */);
|
792
|
+
// Load Routers
|
793
|
+
Logger.Log('Koatty', '', 'Load Routers ...');
|
794
|
+
app.router.LoadRouter(controllers);
|
795
|
+
if (!isUTRuntime) {
|
796
|
+
// Start Server
|
797
|
+
app.listen(listenCallback);
|
798
|
+
}
|
799
|
+
return app;
|
800
|
+
}
|
801
|
+
catch (err) {
|
802
|
+
Logger.Error(err);
|
803
|
+
process.exit();
|
804
|
+
}
|
805
|
+
};
|
806
|
+
/**
|
807
|
+
* Listening callback function
|
808
|
+
*
|
809
|
+
* @param {Koatty} app
|
810
|
+
* @returns {*}
|
811
|
+
*/
|
812
|
+
const listenCallback = (app) => {
|
813
|
+
const options = app.server.options;
|
814
|
+
Logger.Log('Koatty', '', '====================================');
|
815
|
+
Logger.Log("Koatty", "", `Nodejs Version: ${process.version}`);
|
816
|
+
Logger.Log("Koatty", "", `Koatty Version: v${KOATTY_VERSION}`);
|
817
|
+
Logger.Log("Koatty", "", `App Environment: ${app.env}`);
|
818
|
+
Logger.Log('Koatty', '', `Server Protocol: ${(options.protocol).toUpperCase()}`);
|
819
|
+
Logger.Log("Koatty", "", `Server running at ${options.protocol === "http2" ? "https" : options.protocol}://${options.hostname || '127.0.0.1'}:${options.port}/`);
|
820
|
+
Logger.Log("Koatty", "", "====================================");
|
821
|
+
// binding event "appStop"
|
822
|
+
Logger.Log('Koatty', '', 'Bind App Stop event ...');
|
823
|
+
koatty_serve.BindProcessEvent(app, 'appStop');
|
824
|
+
// tslint:disable-next-line: no-unused-expression
|
825
|
+
app.appDebug && Logger.Warn(`Running in debug mode.`);
|
826
|
+
// Set Logger
|
827
|
+
Loader.SetLogger(app);
|
828
|
+
};
|
829
|
+
/**
|
830
|
+
* Execute event as async
|
831
|
+
*
|
832
|
+
* @param {Koatty} event
|
833
|
+
* @param {string} eventName
|
834
|
+
*/
|
835
|
+
const asyncEvent = async function (event, eventName) {
|
836
|
+
const ls = event.listeners(eventName);
|
837
|
+
// eslint-disable-next-line no-restricted-syntax
|
838
|
+
for await (const func of ls) {
|
839
|
+
if (koatty_lib.Helper.isFunction(func)) {
|
840
|
+
func();
|
841
|
+
}
|
842
|
+
}
|
843
|
+
return event.removeAllListeners(eventName);
|
844
|
+
};
|
845
|
+
/**
|
846
|
+
* Bootstrap application
|
847
|
+
*
|
848
|
+
* @export
|
849
|
+
* @param {Function} [bootFunc]
|
850
|
+
* @returns {ClassDecorator}
|
851
|
+
*/
|
852
|
+
function Bootstrap(bootFunc) {
|
853
|
+
return function (target) {
|
854
|
+
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
855
|
+
throw new Error(`class does not inherit from Koatty`);
|
856
|
+
}
|
857
|
+
executeBootstrap(target, bootFunc);
|
858
|
+
};
|
859
|
+
}
|
860
|
+
/**
|
861
|
+
* Actively perform dependency injection
|
862
|
+
* Parse the decorator, return the instantiated app.
|
863
|
+
* @export ExecBootStrap
|
864
|
+
* @param {Function} [bootFunc] callback function
|
865
|
+
* @returns
|
866
|
+
*/
|
867
|
+
function ExecBootStrap(bootFunc) {
|
868
|
+
return async (target) => {
|
869
|
+
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
870
|
+
throw new Error(`class ${target.name} does not inherit from Koatty`);
|
871
|
+
}
|
872
|
+
return await executeBootstrap(target, bootFunc, true);
|
873
|
+
};
|
874
|
+
}
|
875
|
+
/**
|
876
|
+
* Define project scan path
|
877
|
+
*
|
878
|
+
* @export
|
879
|
+
* @param {(string | string[])} [scanPath]
|
880
|
+
* @returns {ClassDecorator}
|
881
|
+
*/
|
882
|
+
function ComponentScan(scanPath) {
|
883
|
+
return (target) => {
|
884
|
+
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
885
|
+
throw new Error(`class does not inherit from Koatty`);
|
886
|
+
}
|
887
|
+
scanPath = scanPath ?? '';
|
888
|
+
koatty_container.IOCContainer.saveClassMetadata(koatty_container.TAGGED_CLS, COMPONENT_SCAN, scanPath, target);
|
889
|
+
};
|
890
|
+
}
|
891
|
+
/**
|
892
|
+
* Define project configuration scan path
|
893
|
+
*
|
894
|
+
* @export
|
895
|
+
* @param {(string | string[])} [scanPath]
|
896
|
+
* @returns {ClassDecorator}
|
897
|
+
*/
|
898
|
+
function ConfigurationScan(scanPath) {
|
899
|
+
return (target) => {
|
900
|
+
if (!(target.prototype instanceof koatty_core.Koatty)) {
|
901
|
+
throw new Error(`class does not inherit from Koatty`);
|
902
|
+
}
|
903
|
+
scanPath = scanPath ?? '';
|
904
|
+
koatty_container.IOCContainer.saveClassMetadata(koatty_container.TAGGED_CLS, CONFIGURATION_SCAN, scanPath, target);
|
905
|
+
};
|
906
|
+
}
|
907
|
+
/**
|
908
|
+
* @description: bind App event hook func
|
909
|
+
* example:
|
910
|
+
* export function TestDecorator(): ClassDecorator {
|
911
|
+
* return (target: Function) => {
|
912
|
+
* BindEventHook(AppEvent.appBoot, (app: Koatty) => {
|
913
|
+
* // todo
|
914
|
+
* return Promise.resolve();
|
915
|
+
* }, target)
|
916
|
+
* }
|
917
|
+
* }
|
918
|
+
* @param {AppEvent} eventName
|
919
|
+
* @param {EventHookFunc} eventFunc
|
920
|
+
* @param {any} target
|
921
|
+
* @return {*}
|
922
|
+
*/
|
923
|
+
function BindEventHook(eventName, eventFunc, target) {
|
924
|
+
koatty_container.IOCContainer.attachClassMetadata(koatty_container.TAGGED_CLS, eventName, eventFunc, target);
|
933
925
|
}
|
934
926
|
|
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
|
-
|
927
|
+
/*
|
928
|
+
* @Description: component interface
|
929
|
+
* @Usage:
|
930
|
+
* @Author: richen
|
931
|
+
* @Date: 2023-12-09 21:56:32
|
932
|
+
* @LastEditTime: 2023-12-09 23:03:33
|
933
|
+
* @License: BSD (3-Clause)
|
934
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
935
|
+
*/
|
936
|
+
// tslint:disable-next-line: no-import-side-effect
|
937
|
+
/**
|
938
|
+
* Indicates that an decorated class is a "component".
|
939
|
+
*
|
940
|
+
* @export
|
941
|
+
* @param {string} [identifier] component name
|
942
|
+
* @returns {ClassDecorator}
|
943
|
+
*/
|
944
|
+
function Component(identifier) {
|
945
|
+
return (target) => {
|
946
|
+
identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
|
947
|
+
koatty_container.IOCContainer.saveClass("COMPONENT", target, identifier);
|
948
|
+
};
|
949
|
+
}
|
950
|
+
/**
|
951
|
+
* Indicates that an decorated class is a "controller".
|
952
|
+
*
|
953
|
+
* @export
|
954
|
+
* @param {string} [path] controller router path
|
955
|
+
* @returns {ClassDecorator}
|
956
|
+
*/
|
957
|
+
function Controller(path = "") {
|
958
|
+
return (target) => {
|
959
|
+
const identifier = koatty_container.IOCContainer.getIdentifier(target);
|
960
|
+
koatty_container.IOCContainer.saveClass("CONTROLLER", target, identifier);
|
961
|
+
koatty_container.IOCContainer.savePropertyData(koatty_serve.CONTROLLER_ROUTER, path, target, identifier);
|
962
|
+
};
|
963
|
+
}
|
964
|
+
/**
|
965
|
+
* Indicates that an decorated class is a "middleware".
|
966
|
+
*
|
967
|
+
* @export
|
968
|
+
* @param {string} [identifier] class name
|
969
|
+
* @returns {ClassDecorator}
|
970
|
+
*/
|
971
|
+
function Middleware(identifier) {
|
972
|
+
return (target) => {
|
973
|
+
identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
|
974
|
+
koatty_container.IOCContainer.saveClass("MIDDLEWARE", target, identifier);
|
975
|
+
};
|
976
|
+
}
|
977
|
+
/**
|
978
|
+
* Indicates that an decorated class is a "service".
|
979
|
+
*
|
980
|
+
* @export
|
981
|
+
* @param {string} [identifier] class name
|
982
|
+
* @returns {ClassDecorator}
|
983
|
+
*/
|
984
|
+
function Service(identifier) {
|
985
|
+
return (target) => {
|
986
|
+
identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
|
987
|
+
koatty_container.IOCContainer.saveClass("SERVICE", target, identifier);
|
988
|
+
};
|
989
|
+
}
|
990
|
+
/**
|
991
|
+
* Indicates that an decorated class is a "plugin".
|
992
|
+
*
|
993
|
+
* @export
|
994
|
+
* @param {string} [identifier] class name
|
995
|
+
* @returns {ClassDecorator}
|
996
|
+
*/
|
997
|
+
function Plugin(identifier) {
|
998
|
+
return (target) => {
|
999
|
+
identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
|
1000
|
+
//
|
1001
|
+
if (!identifier.endsWith("Plugin")) {
|
1002
|
+
throw Error("Plugin class name must be 'Plugin' suffix.");
|
1003
|
+
}
|
1004
|
+
koatty_container.IOCContainer.saveClass("COMPONENT", target, `${identifier}`);
|
1005
|
+
};
|
1013
1006
|
}
|
1014
1007
|
|
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
|
-
}
|
1008
|
+
/*
|
1009
|
+
* @Description: base service
|
1010
|
+
* @Usage:
|
1011
|
+
* @Author: richen
|
1012
|
+
* @Date: 2023-12-09 21:56:32
|
1013
|
+
* @LastEditTime: 2023-12-09 23:03:23
|
1014
|
+
* @License: BSD (3-Clause)
|
1015
|
+
* @Copyright (c): <richenlin(at)gmail.com>
|
1016
|
+
*/
|
1017
|
+
/**
|
1018
|
+
* Base service
|
1019
|
+
*
|
1020
|
+
* @export
|
1021
|
+
* @class Base
|
1022
|
+
*/
|
1023
|
+
class BaseService {
|
1024
|
+
/**
|
1025
|
+
* instance of BaseController.
|
1026
|
+
* @param {Koatty} app
|
1027
|
+
* @param {KoattyContext} ctx
|
1028
|
+
* @memberof BaseController
|
1029
|
+
*/
|
1030
|
+
constructor(...arg) {
|
1031
|
+
this.init(arg);
|
1032
|
+
}
|
1033
|
+
/**
|
1034
|
+
* init
|
1035
|
+
*
|
1036
|
+
* @protected
|
1037
|
+
* @memberof BaseController
|
1038
|
+
*/
|
1039
|
+
init(...arg) {
|
1040
|
+
}
|
1048
1041
|
}
|
1049
1042
|
|
1050
1043
|
Object.defineProperty(exports, 'Config', {
|
@@ -1073,31 +1066,31 @@ exports.Middleware = Middleware;
|
|
1073
1066
|
exports.Plugin = Plugin;
|
1074
1067
|
exports.Service = Service;
|
1075
1068
|
Object.keys(koatty_core).forEach(function (k) {
|
1076
|
-
if (k !== 'default' && !
|
1069
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
1077
1070
|
enumerable: true,
|
1078
1071
|
get: function () { return koatty_core[k]; }
|
1079
1072
|
});
|
1080
1073
|
});
|
1081
1074
|
Object.keys(koatty_exception).forEach(function (k) {
|
1082
|
-
if (k !== 'default' && !
|
1075
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
1083
1076
|
enumerable: true,
|
1084
1077
|
get: function () { return koatty_exception[k]; }
|
1085
1078
|
});
|
1086
1079
|
});
|
1087
1080
|
Object.keys(koatty_container).forEach(function (k) {
|
1088
|
-
if (k !== 'default' && !
|
1081
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
1089
1082
|
enumerable: true,
|
1090
1083
|
get: function () { return koatty_container[k]; }
|
1091
1084
|
});
|
1092
1085
|
});
|
1093
1086
|
Object.keys(koatty_trace).forEach(function (k) {
|
1094
|
-
if (k !== 'default' && !
|
1087
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
1095
1088
|
enumerable: true,
|
1096
1089
|
get: function () { return koatty_trace[k]; }
|
1097
1090
|
});
|
1098
1091
|
});
|
1099
1092
|
Object.keys(koatty_serve).forEach(function (k) {
|
1100
|
-
if (k !== 'default' && !
|
1093
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
1101
1094
|
enumerable: true,
|
1102
1095
|
get: function () { return koatty_serve[k]; }
|
1103
1096
|
});
|