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/dist/index.js CHANGED
@@ -1,13 +1,12 @@
1
1
  /*!
2
2
  * @Author: richen
3
- * @Date: 2023-12-11 04:45:04
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
- * @Description: trace & catcher middleware
261
- * @Usage:
262
- * @Author: richen
263
- * @Date: 2023-12-09 22:55:54
264
- * @LastEditTime: 2023-12-09 23:00:44
265
- * @License: BSD (3-Clause)
266
- * @Copyright (c): <richenlin(at)gmail.com>
267
- */
268
- class TraceMiddleware {
269
- run(options, app) {
270
- return koatty_trace.Trace(options, app);
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-09 23:00:37
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
- let middlewareConf = app.config(undefined, "middleware");
510
- if (koatty_lib.Helper.isEmpty(middlewareConf)) {
511
- middlewareConf = { config: {}, list: [] };
512
- }
513
- //Mount default middleware
514
- koatty_loader.Load(loadPath || ["./middleware"], app.koattyPath);
515
- //Mount application middleware
516
- // const middleware: any = {};
517
- const appMiddleware = koatty_container.IOCContainer.listClass("MIDDLEWARE") ?? [];
518
- appMiddleware.push({ id: "TraceMiddleware", target: TraceMiddleware });
519
- appMiddleware.forEach((item) => {
520
- item.id = (item.id ?? "").replace("MIDDLEWARE:", "");
521
- if (item.id && koatty_lib.Helper.isClass(item.target)) {
522
- koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "MIDDLEWARE", args: [] });
523
- }
524
- });
525
- const middlewareConfList = middlewareConf.list;
526
- const defaultList = ["TraceMiddleware"];
527
- //de-duplication
528
- const appMList = new Set(defaultList);
529
- middlewareConfList.forEach((item) => {
530
- appMList.add(item);
531
- });
532
- //Automatically call middleware
533
- for (const key of appMList) {
534
- const handle = koatty_container.IOCContainer.get(key, "MIDDLEWARE");
535
- if (!handle) {
536
- Logger.Error(`Middleware ${key} load error.`);
537
- continue;
538
- }
539
- if (!koatty_lib.Helper.isFunction(handle.run)) {
540
- Logger.Error(`Middleware ${key} must be implements method 'run'.`);
541
- continue;
542
- }
543
- if (middlewareConf.config[key] === false) {
544
- // Default middleware cannot be disabled
545
- if (defaultList.includes(key)) {
546
- Logger.Warn(`Middleware ${key} cannot be disabled.`);
547
- }
548
- else {
549
- Logger.Warn(`Middleware ${key} already loaded but not effective.`);
550
- continue;
551
- }
552
- }
553
- Logger.Debug(`Load middleware: ${key}`);
554
- const result = await handle.run(middlewareConf.config[key] || {}, app);
555
- if (koatty_lib.Helper.isFunction(result)) {
556
- if (result.length < 3) {
557
- app.use(result);
558
- }
559
- else {
560
- app.useExp(result);
561
- }
562
- }
563
- }
564
- }
565
- /**
566
- * Load controllers
567
- *
568
- * @static
569
- * @param {*} app
570
- * @memberof Loader
571
- */
572
- static LoadControllers(app) {
573
- const controllerList = koatty_container.IOCContainer.listClass("CONTROLLER");
574
- const controllers = [];
575
- controllerList.forEach((item) => {
576
- item.id = (item.id ?? "").replace("CONTROLLER:", "");
577
- if (item.id && koatty_lib.Helper.isClass(item.target)) {
578
- Logger.Debug(`Load controller: ${item.id}`);
579
- // registering to IOC
580
- koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Prototype", type: "CONTROLLER", args: [] });
581
- const ctl = koatty_container.IOCContainer.getInsByClass(item.target);
582
- if (!(ctl instanceof BaseController)) {
583
- throw new Error(`class ${item.id} does not inherit from BaseController`);
584
- }
585
- controllers.push(item.id);
586
- }
587
- });
588
- return controllers;
589
- }
590
- /**
591
- * Load services
592
- *
593
- * @static
594
- * @param {*} app
595
- * @memberof Loader
596
- */
597
- static LoadServices(app) {
598
- const serviceList = koatty_container.IOCContainer.listClass("SERVICE");
599
- serviceList.forEach((item) => {
600
- item.id = (item.id ?? "").replace("SERVICE:", "");
601
- if (item.id && koatty_lib.Helper.isClass(item.target)) {
602
- Logger.Debug(`Load service: ${item.id}`);
603
- // registering to IOC
604
- koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "SERVICE", args: [] });
605
- }
606
- });
607
- }
608
- /**
609
- * Load components
610
- *
611
- * @static
612
- * @param {*} app
613
- * @memberof Loader
614
- */
615
- // public static LoadComponents(app: Koatty) {
616
- // const componentList = IOCContainer.listClass("COMPONENT");
617
- // componentList.forEach((item: ComponentItem) => {
618
- // item.id = (item.id ?? "").replace("COMPONENT:", "");
619
- // if (item.id && !(item.id).endsWith("Plugin") && Helper.isClass(item.target)) {
620
- // Logger.Debug(`Load component: ${item.id}`);
621
- // // registering to IOC
622
- // IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
623
- // }
624
- // });
625
- // }
626
- /**
627
- * Load components
628
- *
629
- * @static
630
- * @param {*} app
631
- * @memberof Loader
632
- */
633
- static async LoadComponents(app) {
634
- const componentList = koatty_container.IOCContainer.listClass("COMPONENT");
635
- const pluginList = [];
636
- componentList.forEach(async (item) => {
637
- item.id = (item.id ?? "").replace("COMPONENT:", "");
638
- if (koatty_lib.Helper.isClass(item.target)) {
639
- if (item.id && (item.id).endsWith("Plugin")) {
640
- pluginList.push(item.id);
641
- }
642
- // registering to IOC
643
- koatty_container.IOCContainer.reg(item.id, item.target, { scope: "Singleton", type: "COMPONENT", args: [] });
644
- }
645
- });
646
- // load plugin config
647
- let pluginsConf = app.config(undefined, "plugin");
648
- if (koatty_lib.Helper.isEmpty(pluginsConf)) {
649
- pluginsConf = { config: {}, list: [] };
650
- }
651
- const pluginConfList = pluginsConf.list ?? [];
652
- // load plugin list
653
- for (const key of pluginConfList) {
654
- const handle = koatty_container.IOCContainer.get(key, "COMPONENT");
655
- if (!handle) {
656
- Logger.Error(`Plugin ${key} load error.`);
657
- continue;
658
- }
659
- if (!koatty_lib.Helper.isFunction(handle.run)) {
660
- Logger.Error(`Plugin ${key} must be implements method 'run'.`);
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-1";
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-09 22:59:19
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
- * Indicates that an decorated class is a "component".
946
- *
947
- * @export
948
- * @param {string} [identifier] component name
949
- * @returns {ClassDecorator}
950
- */
951
- function Component(identifier) {
952
- return (target) => {
953
- identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
954
- koatty_container.IOCContainer.saveClass("COMPONENT", target, identifier);
955
- };
956
- }
957
- /**
958
- * Indicates that an decorated class is a "controller".
959
- *
960
- * @export
961
- * @param {string} [path] controller router path
962
- * @returns {ClassDecorator}
963
- */
964
- function Controller(path = "") {
965
- return (target) => {
966
- const identifier = koatty_container.IOCContainer.getIdentifier(target);
967
- koatty_container.IOCContainer.saveClass("CONTROLLER", target, identifier);
968
- koatty_container.IOCContainer.savePropertyData(koatty_serve.CONTROLLER_ROUTER, path, target, identifier);
969
- };
970
- }
971
- /**
972
- * Indicates that an decorated class is a "middleware".
973
- *
974
- * @export
975
- * @param {string} [identifier] class name
976
- * @returns {ClassDecorator}
977
- */
978
- function Middleware(identifier) {
979
- return (target) => {
980
- identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
981
- koatty_container.IOCContainer.saveClass("MIDDLEWARE", target, identifier);
982
- };
983
- }
984
- /**
985
- * Indicates that an decorated class is a "service".
986
- *
987
- * @export
988
- * @param {string} [identifier] class name
989
- * @returns {ClassDecorator}
990
- */
991
- function Service(identifier) {
992
- return (target) => {
993
- identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
994
- koatty_container.IOCContainer.saveClass("SERVICE", target, identifier);
995
- };
996
- }
997
- /**
998
- * Indicates that an decorated class is a "plugin".
999
- *
1000
- * @export
1001
- * @param {string} [identifier] class name
1002
- * @returns {ClassDecorator}
1003
- */
1004
- function Plugin(identifier) {
1005
- return (target) => {
1006
- identifier = identifier || koatty_container.IOCContainer.getIdentifier(target);
1007
- //
1008
- if (!identifier.endsWith("Plugin")) {
1009
- throw Error("Plugin class name must be 'Plugin' suffix.");
1010
- }
1011
- koatty_container.IOCContainer.saveClass("COMPONENT", target, `${identifier}`);
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' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
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' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
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' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
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' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
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' && !exports.hasOwnProperty(k)) Object.defineProperty(exports, k, {
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
  });