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