koatty 3.5.7 → 3.5.12-0
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/.commitlintrc.js +3 -0
- package/.eslintignore +2 -0
- package/.huskyrc +5 -0
- package/.versionrc.js +16 -0
- package/CHANGELOG.md +1 -38
- package/README.md +5 -9
- package/api-extractor.json +345 -0
- package/dist/LICENSE +29 -0
- package/dist/README.md +147 -0
- package/dist/index.d.ts +363 -19
- package/dist/index.js +1266 -26
- package/dist/index.mjs +1197 -0
- package/dist/package.json +99 -0
- package/docs/api/index.md +12 -0
- package/docs/api/koatty.apiinput.code.md +11 -0
- package/docs/api/koatty.apiinput.data.md +11 -0
- package/docs/api/koatty.apiinput.md +22 -0
- package/docs/api/koatty.apiinput.message.md +11 -0
- package/docs/api/koatty.apioutput.code.md +11 -0
- package/docs/api/koatty.apioutput.data.md +11 -0
- package/docs/api/koatty.apioutput.md +22 -0
- package/docs/api/koatty.apioutput.message.md +11 -0
- package/docs/api/koatty.appreadyhookfunc.md +11 -0
- package/docs/api/koatty.basecontroller._constructor_.md +20 -0
- package/docs/api/koatty.basecontroller._options.md +11 -0
- package/docs/api/koatty.basecontroller.app.md +11 -0
- package/docs/api/koatty.basecontroller.ctx.md +11 -0
- package/docs/api/koatty.basecontroller.fail.md +28 -0
- package/docs/api/koatty.basecontroller.init.md +19 -0
- package/docs/api/koatty.basecontroller.md +39 -0
- package/docs/api/koatty.basecontroller.ok.md +28 -0
- package/docs/api/koatty.baseservice._constructor_.md +20 -0
- package/docs/api/koatty.baseservice._options.md +11 -0
- package/docs/api/koatty.baseservice.app.md +11 -0
- package/docs/api/koatty.baseservice.init.md +25 -0
- package/docs/api/koatty.baseservice.md +36 -0
- package/docs/api/koatty.bindappreadyhook.md +26 -0
- package/docs/api/koatty.bootstrap.md +27 -0
- package/docs/api/koatty.component.md +27 -0
- package/docs/api/koatty.componentscan.md +27 -0
- package/docs/api/koatty.configurationscan.md +27 -0
- package/docs/api/koatty.controller.md +27 -0
- package/docs/api/koatty.httpcontroller.body.md +28 -0
- package/docs/api/koatty.httpcontroller.deny.md +26 -0
- package/docs/api/koatty.httpcontroller.expires.md +26 -0
- package/docs/api/koatty.httpcontroller.fail.md +28 -0
- package/docs/api/koatty.httpcontroller.header.md +27 -0
- package/docs/api/koatty.httpcontroller.isget.md +19 -0
- package/docs/api/koatty.httpcontroller.ismethod.md +26 -0
- package/docs/api/koatty.httpcontroller.ispost.md +19 -0
- package/docs/api/koatty.httpcontroller.json.md +26 -0
- package/docs/api/koatty.httpcontroller.md +35 -0
- package/docs/api/koatty.httpcontroller.ok.md +28 -0
- package/docs/api/koatty.httpcontroller.param.md +26 -0
- package/docs/api/koatty.httpcontroller.redirect.md +27 -0
- package/docs/api/koatty.httpcontroller.type.md +27 -0
- package/docs/api/koatty.icontroller.__after.md +11 -0
- package/docs/api/koatty.icontroller.__befor.md +11 -0
- package/docs/api/koatty.icontroller.app.md +11 -0
- package/docs/api/koatty.icontroller.ctx.md +11 -0
- package/docs/api/koatty.icontroller.fail.md +11 -0
- package/docs/api/koatty.icontroller.md +25 -0
- package/docs/api/koatty.icontroller.ok.md +11 -0
- package/docs/api/koatty.imiddleware.md +20 -0
- package/docs/api/koatty.imiddleware.run.md +11 -0
- package/docs/api/koatty.iplugin.md +20 -0
- package/docs/api/koatty.iplugin.run.md +11 -0
- package/docs/api/koatty.iservice.app.md +11 -0
- package/docs/api/koatty.iservice.md +20 -0
- package/docs/api/koatty.logger.md +11 -0
- package/docs/api/koatty.md +51 -0
- package/docs/api/koatty.middleware.md +27 -0
- package/docs/api/koatty.plugin.md +27 -0
- package/docs/api/koatty.service.md +27 -0
- package/jest.config.js +0 -2
- package/jest_html_reporters.html +1 -1
- package/package.json +40 -39
- package/rollup.config.js +63 -0
- package/scripts/copyright.js +28 -0
- package/scripts/postBuild.js +10 -0
- package/tsconfig.json +4 -2
- package/babel.config.js +0 -21
- package/commitlint.config.js +0 -14
- package/dist/config/config.d.ts +0 -21
- package/dist/config/config.js +0 -25
- package/dist/config/config.js.map +0 -1
- package/dist/config/middleware.d.ts +0 -23
- package/dist/config/middleware.js +0 -34
- package/dist/config/middleware.js.map +0 -1
- package/dist/config/plugin.d.ts +0 -11
- package/dist/config/plugin.js +0 -15
- package/dist/config/plugin.js.map +0 -1
- package/dist/config/router.d.ts +0 -8
- package/dist/config/router.js +0 -32
- package/dist/config/router.js.map +0 -1
- package/dist/controller/BaseController.d.ts +0 -60
- package/dist/controller/BaseController.js +0 -137
- package/dist/controller/BaseController.js.map +0 -1
- package/dist/controller/HttpController.d.ts +0 -131
- package/dist/controller/HttpController.js +0 -215
- package/dist/controller/HttpController.js.map +0 -1
- package/dist/core/Bootstrap.d.ts +0 -50
- package/dist/core/Bootstrap.js +0 -217
- package/dist/core/Bootstrap.js.map +0 -1
- package/dist/core/Component.d.ts +0 -94
- package/dist/core/Component.js +0 -89
- package/dist/core/Component.js.map +0 -1
- package/dist/core/Constants.d.ts +0 -11
- package/dist/core/Constants.js +0 -24
- package/dist/core/Constants.js.map +0 -1
- package/dist/core/Loader.d.ts +0 -110
- package/dist/core/Loader.js +0 -407
- package/dist/core/Loader.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/middleware/PayloadMiddleware.d.ts +0 -11
- package/dist/middleware/PayloadMiddleware.js +0 -22
- package/dist/middleware/PayloadMiddleware.js.map +0 -1
- package/dist/middleware/TraceMiddleware.d.ts +0 -11
- package/dist/middleware/TraceMiddleware.js +0 -22
- package/dist/middleware/TraceMiddleware.js.map +0 -1
- package/dist/service/BaseService.d.ts +0 -33
- package/dist/service/BaseService.js +0 -32
- package/dist/service/BaseService.js.map +0 -1
- package/dist/util/Helper.d.ts +0 -25
- package/dist/util/Helper.js +0 -117
- package/dist/util/Helper.js.map +0 -1
- package/dist/util/Logger.d.ts +0 -27
- package/dist/util/Logger.js +0 -41
- package/dist/util/Logger.js.map +0 -1
package/dist/index.mjs
ADDED
@@ -0,0 +1,1197 @@
|
|
1
|
+
/*!
|
2
|
+
* @Author: richen
|
3
|
+
* @Date: 2021-12-21 12:21:50
|
4
|
+
* @License: BSD (3-Clause)
|
5
|
+
* @Copyright (c) - <richenlin(at)gmail.com>
|
6
|
+
* @HomePage: https://koatty.org/
|
7
|
+
*/
|
8
|
+
import { Helper } from 'koatty_lib';
|
9
|
+
export { Helper } from 'koatty_lib';
|
10
|
+
import 'reflect-metadata';
|
11
|
+
import { NewRouter, CONTROLLER_ROUTER } from 'koatty_router';
|
12
|
+
export * from 'koatty_router';
|
13
|
+
import { Koatty } from 'koatty_core';
|
14
|
+
export * from 'koatty_core';
|
15
|
+
import { BindProcessEvent, Serve } from 'koatty_serve';
|
16
|
+
export * from 'koatty_serve';
|
17
|
+
import { IOCContainer, TAGGED_CLS } from 'koatty_container';
|
18
|
+
export * from 'koatty_container';
|
19
|
+
import * as path from 'path';
|
20
|
+
import { Load } from 'koatty_loader';
|
21
|
+
import { LoadConfigs } from 'koatty_config';
|
22
|
+
import { DefaultLogger } from 'koatty_logger';
|
23
|
+
import { prevent } from 'koatty_exception';
|
24
|
+
export * from 'koatty_exception';
|
25
|
+
import { Trace } from 'koatty_trace';
|
26
|
+
export * from 'koatty_trace';
|
27
|
+
import { Payload } from 'koatty_payload';
|
28
|
+
|
29
|
+
/**
|
30
|
+
* @ author: richen
|
31
|
+
* @ copyright: Copyright (c) - <richenlin(at)gmail.com>
|
32
|
+
* @ license: BSD (3-Clause)
|
33
|
+
* @ version: 2020-05-10 11:49:15
|
34
|
+
*/
|
35
|
+
/**
|
36
|
+
* Check class file
|
37
|
+
* name should be always the same as class name
|
38
|
+
* class must be unique
|
39
|
+
*
|
40
|
+
* @export
|
41
|
+
* @param {string} fileName
|
42
|
+
* @param {string} xpath
|
43
|
+
* @param {*} target
|
44
|
+
* @param {Set<unknown>} [exSet]
|
45
|
+
* @returns {*}
|
46
|
+
*/
|
47
|
+
function checkClass(fileName, xpath, target, exSet) {
|
48
|
+
if (Helper.isClass(target) && target.name != fileName) { // export default class name{}
|
49
|
+
throw Error(`The file(${xpath}) name should be always the same as class name.`);
|
50
|
+
}
|
51
|
+
if (target["__esModule"]) {
|
52
|
+
if (target.name === undefined) { // export class name{}
|
53
|
+
const keys = Object.keys(target);
|
54
|
+
if (keys[0] != fileName && Helper.isClass(target[keys[0]])) {
|
55
|
+
throw Error(`The file(${xpath}) name should be always the same as class name.`);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
else if (target.name != fileName) { // export default class {}
|
59
|
+
throw Error(`The file(${xpath}) name should be always the same as class name.`);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
if (!exSet) {
|
63
|
+
return;
|
64
|
+
}
|
65
|
+
if (exSet.has(fileName)) {
|
66
|
+
throw new Error(`A same class already exists. at \`${xpath}\`.`);
|
67
|
+
}
|
68
|
+
exSet.add(fileName);
|
69
|
+
return;
|
70
|
+
}
|
71
|
+
/**
|
72
|
+
* Format api interface data format
|
73
|
+
*
|
74
|
+
* @private
|
75
|
+
* @param {Error | string | ApiInput} msg 待处理的接口数据信息|接口msg
|
76
|
+
* @param {*} data 待返回的数据
|
77
|
+
* @param {number} defaultCode 默认错误码
|
78
|
+
* @returns {ApiOutput} 格式化之后的接口数据
|
79
|
+
* @memberof BaseController
|
80
|
+
*/
|
81
|
+
function formatApiData(msg, data, defaultCode) {
|
82
|
+
let obj = {
|
83
|
+
code: defaultCode,
|
84
|
+
message: '',
|
85
|
+
data: null,
|
86
|
+
};
|
87
|
+
if (Helper.isError(msg)) {
|
88
|
+
const { code, message } = msg;
|
89
|
+
obj.code = code || defaultCode;
|
90
|
+
obj.message = message;
|
91
|
+
}
|
92
|
+
else if (Helper.isObject(msg)) {
|
93
|
+
obj = { ...obj, ...msg };
|
94
|
+
}
|
95
|
+
else {
|
96
|
+
obj.message = msg;
|
97
|
+
obj.data = data;
|
98
|
+
}
|
99
|
+
return obj;
|
100
|
+
}
|
101
|
+
|
102
|
+
/**
|
103
|
+
* @ author: richen
|
104
|
+
* @ copyright: Copyright (c) - <richenlin(at)gmail.com>
|
105
|
+
* @ license: BSD (3-Clause)
|
106
|
+
* @ version: 2020-05-20 15:45:24
|
107
|
+
*/
|
108
|
+
/**
|
109
|
+
* Base controller
|
110
|
+
*
|
111
|
+
* @export
|
112
|
+
* @class BaseController
|
113
|
+
* @implements {IController}
|
114
|
+
*/
|
115
|
+
class BaseController {
|
116
|
+
/**
|
117
|
+
* instance of BaseController.
|
118
|
+
* @param {Koatty} app
|
119
|
+
* @param {KoattyContext} ctx
|
120
|
+
* @memberof BaseController
|
121
|
+
*/
|
122
|
+
constructor(ctx) {
|
123
|
+
this.ctx = ctx;
|
124
|
+
this.init();
|
125
|
+
}
|
126
|
+
/**
|
127
|
+
* init
|
128
|
+
*
|
129
|
+
* @protected
|
130
|
+
* @memberof BaseController
|
131
|
+
*/
|
132
|
+
init() {
|
133
|
+
}
|
134
|
+
// /**
|
135
|
+
// * Class pre-execution method, executed before each class member methods (except constructor, init, __after) are executed.
|
136
|
+
// *
|
137
|
+
// * @returns {Promise<any>}
|
138
|
+
// * @memberof BaseController
|
139
|
+
// */
|
140
|
+
// public __before(): Promise<any> {
|
141
|
+
// return Promise.resolve();
|
142
|
+
// }
|
143
|
+
// /**
|
144
|
+
// * Class after-execution method,after each class member methods (except constructor, init, __before) are executed.
|
145
|
+
// *
|
146
|
+
// * @public
|
147
|
+
// * @returns {*}
|
148
|
+
// * @memberof BaseController
|
149
|
+
// */
|
150
|
+
// public __after(): Promise<any> {
|
151
|
+
// return Promise.resolve();
|
152
|
+
// }
|
153
|
+
/**
|
154
|
+
* Response to normalize json format content for success
|
155
|
+
*
|
156
|
+
* @param {(string | ApiInput)} msg 待处理的message消息
|
157
|
+
* @param {*} [data] 待处理的数据
|
158
|
+
* @param {number} [code=200] 错误码,默认0
|
159
|
+
* @returns {*}
|
160
|
+
* @memberof BaseController
|
161
|
+
*/
|
162
|
+
ok(msg, data, code = 0) {
|
163
|
+
const obj = formatApiData(msg, data, code);
|
164
|
+
return Promise.resolve(obj);
|
165
|
+
}
|
166
|
+
/**
|
167
|
+
* Response to normalize json format content for fail
|
168
|
+
*
|
169
|
+
* @param {(string | ApiInput)} msg
|
170
|
+
* @param {*} [data]
|
171
|
+
* @param {number} [code=1]
|
172
|
+
* @returns {*}
|
173
|
+
* @memberof BaseController
|
174
|
+
*/
|
175
|
+
fail(msg, data, code = 1) {
|
176
|
+
const obj = formatApiData(msg, data, code);
|
177
|
+
return Promise.resolve(obj);
|
178
|
+
}
|
179
|
+
}
|
180
|
+
// const properties = ["constructor", "init"];
|
181
|
+
// export const BaseController = new Proxy(Base, {
|
182
|
+
// set(target, key, value, receiver) {
|
183
|
+
// if (Reflect.get(target, key, receiver) === undefined) {
|
184
|
+
// return Reflect.set(target, key, value, receiver);
|
185
|
+
// } else if (key === "init") {
|
186
|
+
// return Reflect.set(target, key, value, receiver);
|
187
|
+
// } else {
|
188
|
+
// throw Error("Cannot redefine getter-only property");
|
189
|
+
// }
|
190
|
+
// },
|
191
|
+
// deleteProperty(target, key) {
|
192
|
+
// throw Error("Cannot delete getter-only property");
|
193
|
+
// },
|
194
|
+
// construct(target, args, newTarget) {
|
195
|
+
// Reflect.ownKeys(target.prototype).map((n) => {
|
196
|
+
// if (newTarget.prototype.hasOwnProperty(n) && !properties.includes(Helper.toString(n))) {
|
197
|
+
// throw Error(`Cannot override the final method "${Helper.toString(n)}"`);
|
198
|
+
// }
|
199
|
+
// });
|
200
|
+
// return Reflect.construct(target, args, newTarget);
|
201
|
+
// }
|
202
|
+
// });
|
203
|
+
|
204
|
+
/**
|
205
|
+
* @ author: richen
|
206
|
+
* @ copyright: Copyright (c) - <richenlin(at)gmail.com>
|
207
|
+
* @ license: BSD (3-Clause)
|
208
|
+
* @ version: 2020-05-20 15:45:24
|
209
|
+
*/
|
210
|
+
/**
|
211
|
+
* HTTP controller
|
212
|
+
*
|
213
|
+
* @export
|
214
|
+
* @class HttpController
|
215
|
+
* @implements {IController}
|
216
|
+
*/
|
217
|
+
class HttpController extends BaseController {
|
218
|
+
/**
|
219
|
+
* Whether it is a GET request
|
220
|
+
*
|
221
|
+
* @public
|
222
|
+
* @returns {boolean}
|
223
|
+
* @memberof HttpController
|
224
|
+
*/
|
225
|
+
isGet() {
|
226
|
+
return this.ctx.method === "GET";
|
227
|
+
}
|
228
|
+
/**
|
229
|
+
* Whether it is a POST request
|
230
|
+
*
|
231
|
+
* @public
|
232
|
+
* @returns {boolean}
|
233
|
+
* @memberof HttpController
|
234
|
+
*/
|
235
|
+
isPost() {
|
236
|
+
return this.ctx.method === "POST";
|
237
|
+
}
|
238
|
+
/**
|
239
|
+
* Determines whether the METHOD request is specified
|
240
|
+
*
|
241
|
+
* @public
|
242
|
+
* @param {string} method
|
243
|
+
* @returns {boolean}
|
244
|
+
* @memberof HttpController
|
245
|
+
*/
|
246
|
+
isMethod(method) {
|
247
|
+
return this.ctx.method === method.toUpperCase();
|
248
|
+
}
|
249
|
+
/**
|
250
|
+
* Get/Set headers.
|
251
|
+
*
|
252
|
+
* @public
|
253
|
+
* @param {string} [name]
|
254
|
+
* @param {*} [value]
|
255
|
+
* @returns {*}
|
256
|
+
* @memberof HttpController
|
257
|
+
*/
|
258
|
+
header(name, value) {
|
259
|
+
if (name === undefined) {
|
260
|
+
return this.ctx.headers;
|
261
|
+
}
|
262
|
+
if (value === undefined) {
|
263
|
+
return this.ctx.get(name);
|
264
|
+
}
|
265
|
+
return this.ctx.set(name, value);
|
266
|
+
}
|
267
|
+
/**
|
268
|
+
* Get POST/GET parameters, the POST value is priority.
|
269
|
+
*
|
270
|
+
* @param {string} [name]
|
271
|
+
* @returns
|
272
|
+
* @memberof HttpController
|
273
|
+
*/
|
274
|
+
param(name) {
|
275
|
+
return this.ctx.bodyParser().then((body) => {
|
276
|
+
const getParams = this.ctx.queryParser() || {};
|
277
|
+
const postParams = (body.post ? body.post : body) || {};
|
278
|
+
if (name !== undefined) {
|
279
|
+
return postParams[name] === undefined ? getParams[name] : postParams[name];
|
280
|
+
}
|
281
|
+
return { ...getParams, ...postParams };
|
282
|
+
});
|
283
|
+
}
|
284
|
+
/**
|
285
|
+
* Set response content-type
|
286
|
+
*
|
287
|
+
* @public
|
288
|
+
* @param {string} contentType
|
289
|
+
* @param {(string | boolean)} [encoding]
|
290
|
+
* @returns {string}
|
291
|
+
* @memberof HttpController
|
292
|
+
*/
|
293
|
+
type(contentType, encoding) {
|
294
|
+
if (encoding !== false && !contentType.includes("charset")) {
|
295
|
+
contentType = `${contentType}; charset=${encoding || this.app.config("encoding")}`;
|
296
|
+
}
|
297
|
+
this.ctx.type = contentType;
|
298
|
+
return contentType;
|
299
|
+
}
|
300
|
+
/**
|
301
|
+
* set cache-control and expires header
|
302
|
+
*
|
303
|
+
* @public
|
304
|
+
* @param {number} [timeout=30]
|
305
|
+
* @returns {void}
|
306
|
+
* @memberof HttpController
|
307
|
+
*/
|
308
|
+
expires(timeout = 30) {
|
309
|
+
timeout = Helper.toNumber(timeout) * 1000;
|
310
|
+
const date = new Date(Date.now() + timeout);
|
311
|
+
this.ctx.set("Cache-Control", `max-age=${timeout}`);
|
312
|
+
return this.ctx.set("Expires", date.toUTCString());
|
313
|
+
}
|
314
|
+
/**
|
315
|
+
* Url redirect
|
316
|
+
*
|
317
|
+
* @param {string} urls
|
318
|
+
* @param {string} [alt]
|
319
|
+
* @returns {void}
|
320
|
+
* @memberof HttpController
|
321
|
+
*/
|
322
|
+
redirect(urls, alt) {
|
323
|
+
return this.ctx.redirect(urls, alt);
|
324
|
+
}
|
325
|
+
/**
|
326
|
+
* Block access
|
327
|
+
*
|
328
|
+
* @param {number} [code=403]
|
329
|
+
* @returns {Promise<any>}
|
330
|
+
* @memberof HttpController
|
331
|
+
*/
|
332
|
+
deny(code = 403) {
|
333
|
+
return this.ctx.throw(code);
|
334
|
+
}
|
335
|
+
/**
|
336
|
+
* Set response Body content
|
337
|
+
*
|
338
|
+
* @param {*} data
|
339
|
+
* @param {string} [contentType]
|
340
|
+
* @param {string} [encoding]
|
341
|
+
* @returns {Promise<any>}
|
342
|
+
* @memberof HttpController
|
343
|
+
*/
|
344
|
+
body(data, contentType, encoding) {
|
345
|
+
contentType = contentType || "text/plain";
|
346
|
+
encoding = encoding || this.app.config("encoding") || "utf-8";
|
347
|
+
this.type(contentType, encoding);
|
348
|
+
this.ctx.body = data;
|
349
|
+
return null;
|
350
|
+
}
|
351
|
+
/**
|
352
|
+
* Respond to json formatted content
|
353
|
+
*
|
354
|
+
* @param {*} data
|
355
|
+
* @returns {Promise<any>}
|
356
|
+
* @memberof HttpController
|
357
|
+
*/
|
358
|
+
json(data) {
|
359
|
+
return this.body(data, "application/json");
|
360
|
+
}
|
361
|
+
/**
|
362
|
+
* Response to normalize json format content for success
|
363
|
+
*
|
364
|
+
* @param {(string | ApiInput)} msg 待处理的message消息
|
365
|
+
* @param {*} [data] 待处理的数据
|
366
|
+
* @param {number} [code=200] 错误码,默认0
|
367
|
+
* @returns {*}
|
368
|
+
* @memberof HttpController
|
369
|
+
*/
|
370
|
+
ok(msg, data, code = 0) {
|
371
|
+
const obj = formatApiData(msg, data, code);
|
372
|
+
return this.json(obj);
|
373
|
+
}
|
374
|
+
/**
|
375
|
+
* Response to normalize json format content for fail
|
376
|
+
*
|
377
|
+
* @param {(string | ApiInput)} msg
|
378
|
+
* @param {*} [data]
|
379
|
+
* @param {number} [code=1]
|
380
|
+
* @returns {*}
|
381
|
+
* @memberof HttpController
|
382
|
+
*/
|
383
|
+
fail(msg, data, code = 1) {
|
384
|
+
const obj = formatApiData(msg, data, code);
|
385
|
+
return this.json(obj);
|
386
|
+
}
|
387
|
+
}
|
388
|
+
// const properties = ["constructor", "init"];
|
389
|
+
// export const HttpController = new Proxy(Base, {
|
390
|
+
// set(target, key, value, receiver) {
|
391
|
+
// if (Reflect.get(target, key, receiver) === undefined) {
|
392
|
+
// return Reflect.set(target, key, value, receiver);
|
393
|
+
// } else if (key === "init") {
|
394
|
+
// return Reflect.set(target, key, value, receiver);
|
395
|
+
// } else {
|
396
|
+
// throw Error("Cannot redefine getter-only property");
|
397
|
+
// }
|
398
|
+
// },
|
399
|
+
// deleteProperty(target, key) {
|
400
|
+
// throw Error("Cannot delete getter-only property");
|
401
|
+
// },
|
402
|
+
// construct(target, args, newTarget) {
|
403
|
+
// Reflect.ownKeys(target.prototype).map((n) => {
|
404
|
+
// if (newTarget.prototype.hasOwnProperty(n) && !properties.includes(Helper.toString(n))) {
|
405
|
+
// throw Error(`Cannot override the final method "${Helper.toString(n)}"`);
|
406
|
+
// }
|
407
|
+
// });
|
408
|
+
// return Reflect.construct(target, args, newTarget);
|
409
|
+
// }
|
410
|
+
// });
|
411
|
+
|
412
|
+
/**
|
413
|
+
* @ author: richen
|
414
|
+
* @ copyright: Copyright (c) - <richenlin(at)gmail.com>
|
415
|
+
* @ license: BSD (3-Clause)
|
416
|
+
* @ version: 2020-05-10 11:49:15
|
417
|
+
*/
|
418
|
+
// Logger
|
419
|
+
const Logger = DefaultLogger;
|
420
|
+
/**
|
421
|
+
* SetLogger
|
422
|
+
*
|
423
|
+
* @export
|
424
|
+
* @param {{
|
425
|
+
* logLevel?: LogLevelType;
|
426
|
+
* logConsole?: boolean;
|
427
|
+
* logFile?: boolean;
|
428
|
+
* logFileLevel?: LogLevelType;
|
429
|
+
* logFilePath?: string;
|
430
|
+
* }} config
|
431
|
+
*/
|
432
|
+
function SetLogger(config) {
|
433
|
+
if (config.logLevel !== undefined) {
|
434
|
+
DefaultLogger.setLevel(config.logLevel);
|
435
|
+
}
|
436
|
+
if (config.logConsole !== undefined) {
|
437
|
+
DefaultLogger.setLogConsole(config.logConsole);
|
438
|
+
}
|
439
|
+
if (config.logFile !== undefined) {
|
440
|
+
DefaultLogger.setLogFile(config.logFile);
|
441
|
+
DefaultLogger.setLogFilePath(config.logFilePath);
|
442
|
+
}
|
443
|
+
if (config.logFileLevel !== undefined) {
|
444
|
+
DefaultLogger.setLogFileLevel(config.logFileLevel);
|
445
|
+
}
|
446
|
+
}
|
447
|
+
|
448
|
+
/**
|
449
|
+
* Base class
|
450
|
+
*
|
451
|
+
* @export
|
452
|
+
* @class Base
|
453
|
+
*/
|
454
|
+
class BaseService {
|
455
|
+
/**
|
456
|
+
* instance of Base.
|
457
|
+
* @param {...any[]} arg
|
458
|
+
* @memberof Base
|
459
|
+
*/
|
460
|
+
constructor(...arg) {
|
461
|
+
this.init(arg);
|
462
|
+
}
|
463
|
+
/**
|
464
|
+
* init
|
465
|
+
*
|
466
|
+
* @protected
|
467
|
+
* @param {...any[]} arg
|
468
|
+
* @memberof Base
|
469
|
+
*/
|
470
|
+
init(...arg) {
|
471
|
+
// todo
|
472
|
+
// Logger.Debug(arg)
|
473
|
+
}
|
474
|
+
}
|
475
|
+
|
476
|
+
/**
|
477
|
+
* @ author: richen
|
478
|
+
* @ copyright: Copyright (c) - <richenlin(at)gmail.com>
|
479
|
+
* @ license: BSD (3-Clause)
|
480
|
+
* @ version: 2020-05-10 11:49:15
|
481
|
+
*/
|
482
|
+
const COMPONENT_SCAN = 'COMPONENT_SCAN';
|
483
|
+
const CONFIGURATION_SCAN = 'CONFIGURATION_SCAN';
|
484
|
+
const APP_READY_HOOK = "APP_READY_HOOK";
|
485
|
+
// tslint:disable: no-irregular-whitespace
|
486
|
+
const LOGO = `
|
487
|
+
|
488
|
+
██ ██ ██████ █████ ████████ ████████ ██ ██
|
489
|
+
██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
490
|
+
█████ ██ ██ ███████ ██ ██ ████
|
491
|
+
██ ██ ██ ██ ██ ██ ██ ██ ██
|
492
|
+
██ ██ ██████ ██ ██ ██ ██ ██
|
493
|
+
https://github.com/koatty
|
494
|
+
`;
|
495
|
+
|
496
|
+
class TraceMiddleware {
|
497
|
+
run(options, app) {
|
498
|
+
return Trace(options, app);
|
499
|
+
}
|
500
|
+
}
|
501
|
+
|
502
|
+
class PayloadMiddleware {
|
503
|
+
run(options, app) {
|
504
|
+
return Payload(options, app);
|
505
|
+
}
|
506
|
+
}
|
507
|
+
|
508
|
+
/**
|
509
|
+
* @ author: richen
|
510
|
+
* @ copyright: Copyright (c) - <richenlin(at)gmail.com>
|
511
|
+
* @ license: BSD (3-Clause)
|
512
|
+
* @ version: 2020-07-06 11:18:01
|
513
|
+
*/
|
514
|
+
/**
|
515
|
+
*
|
516
|
+
*/
|
517
|
+
class Loader {
|
518
|
+
/**
|
519
|
+
* initialize env
|
520
|
+
*
|
521
|
+
* @static
|
522
|
+
* @param {Koatty} app
|
523
|
+
* @memberof Loader
|
524
|
+
*/
|
525
|
+
static initialize(app) {
|
526
|
+
var _a, _b;
|
527
|
+
const env = ((_a = process.execArgv) !== null && _a !== void 0 ? _a : []).join(",");
|
528
|
+
if (env.indexOf('ts-node') > -1 || env.indexOf('--debug') > -1) {
|
529
|
+
app.appDebug = true;
|
530
|
+
}
|
531
|
+
// app.env
|
532
|
+
app.env = process.env.KOATTY_ENV || process.env.NODE_ENV;
|
533
|
+
if ((env.indexOf('--production') > -1) || (((_b = app.env) !== null && _b !== void 0 ? _b : '').indexOf('pro') > -1)) {
|
534
|
+
app.appDebug = false;
|
535
|
+
}
|
536
|
+
if (app.appDebug) {
|
537
|
+
app.env = 'development';
|
538
|
+
process.env.NODE_ENV = 'development';
|
539
|
+
process.env.APP_DEBUG = 'true';
|
540
|
+
Logger.setLevel("DEBUG");
|
541
|
+
}
|
542
|
+
else {
|
543
|
+
app.env = 'production';
|
544
|
+
process.env.NODE_ENV = 'production';
|
545
|
+
Logger.setLevel("INFO");
|
546
|
+
}
|
547
|
+
// define path
|
548
|
+
const rootPath = app.rootPath || process.cwd();
|
549
|
+
const appPath = app.appPath || path.resolve(rootPath, env.indexOf('ts-node') > -1 ? 'src' : 'dist');
|
550
|
+
const thinkPath = path.resolve(__dirname, '..');
|
551
|
+
Helper.define(app, 'rootPath', rootPath);
|
552
|
+
Helper.define(app, 'appPath', appPath);
|
553
|
+
Helper.define(app, 'thinkPath', thinkPath);
|
554
|
+
process.env.ROOT_PATH = rootPath;
|
555
|
+
process.env.APP_PATH = appPath;
|
556
|
+
process.env.THINK_PATH = thinkPath;
|
557
|
+
// Compatible with old version, will be deprecated
|
558
|
+
Helper.define(app, 'prevent', prevent);
|
559
|
+
Helper.define(app, 'root_path', rootPath);
|
560
|
+
Helper.define(app, 'app_path', appPath);
|
561
|
+
Helper.define(app, 'think_path', thinkPath);
|
562
|
+
}
|
563
|
+
/**
|
564
|
+
* Get component metadata
|
565
|
+
*
|
566
|
+
* @static
|
567
|
+
* @param {Koatty} app
|
568
|
+
* @param {*} target
|
569
|
+
* @returns {*} {any[]}
|
570
|
+
* @memberof Loader
|
571
|
+
*/
|
572
|
+
static GetComponentMetas(app, target) {
|
573
|
+
let componentMetas = [];
|
574
|
+
const componentMeta = IOCContainer.getClassMetadata(TAGGED_CLS, COMPONENT_SCAN, target);
|
575
|
+
if (componentMeta) {
|
576
|
+
if (Helper.isArray(componentMeta)) {
|
577
|
+
componentMetas = componentMeta;
|
578
|
+
}
|
579
|
+
else {
|
580
|
+
componentMetas.push(componentMeta);
|
581
|
+
}
|
582
|
+
}
|
583
|
+
if (componentMetas.length < 1) {
|
584
|
+
componentMetas = [app.appPath];
|
585
|
+
}
|
586
|
+
return componentMetas;
|
587
|
+
}
|
588
|
+
/**
|
589
|
+
* Load all bean, excepted config/*、App.ts
|
590
|
+
*
|
591
|
+
* @static
|
592
|
+
* @param {Koatty} app
|
593
|
+
* @param {*} target
|
594
|
+
* @memberof Loader
|
595
|
+
*/
|
596
|
+
static CheckAllComponents(app, target) {
|
597
|
+
// component metadata
|
598
|
+
const componentMetas = Loader.GetComponentMetas(app, target);
|
599
|
+
// configuration metadata
|
600
|
+
const configurationMetas = Loader.GetConfigurationMetas(app, target);
|
601
|
+
const exSet = new Set();
|
602
|
+
Load(componentMetas, '', (fileName, xpath, xTarget) => {
|
603
|
+
checkClass(fileName, xpath, xTarget, exSet);
|
604
|
+
}, ['**/**.js', '**/**.ts', '!**/**.d.ts'], [...configurationMetas, `${target.name || '.no'}.ts`]);
|
605
|
+
exSet.clear();
|
606
|
+
}
|
607
|
+
/**
|
608
|
+
* Get configuration metadata
|
609
|
+
*
|
610
|
+
* @static
|
611
|
+
* @param {Koatty} app
|
612
|
+
* @param {*} target
|
613
|
+
* @returns {*} {any[]}
|
614
|
+
* @memberof Loader
|
615
|
+
*/
|
616
|
+
static GetConfigurationMetas(app, target) {
|
617
|
+
const confMeta = IOCContainer.getClassMetadata(TAGGED_CLS, CONFIGURATION_SCAN, target);
|
618
|
+
let configurationMetas = [];
|
619
|
+
if (confMeta) {
|
620
|
+
if (Helper.isArray(confMeta)) {
|
621
|
+
configurationMetas = confMeta;
|
622
|
+
}
|
623
|
+
else {
|
624
|
+
configurationMetas.push(confMeta);
|
625
|
+
}
|
626
|
+
}
|
627
|
+
return configurationMetas;
|
628
|
+
}
|
629
|
+
/**
|
630
|
+
* Set Logger level
|
631
|
+
*
|
632
|
+
* @static
|
633
|
+
* @param {Koatty} app
|
634
|
+
* @memberof Loader
|
635
|
+
*/
|
636
|
+
static SetLogger(app) {
|
637
|
+
var _a;
|
638
|
+
const configs = (_a = app.getMetaData("_configs")) !== null && _a !== void 0 ? _a : {};
|
639
|
+
//Logger
|
640
|
+
if (configs.config) {
|
641
|
+
const opt = configs.config;
|
642
|
+
let logLevel = "DEBUG", logFileLevel = "INFO", logConsole = true, logFile = false, logFilePath = app.rootPath + "/logs";
|
643
|
+
if (app.env === "production") {
|
644
|
+
logLevel = "INFO";
|
645
|
+
logFileLevel = "WARN";
|
646
|
+
logConsole = false;
|
647
|
+
logFile = true;
|
648
|
+
}
|
649
|
+
if (opt.logs_level) {
|
650
|
+
logLevel = opt.logs_level;
|
651
|
+
}
|
652
|
+
if (opt.logs_write_level) {
|
653
|
+
logFileLevel = opt.logs_write_level;
|
654
|
+
}
|
655
|
+
if (opt.logs_write !== undefined) {
|
656
|
+
logFile = !!opt.logs_write;
|
657
|
+
}
|
658
|
+
if (opt.logs_console !== undefined) {
|
659
|
+
logConsole = !!opt.logs_console;
|
660
|
+
}
|
661
|
+
if (opt.logs_path) {
|
662
|
+
logFilePath = opt.logs_path;
|
663
|
+
}
|
664
|
+
SetLogger({ logLevel, logConsole, logFile, logFileLevel, logFilePath });
|
665
|
+
}
|
666
|
+
}
|
667
|
+
/**
|
668
|
+
* Load app ready hook funcs
|
669
|
+
*
|
670
|
+
* @static
|
671
|
+
* @param {Koatty} app
|
672
|
+
* @param {*} target
|
673
|
+
* @memberof Loader
|
674
|
+
*/
|
675
|
+
static LoadAppReadyHooks(app, target) {
|
676
|
+
const funcs = IOCContainer.getClassMetadata(TAGGED_CLS, APP_READY_HOOK, target);
|
677
|
+
if (Helper.isArray(funcs)) {
|
678
|
+
funcs.forEach((element) => {
|
679
|
+
app.once('appReady', () => element(app));
|
680
|
+
return null;
|
681
|
+
});
|
682
|
+
}
|
683
|
+
}
|
684
|
+
/**
|
685
|
+
* Load configuration
|
686
|
+
*
|
687
|
+
* @static
|
688
|
+
* @param {Koatty} app
|
689
|
+
* @param {string[]} [loadPath]
|
690
|
+
* @memberof Loader
|
691
|
+
*/
|
692
|
+
static LoadConfigs(app, loadPath) {
|
693
|
+
const frameConfig = {};
|
694
|
+
// Logger.Debug(`Load configuration path: ${app.thinkPath}/config`);
|
695
|
+
Load(["./config"], app.thinkPath, function (name, path, exp) {
|
696
|
+
frameConfig[name] = exp;
|
697
|
+
});
|
698
|
+
if (Helper.isArray(loadPath)) {
|
699
|
+
loadPath = loadPath.length > 0 ? loadPath : ["./config"];
|
700
|
+
}
|
701
|
+
let appConfig = LoadConfigs(loadPath, app.appPath);
|
702
|
+
appConfig = Helper.extend(frameConfig, appConfig, true);
|
703
|
+
app.setMetaData("_configs", appConfig);
|
704
|
+
}
|
705
|
+
/**
|
706
|
+
* Load middlewares
|
707
|
+
* [async]
|
708
|
+
* @static
|
709
|
+
* @param {*} app
|
710
|
+
* @param {(string | string[])} [loadPath]
|
711
|
+
* @memberof Loader
|
712
|
+
*/
|
713
|
+
static async LoadMiddlewares(app, loadPath) {
|
714
|
+
var _a, _b;
|
715
|
+
let middlewareConf = app.config(undefined, "middleware");
|
716
|
+
if (Helper.isEmpty(middlewareConf)) {
|
717
|
+
middlewareConf = { config: {}, list: [] };
|
718
|
+
}
|
719
|
+
//Mount default middleware
|
720
|
+
Load(loadPath || ["./middleware"], app.thinkPath);
|
721
|
+
//Mount application middleware
|
722
|
+
// const middleware: any = {};
|
723
|
+
const appMiddleware = (_a = IOCContainer.listClass("MIDDLEWARE")) !== null && _a !== void 0 ? _a : [];
|
724
|
+
appMiddleware.push({ id: "TraceMiddleware", target: TraceMiddleware });
|
725
|
+
appMiddleware.push({ id: "PayloadMiddleware", target: PayloadMiddleware });
|
726
|
+
appMiddleware.forEach((item) => {
|
727
|
+
var _a;
|
728
|
+
item.id = ((_a = item.id) !== null && _a !== void 0 ? _a : "").replace("MIDDLEWARE:", "");
|
729
|
+
if (item.id && Helper.isClass(item.target)) {
|
730
|
+
IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "MIDDLEWARE", args: [] });
|
731
|
+
// middleware[item.id] = item.target;
|
732
|
+
}
|
733
|
+
});
|
734
|
+
const middlewareConfList = middlewareConf.list;
|
735
|
+
const defaultList = ["TraceMiddleware", "PayloadMiddleware"];
|
736
|
+
middlewareConfList.forEach((item) => {
|
737
|
+
if (!defaultList.includes(item)) {
|
738
|
+
defaultList.push(item);
|
739
|
+
}
|
740
|
+
});
|
741
|
+
// if (defaultList.length > middlewareConfList.length) {
|
742
|
+
// Logger.Warn("Some middleware is loaded but not allowed to execute.");
|
743
|
+
// }
|
744
|
+
//de-duplication
|
745
|
+
const appMList = [...new Set(defaultList)];
|
746
|
+
//Automatically call middleware
|
747
|
+
for (const key of appMList) {
|
748
|
+
const handle = IOCContainer.get(key, "MIDDLEWARE");
|
749
|
+
if (!handle) {
|
750
|
+
Logger.Error(`Middleware ${key} load error.`);
|
751
|
+
continue;
|
752
|
+
}
|
753
|
+
if (!Helper.isFunction(handle.run)) {
|
754
|
+
Logger.Error(`Middleware ${key} must be implements method 'run'.`);
|
755
|
+
continue;
|
756
|
+
}
|
757
|
+
if (middlewareConf.config[key] === false) {
|
758
|
+
Logger.Warn(`Middleware ${key} is loaded but not allowed to execute.`);
|
759
|
+
continue;
|
760
|
+
}
|
761
|
+
Logger.Debug(`Load middleware: ${key}`);
|
762
|
+
const result = await handle.run((_b = middlewareConf.config[key]) !== null && _b !== void 0 ? _b : {}, app);
|
763
|
+
if (Helper.isFunction(result)) {
|
764
|
+
if (result.length < 3) {
|
765
|
+
app.use(result);
|
766
|
+
}
|
767
|
+
else {
|
768
|
+
app.useExp(result);
|
769
|
+
}
|
770
|
+
}
|
771
|
+
}
|
772
|
+
// app.setMetaData("_middlewares", middleware);
|
773
|
+
}
|
774
|
+
/**
|
775
|
+
* Load controllers
|
776
|
+
*
|
777
|
+
* @static
|
778
|
+
* @param {*} app
|
779
|
+
* @memberof Loader
|
780
|
+
*/
|
781
|
+
static LoadControllers(app) {
|
782
|
+
const controllerList = IOCContainer.listClass("CONTROLLER");
|
783
|
+
const controllers = {};
|
784
|
+
controllerList.forEach((item) => {
|
785
|
+
var _a;
|
786
|
+
item.id = ((_a = item.id) !== null && _a !== void 0 ? _a : "").replace("CONTROLLER:", "");
|
787
|
+
if (item.id && Helper.isClass(item.target)) {
|
788
|
+
Logger.Debug(`Load controller: ${item.id}`);
|
789
|
+
// registering to IOC
|
790
|
+
IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "CONTROLLER", args: [] });
|
791
|
+
const ctl = IOCContainer.getInsByClass(item.target);
|
792
|
+
if (!(ctl instanceof BaseController)) {
|
793
|
+
throw new Error(`class ${item.id} does not inherit from BaseController`);
|
794
|
+
}
|
795
|
+
controllers[item.id] = 1;
|
796
|
+
}
|
797
|
+
});
|
798
|
+
app.setMetaData("_controllers", controllers);
|
799
|
+
}
|
800
|
+
/**
|
801
|
+
* Load services
|
802
|
+
*
|
803
|
+
* @static
|
804
|
+
* @param {*} app
|
805
|
+
* @memberof Loader
|
806
|
+
*/
|
807
|
+
static LoadServices(app) {
|
808
|
+
const serviceList = IOCContainer.listClass("SERVICE");
|
809
|
+
serviceList.forEach((item) => {
|
810
|
+
var _a;
|
811
|
+
item.id = ((_a = item.id) !== null && _a !== void 0 ? _a : "").replace("SERVICE:", "");
|
812
|
+
if (item.id && Helper.isClass(item.target)) {
|
813
|
+
Logger.Debug(`Load service: ${item.id}`);
|
814
|
+
// registering to IOC
|
815
|
+
IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "SERVICE", args: [] });
|
816
|
+
const ctl = IOCContainer.getInsByClass(item.target);
|
817
|
+
if (!(ctl instanceof BaseService)) {
|
818
|
+
throw new Error(`class ${item.id} does not inherit from BaseService`);
|
819
|
+
}
|
820
|
+
}
|
821
|
+
});
|
822
|
+
}
|
823
|
+
/**
|
824
|
+
* Load components
|
825
|
+
*
|
826
|
+
* @static
|
827
|
+
* @param {*} app
|
828
|
+
* @memberof Loader
|
829
|
+
*/
|
830
|
+
static LoadComponents(app) {
|
831
|
+
const componentList = IOCContainer.listClass("COMPONENT");
|
832
|
+
componentList.forEach((item) => {
|
833
|
+
var _a;
|
834
|
+
item.id = ((_a = item.id) !== null && _a !== void 0 ? _a : "").replace("COMPONENT:", "");
|
835
|
+
if (item.id && !(item.id).endsWith("Plugin") && Helper.isClass(item.target)) {
|
836
|
+
Logger.Debug(`Load component: ${item.id}`);
|
837
|
+
// inject schedule
|
838
|
+
// injectSchedule(item.target, item.target.prototype, IOCContainer);
|
839
|
+
// registering to IOC
|
840
|
+
IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
|
841
|
+
}
|
842
|
+
});
|
843
|
+
}
|
844
|
+
/**
|
845
|
+
* Load plugins
|
846
|
+
*
|
847
|
+
* @static
|
848
|
+
* @param {*} app
|
849
|
+
* @memberof Loader
|
850
|
+
*/
|
851
|
+
static async LoadPlugins(app) {
|
852
|
+
var _a;
|
853
|
+
const componentList = IOCContainer.listClass("COMPONENT");
|
854
|
+
let pluginsConf = app.config(undefined, "plugin");
|
855
|
+
if (Helper.isEmpty(pluginsConf)) {
|
856
|
+
pluginsConf = { config: {}, list: [] };
|
857
|
+
}
|
858
|
+
const pluginList = [];
|
859
|
+
componentList.forEach(async (item) => {
|
860
|
+
var _a;
|
861
|
+
item.id = ((_a = item.id) !== null && _a !== void 0 ? _a : "").replace("COMPONENT:", "");
|
862
|
+
if (item.id && (item.id).endsWith("Plugin") && Helper.isClass(item.target)) {
|
863
|
+
// Logger.Debug(`Load plugin: ${item.id}`);
|
864
|
+
// registering to IOC
|
865
|
+
IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
|
866
|
+
pluginList.push(item.id);
|
867
|
+
}
|
868
|
+
});
|
869
|
+
const pluginConfList = pluginsConf.list;
|
870
|
+
if (pluginList.length > pluginConfList.length) {
|
871
|
+
Logger.Warn("Some plugins is loaded but not allowed to execute.");
|
872
|
+
}
|
873
|
+
for (const key of pluginConfList) {
|
874
|
+
const handle = IOCContainer.get(key, "COMPONENT");
|
875
|
+
if (!Helper.isFunction(handle.run)) {
|
876
|
+
Logger.Error(`plugin ${key} must be implements method 'run'.`);
|
877
|
+
continue;
|
878
|
+
}
|
879
|
+
if (pluginsConf.config[key] === false) {
|
880
|
+
continue;
|
881
|
+
}
|
882
|
+
// Logger.Debug(`Execute plugin: ${key}`);
|
883
|
+
// sync exec
|
884
|
+
await handle.run((_a = pluginsConf.config[key]) !== null && _a !== void 0 ? _a : {}, app);
|
885
|
+
}
|
886
|
+
}
|
887
|
+
}
|
888
|
+
|
889
|
+
var version = "3.5.12-0";
|
890
|
+
var engines = {
|
891
|
+
node: ">12.0.0"
|
892
|
+
};
|
893
|
+
|
894
|
+
/*
|
895
|
+
* @Description:
|
896
|
+
* @Usage:
|
897
|
+
* @Author: richen
|
898
|
+
* @Date: 2021-12-17 11:54:06
|
899
|
+
* @LastEditTime: 2021-12-17 13:13:00
|
900
|
+
*/
|
901
|
+
const KOATTY_VERSION = version;
|
902
|
+
const ENGINES_VERSION = engines.node.slice(1) || '12.0.0';
|
903
|
+
/**
|
904
|
+
* check node version
|
905
|
+
* @return {void} []
|
906
|
+
*/
|
907
|
+
function checkRuntime() {
|
908
|
+
let nodeEngines = ENGINES_VERSION;
|
909
|
+
nodeEngines = nodeEngines.slice(0, nodeEngines.lastIndexOf('.'));
|
910
|
+
let nodeVersion = process.version;
|
911
|
+
if (nodeVersion[0] === 'v') {
|
912
|
+
nodeVersion = nodeVersion.slice(1);
|
913
|
+
}
|
914
|
+
nodeVersion = nodeVersion.slice(0, nodeVersion.lastIndexOf('.'));
|
915
|
+
if (Helper.toNumber(nodeEngines) > Helper.toNumber(nodeVersion)) {
|
916
|
+
Logger.Error(`Koatty need node version > ${nodeEngines}, current version is ${nodeVersion}, please upgrade it.`);
|
917
|
+
process.exit(-1);
|
918
|
+
}
|
919
|
+
}
|
920
|
+
|
921
|
+
/**
|
922
|
+
* @ author: richen
|
923
|
+
* @ copyright: Copyright (c) - <richenlin(at)gmail.com>
|
924
|
+
* @ license: BSD (3-Clause)
|
925
|
+
* @ version: 2020-07-06 11:22:58
|
926
|
+
*/
|
927
|
+
/**
|
928
|
+
* execute bootstrap
|
929
|
+
*
|
930
|
+
* @param {*} target
|
931
|
+
* @param {Function} bootFunc
|
932
|
+
* @returns {Promise<void>}
|
933
|
+
*/
|
934
|
+
const ExecBootstrap = async function (target, bootFunc) {
|
935
|
+
// checked runtime
|
936
|
+
checkRuntime();
|
937
|
+
const app = Reflect.construct(target, []);
|
938
|
+
try {
|
939
|
+
console.log(LOGO);
|
940
|
+
if (!(app instanceof Koatty)) {
|
941
|
+
throw new Error(`class ${target.name} does not inherit from Koatty`);
|
942
|
+
}
|
943
|
+
// version
|
944
|
+
Helper.define(app, "version", KOATTY_VERSION);
|
945
|
+
// Initialize env
|
946
|
+
Loader.initialize(app);
|
947
|
+
// exec bootFunc
|
948
|
+
if (Helper.isFunction(bootFunc)) {
|
949
|
+
Logger.Log('think', '', 'Execute bootFunc ...');
|
950
|
+
await bootFunc(app);
|
951
|
+
}
|
952
|
+
// Set IOCContainer.app
|
953
|
+
IOCContainer.setApp(app);
|
954
|
+
Logger.Log('think', '', 'ComponentScan ...');
|
955
|
+
// Check all bean
|
956
|
+
Loader.CheckAllComponents(app, target);
|
957
|
+
// Load configuration
|
958
|
+
Logger.Log('think', '', 'Load Configurations ...');
|
959
|
+
// configuration metadata
|
960
|
+
const configurationMetas = Loader.GetConfigurationMetas(app, target);
|
961
|
+
Loader.LoadConfigs(app, configurationMetas);
|
962
|
+
// Load Plugin
|
963
|
+
Logger.Log('think', '', 'Load Plugins ...');
|
964
|
+
await Loader.LoadPlugins(app);
|
965
|
+
// Set Logger
|
966
|
+
Loader.SetLogger(app);
|
967
|
+
// app.emit("appBoot");
|
968
|
+
await asyncEvent(app, 'appBoot');
|
969
|
+
// Load App ready hooks
|
970
|
+
Loader.LoadAppReadyHooks(app, target);
|
971
|
+
// New router
|
972
|
+
const KoattyRouter = newRouter(app);
|
973
|
+
// Load Middleware
|
974
|
+
Logger.Log('think', '', 'Load Middlewares ...');
|
975
|
+
await Loader.LoadMiddlewares(app);
|
976
|
+
// Load Components
|
977
|
+
Logger.Log('think', '', 'Load Components ...');
|
978
|
+
Loader.LoadComponents(app);
|
979
|
+
// Load Services
|
980
|
+
Logger.Log('think', '', 'Load Services ...');
|
981
|
+
Loader.LoadServices(app);
|
982
|
+
// Load Controllers
|
983
|
+
Logger.Log('think', '', 'Load Controllers ...');
|
984
|
+
Loader.LoadControllers(app);
|
985
|
+
// Emit app ready event
|
986
|
+
Logger.Log('think', '', 'Emit App Ready ...');
|
987
|
+
// app.emit("appReady");
|
988
|
+
await asyncEvent(app, 'appReady');
|
989
|
+
// Load Routers
|
990
|
+
Logger.Log('think', '', 'Load Routers ...');
|
991
|
+
KoattyRouter.LoadRouter(app.getMetaData("_controllers"));
|
992
|
+
// Emit app started event
|
993
|
+
Logger.Log('think', '', 'Emit App Start ...');
|
994
|
+
// app.emit("appStart");
|
995
|
+
const server = newServe(app);
|
996
|
+
await asyncEvent(app, 'appStart');
|
997
|
+
Logger.Log('think', '', '====================================');
|
998
|
+
// Start server
|
999
|
+
app.listen(server);
|
1000
|
+
// binding event "appStop"
|
1001
|
+
BindProcessEvent(app, 'appStop');
|
1002
|
+
}
|
1003
|
+
catch (err) {
|
1004
|
+
Logger.Error(err);
|
1005
|
+
process.exit();
|
1006
|
+
}
|
1007
|
+
};
|
1008
|
+
/**
|
1009
|
+
* create router
|
1010
|
+
*
|
1011
|
+
* @export
|
1012
|
+
* @param {Koatty} app
|
1013
|
+
* @returns {*}
|
1014
|
+
*/
|
1015
|
+
const newRouter = function (app) {
|
1016
|
+
var _a;
|
1017
|
+
const protocol = app.config("protocol") || "http";
|
1018
|
+
const options = (_a = app.config(undefined, 'router')) !== null && _a !== void 0 ? _a : {};
|
1019
|
+
const router = NewRouter(app, options, protocol);
|
1020
|
+
Helper.define(app, "router", router);
|
1021
|
+
return router;
|
1022
|
+
};
|
1023
|
+
/**
|
1024
|
+
* create serve
|
1025
|
+
*
|
1026
|
+
* @param {Koatty} app
|
1027
|
+
* @returns {*}
|
1028
|
+
*/
|
1029
|
+
const newServe = function (app) {
|
1030
|
+
const protocol = app.config("protocol") || "http";
|
1031
|
+
const server = Serve(app, protocol);
|
1032
|
+
Helper.define(app, "server", server);
|
1033
|
+
return server;
|
1034
|
+
};
|
1035
|
+
/**
|
1036
|
+
* Execute event as async
|
1037
|
+
*
|
1038
|
+
* @param {Koatty} event
|
1039
|
+
* @param {string} eventName
|
1040
|
+
*/
|
1041
|
+
const asyncEvent = async function (event, eventName) {
|
1042
|
+
const ls = event.listeners(eventName);
|
1043
|
+
// eslint-disable-next-line no-restricted-syntax
|
1044
|
+
for await (const func of ls) {
|
1045
|
+
if (Helper.isFunction(func)) {
|
1046
|
+
func();
|
1047
|
+
}
|
1048
|
+
}
|
1049
|
+
return event.removeAllListeners(eventName);
|
1050
|
+
};
|
1051
|
+
/**
|
1052
|
+
* Bootstrap application
|
1053
|
+
*
|
1054
|
+
* @export
|
1055
|
+
* @param {Function} [bootFunc]
|
1056
|
+
* @returns {ClassDecorator}
|
1057
|
+
*/
|
1058
|
+
function Bootstrap(bootFunc) {
|
1059
|
+
return function (target) {
|
1060
|
+
if (!(target.prototype instanceof Koatty)) {
|
1061
|
+
throw new Error(`class does not inherit from Koatty`);
|
1062
|
+
}
|
1063
|
+
ExecBootstrap(target, bootFunc);
|
1064
|
+
};
|
1065
|
+
}
|
1066
|
+
/**
|
1067
|
+
* Define project scan path
|
1068
|
+
*
|
1069
|
+
* @export
|
1070
|
+
* @param {(string | string[])} [scanPath]
|
1071
|
+
* @returns {ClassDecorator}
|
1072
|
+
*/
|
1073
|
+
function ComponentScan(scanPath) {
|
1074
|
+
Logger.Log('think', '', 'ComponentScan');
|
1075
|
+
return (target) => {
|
1076
|
+
if (!(target.prototype instanceof Koatty)) {
|
1077
|
+
throw new Error(`class does not inherit from Koatty`);
|
1078
|
+
}
|
1079
|
+
scanPath = scanPath !== null && scanPath !== void 0 ? scanPath : '';
|
1080
|
+
IOCContainer.saveClassMetadata(TAGGED_CLS, COMPONENT_SCAN, scanPath, target);
|
1081
|
+
};
|
1082
|
+
}
|
1083
|
+
/**
|
1084
|
+
* Define project configuration scan path
|
1085
|
+
*
|
1086
|
+
* @export
|
1087
|
+
* @param {(string | string[])} [scanPath]
|
1088
|
+
* @returns {ClassDecorator}
|
1089
|
+
*/
|
1090
|
+
function ConfigurationScan(scanPath) {
|
1091
|
+
Logger.Log('think', '', 'ConfigurationScan');
|
1092
|
+
return (target) => {
|
1093
|
+
if (!(target.prototype instanceof Koatty)) {
|
1094
|
+
throw new Error(`class does not inherit from Koatty`);
|
1095
|
+
}
|
1096
|
+
scanPath = scanPath !== null && scanPath !== void 0 ? scanPath : '';
|
1097
|
+
IOCContainer.saveClassMetadata(TAGGED_CLS, CONFIGURATION_SCAN, scanPath, target);
|
1098
|
+
};
|
1099
|
+
}
|
1100
|
+
/**
|
1101
|
+
* bind AppReadyHookFunc
|
1102
|
+
* example:
|
1103
|
+
* export function TestDecorator(): ClassDecorator {
|
1104
|
+
* return (target: any) => {
|
1105
|
+
* BindAppReadyHook((app: Koatty) => {
|
1106
|
+
* // todo
|
1107
|
+
* return Promise.resolve();
|
1108
|
+
* }, target)
|
1109
|
+
* }
|
1110
|
+
* }
|
1111
|
+
*
|
1112
|
+
* @export
|
1113
|
+
* @param {AppReadyHookFunc} func
|
1114
|
+
* @param {*} target
|
1115
|
+
*/
|
1116
|
+
function BindAppReadyHook(func, target) {
|
1117
|
+
IOCContainer.attachClassMetadata(TAGGED_CLS, APP_READY_HOOK, func, target);
|
1118
|
+
}
|
1119
|
+
|
1120
|
+
/**
|
1121
|
+
* @ author: richen
|
1122
|
+
* @ copyright: Copyright (c) - <richenlin(at)gmail.com>
|
1123
|
+
* @ license: BSD (3-Clause)
|
1124
|
+
* @ version: 2020-05-10 11:32:45
|
1125
|
+
*/
|
1126
|
+
/**
|
1127
|
+
* Indicates that an decorated class is a "component".
|
1128
|
+
*
|
1129
|
+
* @export
|
1130
|
+
* @param {string} [identifier] component name
|
1131
|
+
* @returns {ClassDecorator}
|
1132
|
+
*/
|
1133
|
+
function Component(identifier) {
|
1134
|
+
return (target) => {
|
1135
|
+
identifier = identifier || IOCContainer.getIdentifier(target);
|
1136
|
+
IOCContainer.saveClass("COMPONENT", target, identifier);
|
1137
|
+
};
|
1138
|
+
}
|
1139
|
+
/**
|
1140
|
+
* Indicates that an decorated class is a "controller".
|
1141
|
+
*
|
1142
|
+
* @export
|
1143
|
+
* @param {string} [path] controller router path
|
1144
|
+
* @returns {ClassDecorator}
|
1145
|
+
*/
|
1146
|
+
function Controller(path = "") {
|
1147
|
+
return (target) => {
|
1148
|
+
const identifier = IOCContainer.getIdentifier(target);
|
1149
|
+
IOCContainer.saveClass("CONTROLLER", target, identifier);
|
1150
|
+
IOCContainer.savePropertyData(CONTROLLER_ROUTER, path, target, identifier);
|
1151
|
+
};
|
1152
|
+
}
|
1153
|
+
/**
|
1154
|
+
* Indicates that an decorated class is a "middleware".
|
1155
|
+
*
|
1156
|
+
* @export
|
1157
|
+
* @param {string} [identifier] middleware name
|
1158
|
+
* @returns {ClassDecorator}
|
1159
|
+
*/
|
1160
|
+
function Middleware(identifier) {
|
1161
|
+
return (target) => {
|
1162
|
+
identifier = identifier || IOCContainer.getIdentifier(target);
|
1163
|
+
IOCContainer.saveClass("MIDDLEWARE", target, identifier);
|
1164
|
+
};
|
1165
|
+
}
|
1166
|
+
/**
|
1167
|
+
* Indicates that an decorated class is a "service".
|
1168
|
+
*
|
1169
|
+
* @export
|
1170
|
+
* @param {string} [identifier] middleware name
|
1171
|
+
* @returns {ClassDecorator}
|
1172
|
+
*/
|
1173
|
+
function Service(identifier) {
|
1174
|
+
return (target) => {
|
1175
|
+
identifier = identifier || IOCContainer.getIdentifier(target);
|
1176
|
+
IOCContainer.saveClass("SERVICE", target, identifier);
|
1177
|
+
};
|
1178
|
+
}
|
1179
|
+
/**
|
1180
|
+
* Indicates that an decorated class is a "plugin".
|
1181
|
+
*
|
1182
|
+
* @export
|
1183
|
+
* @param {string} [identifier]
|
1184
|
+
* @returns {ClassDecorator}
|
1185
|
+
*/
|
1186
|
+
function Plugin(identifier) {
|
1187
|
+
return (target) => {
|
1188
|
+
identifier = identifier || IOCContainer.getIdentifier(target);
|
1189
|
+
//
|
1190
|
+
if (!identifier.endsWith("Plugin")) {
|
1191
|
+
throw Error("Plugin class name must be 'Plugin' suffix.");
|
1192
|
+
}
|
1193
|
+
IOCContainer.saveClass("COMPONENT", target, `${identifier}`);
|
1194
|
+
};
|
1195
|
+
}
|
1196
|
+
|
1197
|
+
export { BaseController, BaseService, BindAppReadyHook, Bootstrap, Component, ComponentScan, ConfigurationScan, Controller, HttpController, Logger, Middleware, Plugin, Service };
|