@eggjs/core 6.4.1 → 6.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +22 -22
  2. package/dist/commonjs/egg.d.ts +17 -18
  3. package/dist/commonjs/egg.js +9 -9
  4. package/dist/commonjs/lifecycle.d.ts +2 -2
  5. package/dist/commonjs/lifecycle.js +16 -13
  6. package/dist/commonjs/loader/context_loader.js +2 -2
  7. package/dist/commonjs/loader/egg_loader.d.ts +13 -13
  8. package/dist/commonjs/loader/egg_loader.js +77 -62
  9. package/dist/commonjs/loader/file_loader.d.ts +3 -3
  10. package/dist/commonjs/loader/file_loader.js +22 -24
  11. package/dist/commonjs/singleton.d.ts +2 -2
  12. package/dist/commonjs/singleton.js +5 -6
  13. package/dist/commonjs/utils/index.d.ts +2 -2
  14. package/dist/commonjs/utils/index.js +4 -4
  15. package/dist/commonjs/utils/sequencify.d.ts +1 -1
  16. package/dist/commonjs/utils/sequencify.js +18 -13
  17. package/dist/commonjs/utils/timing.js +14 -8
  18. package/dist/esm/egg.d.ts +17 -18
  19. package/dist/esm/egg.js +11 -11
  20. package/dist/esm/lifecycle.d.ts +2 -2
  21. package/dist/esm/lifecycle.js +16 -13
  22. package/dist/esm/loader/context_loader.js +2 -2
  23. package/dist/esm/loader/egg_loader.d.ts +13 -13
  24. package/dist/esm/loader/egg_loader.js +80 -65
  25. package/dist/esm/loader/file_loader.d.ts +3 -3
  26. package/dist/esm/loader/file_loader.js +23 -25
  27. package/dist/esm/singleton.d.ts +2 -2
  28. package/dist/esm/singleton.js +5 -6
  29. package/dist/esm/utils/index.d.ts +2 -2
  30. package/dist/esm/utils/index.js +4 -4
  31. package/dist/esm/utils/sequencify.d.ts +1 -1
  32. package/dist/esm/utils/sequencify.js +18 -13
  33. package/dist/esm/utils/timing.js +14 -8
  34. package/dist/package.json +1 -1
  35. package/package.json +16 -6
  36. package/src/egg.ts +159 -59
  37. package/src/lifecycle.ts +72 -33
  38. package/src/loader/context_loader.ts +9 -7
  39. package/src/loader/egg_loader.ts +445 -183
  40. package/src/loader/file_loader.ts +78 -37
  41. package/src/singleton.ts +64 -26
  42. package/src/utils/index.ts +20 -13
  43. package/src/utils/sequencify.ts +50 -15
  44. package/src/utils/timing.ts +27 -13
package/src/egg.ts CHANGED
@@ -1,26 +1,33 @@
1
1
  /* eslint-disable prefer-spread */
2
2
  import assert from 'node:assert';
3
3
  import { debuglog } from 'node:util';
4
+
4
5
  import {
5
- Application as KoaApplication, Context as KoaContext,
6
- Request as KoaRequest, Response as KoaResponse,
7
- } from '@eggjs/koa';
8
- import type {
9
- MiddlewareFunc as KoaMiddlewareFunc,
10
- Next,
6
+ Application as KoaApplication,
7
+ Context as KoaContext,
8
+ Request as KoaRequest,
9
+ Response as KoaResponse,
10
+ type MiddlewareFunc as KoaMiddlewareFunc,
11
+ type Next,
11
12
  } from '@eggjs/koa';
12
- import { EggConsoleLogger, Logger } from 'egg-logger';
13
- import { RegisterOptions, ResourcesController, EggRouter as Router } from '@eggjs/router';
13
+ import { EggConsoleLogger, type Logger } from 'egg-logger';
14
+ import {
15
+ EggRouter as Router,
16
+ type RegisterOptions,
17
+ type ResourcesController,
18
+ } from '@eggjs/router';
14
19
  import type { ReadyFunctionArg } from 'get-ready';
20
+
15
21
  import { BaseContextClass } from './base_context_class.js';
16
22
  import { Timing } from './utils/timing.js';
17
- import type { Fun } from './utils/index.js';
18
23
  import { Lifecycle } from './lifecycle.js';
19
24
  import { EggLoader } from './loader/egg_loader.js';
20
- import utils from './utils/index.js';
21
- import { EggAppConfig } from './types.js';
25
+ import utils, { type Fun } from './utils/index.js';
26
+ import type { EggAppConfig } from './types.js';
22
27
  import {
23
- Singleton, type SingletonCreateMethod, type SingletonOptions,
28
+ Singleton,
29
+ type SingletonCreateMethod,
30
+ type SingletonOptions,
24
31
  } from './singleton.js';
25
32
 
26
33
  const debug = debuglog('@eggjs/core/egg');
@@ -38,15 +45,10 @@ export interface EggCoreOptions {
38
45
  export type EggCoreInitOptions = Partial<EggCoreOptions>;
39
46
 
40
47
  // export @eggjs/koa classes
41
- export {
42
- KoaRequest, KoaResponse, KoaContext, KoaApplication,
43
- Router,
44
- };
48
+ export { KoaRequest, KoaResponse, KoaContext, KoaApplication, Router };
45
49
 
46
50
  // export @eggjs/koa types
47
- export type {
48
- Next, KoaMiddlewareFunc,
49
- };
51
+ export type { Next, KoaMiddlewareFunc };
50
52
 
51
53
  // export @eggjs/core classes
52
54
  export class Request extends KoaRequest {
@@ -96,7 +98,8 @@ export class Context extends KoaContext {
96
98
  }
97
99
 
98
100
  // export @eggjs/core types
99
- export type MiddlewareFunc<T = Context> = KoaMiddlewareFunc<T>;
101
+ export type MiddlewareFunc<T extends KoaContext = Context> =
102
+ KoaMiddlewareFunc<T>;
100
103
 
101
104
  export class EggCore extends KoaApplication {
102
105
  options: EggCoreOptions;
@@ -112,27 +115,38 @@ export class EggCore extends KoaApplication {
112
115
  #router?: Router;
113
116
 
114
117
  /** auto inject on loadService() */
118
+
115
119
  readonly serviceClasses: Record<string, any> = {};
116
120
  /** auto inject on loadController() */
121
+
117
122
  readonly controller: Record<string, any> = {};
118
123
  /** auto inject on loadMiddleware() */
119
- readonly middlewares: Record<string, (opt: any, app: EggCore) => MiddlewareFunc> = {};
124
+ readonly middlewares: Record<
125
+ string,
126
+ (opt: unknown, app: EggCore) => MiddlewareFunc
127
+ > = {};
120
128
 
121
129
  /**
122
130
  * @class
123
131
  * @param {Object} options - options
124
- * @param {String} [options.baseDir=process.cwd()] - the directory of application
125
- * @param {String} [options.type=application|agent] - whether it's running in app worker or agent worker
132
+ * @param {String} [options.baseDir] - the directory of application
133
+ * @param {String} [options.type] - whether it's running in app worker or agent worker
126
134
  * @param {Object} [options.plugins] - custom plugins
127
135
  * @since 1.0.0
128
136
  */
129
137
  constructor(options: EggCoreInitOptions = {}) {
130
138
  options.baseDir = options.baseDir ?? process.cwd();
131
139
  options.type = options.type ?? 'application';
132
- assert(typeof options.baseDir === 'string', 'options.baseDir required, and must be a string');
140
+ assert(
141
+ typeof options.baseDir === 'string',
142
+ 'options.baseDir required, and must be a string'
143
+ );
133
144
  // assert(fs.existsSync(options.baseDir), `Directory ${options.baseDir} not exists`);
134
145
  // assert(fs.statSync(options.baseDir).isDirectory(), `Directory ${options.baseDir} is not a directory`);
135
- assert(options.type === 'application' || options.type === 'agent', 'options.type should be application or agent');
146
+ assert(
147
+ options.type === 'application' || options.type === 'agent',
148
+ 'options.type should be application or agent'
149
+ );
136
150
  super();
137
151
 
138
152
  this.timing = new Timing();
@@ -205,7 +219,7 @@ export class EggCore extends KoaApplication {
205
219
  * @since 1.0.0
206
220
  */
207
221
  const Loader = this[EGG_LOADER];
208
- assert(Loader, 'Symbol.for(\'egg#loader\') is required');
222
+ assert(Loader, "Symbol.for('egg#loader') is required");
209
223
  this.loader = new Loader({
210
224
  baseDir: options.baseDir,
211
225
  app: this,
@@ -249,7 +263,7 @@ export class EggCore extends KoaApplication {
249
263
  * override koa's app.use, support generator function
250
264
  * @since 1.0.0
251
265
  */
252
- use(fn: MiddlewareFunc) {
266
+ use<T extends KoaContext = Context>(fn: MiddlewareFunc<T>) {
253
267
  assert(typeof fn === 'function', 'app.use() requires a function');
254
268
  debug('[use] add middleware: %o', fn._name || fn.name || '-');
255
269
  this.middleware.push(fn as unknown as KoaMiddlewareFunc);
@@ -309,7 +323,7 @@ export class EggCore extends KoaApplication {
309
323
  * @since 1.0.0
310
324
  */
311
325
  get config(): EggAppConfig {
312
- return this.loader ? this.loader.config : {} as EggAppConfig;
326
+ return this.loader ? this.loader.config : ({} as EggAppConfig);
313
327
  }
314
328
 
315
329
  /**
@@ -326,7 +340,9 @@ export class EggCore extends KoaApplication {
326
340
  * @param {string} [name] scope name, default is empty string
327
341
  */
328
342
  beforeStart(scope: Fun, name?: string) {
329
- this.deprecate('`beforeStart` was deprecated, please use "Life Cycles" instead, see https://www.eggjs.org/advanced/loader#life-cycles');
343
+ this.deprecate(
344
+ '`beforeStart` was deprecated, please use "Life Cycles" instead, see https://www.eggjs.org/advanced/loader#life-cycles'
345
+ );
330
346
  this.lifecycle.registerBeforeStart(scope, name ?? '');
331
347
  }
332
348
 
@@ -363,13 +379,15 @@ export class EggCore extends KoaApplication {
363
379
  * @param {object} opts -
364
380
  * - {Number} [timeout=10000] - emit `ready_timeout` when it doesn't finish but reach the timeout
365
381
  * - {Boolean} [isWeakDep=false] - whether it's a weak dependency
366
- * @return {Function} - a callback
382
+ * @returns {Function} - a callback
367
383
  * @example
368
384
  * const done = app.readyCallback('mysql');
369
385
  * mysql.ready(done);
370
386
  */
371
387
  readyCallback(name: string, opts: object) {
372
- this.deprecate('`readyCallback` was deprecated, please use "Life Cycles" instead, see https://www.eggjs.org/advanced/loader#life-cycles');
388
+ this.deprecate(
389
+ '`readyCallback` was deprecated, please use "Life Cycles" instead, see https://www.eggjs.org/advanced/loader#life-cycles'
390
+ );
373
391
  return this.lifecycle.legacyReadyCallback(name, opts);
374
392
  }
375
393
 
@@ -386,7 +404,9 @@ export class EggCore extends KoaApplication {
386
404
  * @param {Function} fn - the function that can be generator function or async function.
387
405
  */
388
406
  beforeClose(fn: Fun, name?: string) {
389
- this.deprecate('`beforeClose` was deprecated, please use "Life Cycles" instead, see https://www.eggjs.org/advanced/loader#life-cycles');
407
+ this.deprecate(
408
+ '`beforeClose` was deprecated, please use "Life Cycles" instead, see https://www.eggjs.org/advanced/loader#life-cycles'
409
+ );
390
410
  this.lifecycle.registerBeforeClose(fn, name);
391
411
  }
392
412
 
@@ -398,7 +418,7 @@ export class EggCore extends KoaApplication {
398
418
  *
399
419
  * If error is thrown when it's closing, the promise will reject.
400
420
  * It will also reject after following call.
401
- * @return {Promise} promise
421
+ * @returns {Promise} promise
402
422
  * @since 1.0.0
403
423
  */
404
424
  async close(): Promise<void> {
@@ -416,25 +436,33 @@ export class EggCore extends KoaApplication {
416
436
  if (this.#router) {
417
437
  return this.#router;
418
438
  }
419
- const router = this.#router = new Router({ sensitive: true }, this);
420
- return router;
439
+ this.#router = new Router({ sensitive: true }, this);
440
+ return this.#router;
421
441
  }
422
442
 
423
443
  /**
424
444
  * Alias to {@link Router#url}
425
445
  * @param {String} name - Router name
426
446
  * @param {Object} params - more parameters
427
- * @return {String} url
447
+ * @returns {String} url
428
448
  */
429
- url(name: string, params?: any): string {
449
+ url(name: string, params?: Parameters<Router['url']>[1]): string {
430
450
  return this.router.url(name, params);
431
451
  }
432
452
 
433
453
  // delegate all router method to application
434
454
  // 'head', 'options', 'get', 'put', 'patch', 'post', 'delete'
435
455
  // 'all', 'resources', 'register', 'redirect'
436
- head(path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
437
- head(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
456
+ head(
457
+ path: string | RegExp | (string | RegExp)[],
458
+ ...middlewares: (MiddlewareFunc | string)[]
459
+ ): EggCore;
460
+ head(
461
+ name: string,
462
+ path: string | RegExp | (string | RegExp)[],
463
+ ...middlewares: (MiddlewareFunc | string)[]
464
+ ): EggCore;
465
+
438
466
  head(...args: any): EggCore {
439
467
  this.router.head.apply(this.router, args);
440
468
  return this;
@@ -445,68 +473,140 @@ export class EggCore extends KoaApplication {
445
473
  // this.router.options.apply(this.router, args);
446
474
  // return this;
447
475
  // }
448
- get(path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
449
- get(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
476
+ get(
477
+ path: string | RegExp | (string | RegExp)[],
478
+ ...middlewares: (MiddlewareFunc | string)[]
479
+ ): EggCore;
480
+ get(
481
+ name: string,
482
+ path: string | RegExp | (string | RegExp)[],
483
+ ...middlewares: (MiddlewareFunc | string)[]
484
+ ): EggCore;
485
+
450
486
  get(...args: any): EggCore {
451
487
  this.router.get.apply(this.router, args);
452
488
  return this;
453
489
  }
454
- put(path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
455
- put(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
490
+ put(
491
+ path: string | RegExp | (string | RegExp)[],
492
+ ...middlewares: (MiddlewareFunc | string)[]
493
+ ): EggCore;
494
+ put(
495
+ name: string,
496
+ path: string | RegExp | (string | RegExp)[],
497
+ ...middlewares: (MiddlewareFunc | string)[]
498
+ ): EggCore;
499
+
456
500
  put(...args: any): EggCore {
457
501
  this.router.put.apply(this.router, args);
458
502
  return this;
459
503
  }
460
- patch(path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
461
- patch(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
504
+ patch(
505
+ path: string | RegExp | (string | RegExp)[],
506
+ ...middlewares: (MiddlewareFunc | string)[]
507
+ ): EggCore;
508
+ patch(
509
+ name: string,
510
+ path: string | RegExp | (string | RegExp)[],
511
+ ...middlewares: (MiddlewareFunc | string)[]
512
+ ): EggCore;
513
+
462
514
  patch(...args: any): EggCore {
463
515
  this.router.patch.apply(this.router, args);
464
516
  return this;
465
517
  }
466
- post(path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
467
- post(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
518
+ post(
519
+ path: string | RegExp | (string | RegExp)[],
520
+ ...middlewares: (MiddlewareFunc | string)[]
521
+ ): EggCore;
522
+ post(
523
+ name: string,
524
+ path: string | RegExp | (string | RegExp)[],
525
+ ...middlewares: (MiddlewareFunc | string)[]
526
+ ): EggCore;
527
+
468
528
  post(...args: any): EggCore {
469
529
  this.router.post.apply(this.router, args);
470
530
  return this;
471
531
  }
472
- delete(path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
473
- delete(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
532
+ delete(
533
+ path: string | RegExp | (string | RegExp)[],
534
+ ...middlewares: (MiddlewareFunc | string)[]
535
+ ): EggCore;
536
+ delete(
537
+ name: string,
538
+ path: string | RegExp | (string | RegExp)[],
539
+ ...middlewares: (MiddlewareFunc | string)[]
540
+ ): EggCore;
541
+
474
542
  delete(...args: any): EggCore {
475
543
  this.router.delete.apply(this.router, args);
476
544
  return this;
477
545
  }
478
- del(path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
479
- del(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
546
+ del(
547
+ path: string | RegExp | (string | RegExp)[],
548
+ ...middlewares: (MiddlewareFunc | string)[]
549
+ ): EggCore;
550
+ del(
551
+ name: string,
552
+ path: string | RegExp | (string | RegExp)[],
553
+ ...middlewares: (MiddlewareFunc | string)[]
554
+ ): EggCore;
555
+
480
556
  del(...args: any): EggCore {
481
557
  this.router.del.apply(this.router, args);
482
558
  return this;
483
559
  }
484
560
 
485
- all(path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
486
- all(name: string, path: string | RegExp | (string | RegExp)[], ...middlewares: (MiddlewareFunc | string)[]): EggCore;
561
+ all(
562
+ path: string | RegExp | (string | RegExp)[],
563
+ ...middlewares: (MiddlewareFunc | string)[]
564
+ ): EggCore;
565
+ all(
566
+ name: string,
567
+ path: string | RegExp | (string | RegExp)[],
568
+ ...middlewares: (MiddlewareFunc | string)[]
569
+ ): EggCore;
570
+
487
571
  all(...args: any): EggCore {
488
572
  this.router.all.apply(this.router, args);
489
573
  return this;
490
574
  }
491
575
 
492
576
  resources(prefix: string, controller: string | ResourcesController): EggCore;
493
- resources(prefix: string, middleware: MiddlewareFunc, controller: string | ResourcesController): EggCore;
494
- resources(name: string, prefix: string, controller: string | ResourcesController): EggCore;
495
- resources(name: string, prefix: string, middleware: MiddlewareFunc, controller: string | ResourcesController): EggCore;
577
+ resources(
578
+ prefix: string,
579
+ middleware: MiddlewareFunc,
580
+ controller: string | ResourcesController
581
+ ): EggCore;
582
+ resources(
583
+ name: string,
584
+ prefix: string,
585
+ controller: string | ResourcesController
586
+ ): EggCore;
587
+ resources(
588
+ name: string,
589
+ prefix: string,
590
+ middleware: MiddlewareFunc,
591
+ controller: string | ResourcesController
592
+ ): EggCore;
593
+
496
594
  resources(...args: any): EggCore {
497
595
  this.router.resources.apply(this.router, args);
498
596
  return this;
499
597
  }
500
598
 
501
- redirect(source: string, destination: string, status: number = 301) {
599
+ redirect(source: string, destination: string, status = 301) {
502
600
  this.router.redirect(source, destination, status);
503
601
  return this;
504
602
  }
505
603
 
506
- register(path: string | RegExp | (string | RegExp)[],
604
+ register(
605
+ path: string | RegExp | (string | RegExp)[],
507
606
  methods: string[],
508
607
  middleware: MiddlewareFunc | MiddlewareFunc[],
509
- opts?: RegisterOptions) {
608
+ opts?: RegisterOptions
609
+ ) {
510
610
  this.router.register(path, methods, middleware, opts);
511
611
  return this;
512
612
  }
package/src/lifecycle.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import assert from 'node:assert';
2
2
  import { EventEmitter } from 'node:events';
3
3
  import { debuglog, format } from 'node:util';
4
+
4
5
  import { isClass } from 'is-type-of';
5
- import { Ready as ReadyObject } from 'get-ready';
6
- import type { ReadyFunctionArg } from 'get-ready';
6
+ import { Ready as ReadyObject, type ReadyFunctionArg } from 'get-ready';
7
7
  import { Ready } from 'ready-callback';
8
8
  import { EggConsoleLogger } from 'egg-logger';
9
+
9
10
  import utils from './utils/index.js';
10
11
  import type { Fun } from './utils/index.js';
11
12
  import type { EggCore } from './egg.js';
@@ -54,7 +55,7 @@ export interface ILifecycleBoot {
54
55
  beforeClose?(): Promise<void>;
55
56
  }
56
57
 
57
- export type BootImplClass<T = ILifecycleBoot> = new(...args: any[]) => T;
58
+ export type BootImplClass<T = ILifecycleBoot> = new (...args: any[]) => T;
58
59
 
59
60
  export interface LifecycleOptions {
60
61
  baseDir: string;
@@ -89,20 +90,29 @@ export class Lifecycle extends EventEmitter {
89
90
 
90
91
  this.timing.start(`${this.options.app.type} Start`);
91
92
  // get app timeout from env or use default timeout 10 second
92
- const eggReadyTimeoutEnv = parseInt(process.env.EGG_READY_TIMEOUT_ENV || '10000');
93
+ const eggReadyTimeoutEnv = Number.parseInt(
94
+ process.env.EGG_READY_TIMEOUT_ENV || '10000'
95
+ );
93
96
  assert(
94
97
  Number.isInteger(eggReadyTimeoutEnv),
95
- `process.env.EGG_READY_TIMEOUT_ENV ${process.env.EGG_READY_TIMEOUT_ENV} should be able to parseInt.`);
98
+ `process.env.EGG_READY_TIMEOUT_ENV ${process.env.EGG_READY_TIMEOUT_ENV} should be able to parseInt.`
99
+ );
96
100
  this.readyTimeout = eggReadyTimeoutEnv;
97
101
 
98
102
  this.#initReady();
99
- this
100
- .on('ready_stat', data => {
101
- this.logger.info('[@eggjs/core/lifecycle:ready_stat] end ready task %s, remain %j', data.id, data.remain);
102
- })
103
- .on('ready_timeout', id => {
104
- this.logger.warn('[@eggjs/core/lifecycle:ready_timeout] %s seconds later %s was still unable to finish.', this.readyTimeout / 1000, id);
105
- });
103
+ this.on('ready_stat', data => {
104
+ this.logger.info(
105
+ '[@eggjs/core/lifecycle:ready_stat] end ready task %s, remain %j',
106
+ data.id,
107
+ data.remain
108
+ );
109
+ }).on('ready_timeout', id => {
110
+ this.logger.warn(
111
+ '[@eggjs/core/lifecycle:ready_timeout] %s seconds later %s was still unable to finish.',
112
+ this.readyTimeout / 1000,
113
+ id
114
+ );
115
+ });
106
116
 
107
117
  this.ready(err => {
108
118
  this.triggerDidReady(err);
@@ -136,10 +146,12 @@ export class Lifecycle extends EventEmitter {
136
146
  const timingKeyPrefix = 'readyCallback';
137
147
  const timing = this.timing;
138
148
  const cb = this.loadReady.readyCallback(name, opt);
139
- const timingKey = `${timingKeyPrefix} in ` + utils.getResolvedFilename(name, this.app.baseDir);
149
+ const timingKey =
150
+ `${timingKeyPrefix} in ` +
151
+ utils.getResolvedFilename(name, this.app.baseDir);
140
152
  this.timing.start(timingKey);
141
153
  debug('register legacyReadyCallback');
142
- return function legacyReadyCallback(...args: any[]) {
154
+ return function legacyReadyCallback(...args: unknown[]) {
143
155
  timing.end(timingKey);
144
156
  debug('end legacyReadyCallback');
145
157
  cb(...args);
@@ -147,12 +159,21 @@ export class Lifecycle extends EventEmitter {
147
159
  }
148
160
 
149
161
  addBootHook(bootHootOrBootClass: BootImplClass | ILifecycleBoot) {
150
- assert(this.#init === false, 'do not add hook when lifecycle has been initialized');
162
+ assert(
163
+ this.#init === false,
164
+ 'do not add hook when lifecycle has been initialized'
165
+ );
151
166
  this.#bootHooks.push(bootHootOrBootClass);
152
167
  }
153
168
 
154
- addFunctionAsBootHook<T = EggCore>(hook: (app: T) => void, fullPath?: string) {
155
- assert(this.#init === false, 'do not add hook when lifecycle has been initialized');
169
+ addFunctionAsBootHook<T = EggCore>(
170
+ hook: (app: T) => void,
171
+ fullPath?: string
172
+ ) {
173
+ assert(
174
+ this.#init === false,
175
+ 'do not add hook when lifecycle has been initialized'
176
+ );
156
177
  // app.js is exported as a function
157
178
  // call this function in configDidLoad
158
179
  class Boot implements ILifecycleBoot {
@@ -190,8 +211,7 @@ export class Lifecycle extends EventEmitter {
190
211
  }
191
212
 
192
213
  registerBeforeStart(scope: Fun, name: string) {
193
- debug('%s add registerBeforeStart, name: %o',
194
- this.options.app.type, name);
214
+ debug('%s add registerBeforeStart, name: %o', this.options.app.type, name);
195
215
  this.#registerReadyCallback({
196
216
  scope,
197
217
  ready: this.loadReady,
@@ -207,15 +227,22 @@ export class Lifecycle extends EventEmitter {
207
227
  fn.fullPath = fullPath;
208
228
  }
209
229
  this.#closeFunctionSet.add(fn);
210
- debug('%s register beforeClose at %o, count: %d',
211
- this.app.type, fullPath, this.#closeFunctionSet.size);
230
+ debug(
231
+ '%s register beforeClose at %o, count: %d',
232
+ this.app.type,
233
+ fullPath,
234
+ this.#closeFunctionSet.size
235
+ );
212
236
  }
213
237
 
214
238
  async close() {
215
239
  // close in reverse order: first created, last closed
216
240
  const closeFns = Array.from(this.#closeFunctionSet);
217
- debug('%s start trigger %d beforeClose functions',
218
- this.app.type, closeFns.length);
241
+ debug(
242
+ '%s start trigger %d beforeClose functions',
243
+ this.app.type,
244
+ closeFns.length
245
+ );
219
246
  for (const fn of closeFns.reverse()) {
220
247
  debug('%s trigger beforeClose at %o', this.app.type, fn.fullPath);
221
248
  await utils.callFn(fn);
@@ -301,7 +328,11 @@ export class Lifecycle extends EventEmitter {
301
328
  try {
302
329
  await boot.didReady(err);
303
330
  } catch (err) {
304
- debug('trigger didReady error at %o, error: %s', boot.fullPath, err);
331
+ debug(
332
+ 'trigger didReady error at %o, error: %s',
333
+ boot.fullPath,
334
+ err
335
+ );
305
336
  this.emit('error', err);
306
337
  }
307
338
  }
@@ -321,7 +352,11 @@ export class Lifecycle extends EventEmitter {
321
352
  try {
322
353
  await boot.serverDidReady();
323
354
  } catch (err) {
324
- debug('trigger serverDidReady error at %o, error: %s', boot.fullPath, err);
355
+ debug(
356
+ 'trigger serverDidReady error at %o, error: %s',
357
+ boot.fullPath,
358
+ err
359
+ );
325
360
  this.emit('error', err);
326
361
  }
327
362
  }
@@ -355,8 +390,8 @@ export class Lifecycle extends EventEmitter {
355
390
 
356
391
  #delegateReadyEvent(ready: Ready) {
357
392
  ready.once('error', (err?: Error) => ready.ready(err));
358
- ready.on('ready_timeout', (id: any) => this.emit('ready_timeout', id));
359
- ready.on('ready_stat', (data: any) => this.emit('ready_stat', data));
393
+ ready.on('ready_timeout', (id: unknown) => this.emit('ready_timeout', id));
394
+ ready.on('ready_stat', (data: unknown) => this.emit('ready_stat', data));
360
395
  ready.on('error', (err?: Error) => this.emit('error', err));
361
396
  }
362
397
 
@@ -368,12 +403,14 @@ export class Lifecycle extends EventEmitter {
368
403
  }) {
369
404
  const { scope, ready, timingKeyPrefix, scopeFullName } = args;
370
405
  if (typeof scope !== 'function') {
371
- throw new Error('boot only support function');
406
+ throw new TypeError('boot only support function');
372
407
  }
373
408
 
374
409
  // get filename from stack if scopeFullName is undefined
375
410
  const name = scopeFullName || utils.getCalleeFromStack(true, 4);
376
- const timingKey = `${timingKeyPrefix} in ` + utils.getResolvedFilename(name, this.app.baseDir);
411
+ const timingKey =
412
+ `${timingKeyPrefix} in ` +
413
+ utils.getResolvedFilename(name, this.app.baseDir);
377
414
 
378
415
  this.timing.start(timingKey);
379
416
 
@@ -381,19 +418,21 @@ export class Lifecycle extends EventEmitter {
381
418
  const done = ready.readyCallback(name);
382
419
 
383
420
  // ensure scope executes after load completed
384
- process.nextTick(() => {
385
- utils.callFn(scope).then(() => {
421
+ process.nextTick(async () => {
422
+ try {
423
+ await utils.callFn(scope);
386
424
  debug('[registerReadyCallback] end name: %o', name);
387
425
  done();
388
426
  this.timing.end(timingKey);
389
- }, (err: Error) => {
427
+ } catch (e) {
428
+ let err = e as Error;
390
429
  // avoid non-stringify error: TypeError: Cannot convert object to primitive value
391
430
  if (!(err instanceof Error)) {
392
431
  err = new Error(format('%s', err));
393
432
  }
394
433
  done(err);
395
434
  this.timing.end(timingKey);
396
- });
435
+ }
397
436
  });
398
437
  }
399
438
  }
@@ -38,7 +38,8 @@ export class ClassLoader {
38
38
  }
39
39
  }
40
40
 
41
- export interface ContextLoaderOptions extends Omit<FileLoaderOptions, 'target'> {
41
+ export interface ContextLoaderOptions
42
+ extends Omit<FileLoaderOptions, 'target'> {
42
43
  /** required inject */
43
44
  inject: Record<string, any>;
44
45
  /** property name defined to target */
@@ -71,14 +72,14 @@ export class ContextLoader extends FileLoader {
71
72
  ...options,
72
73
  target,
73
74
  });
74
- this.#inject = this.options.inject!;
75
+ this.#inject = this.options.inject as Record<string, any>;
75
76
 
76
77
  const app = this.#inject;
77
78
  const property = options.property;
78
79
  // define ctx.service
79
80
  Object.defineProperty(app.context, property, {
80
81
  get() {
81
- // eslint-disable-next-line @typescript-eslint/no-this-alias
82
+ // oxlint-disable-next-line unicorn/no-this-assignment, typescript/no-this-alias
82
83
  const ctx = this;
83
84
  // distinguish property cache,
84
85
  // cache's lifecycle is the same with this context instance
@@ -86,11 +87,12 @@ export class ContextLoader extends FileLoader {
86
87
  if (!ctx[CLASS_LOADER]) {
87
88
  ctx[CLASS_LOADER] = new Map();
88
89
  }
89
- const classLoader: Map<string | symbol, ClassLoader> = ctx[CLASS_LOADER];
90
+ const classLoader: Map<string | symbol, ClassLoader> =
91
+ ctx[CLASS_LOADER];
90
92
  let instance = classLoader.get(property);
91
93
  if (!instance) {
92
94
  instance = getInstance(target, ctx);
93
- classLoader.set(property, instance!);
95
+ classLoader.set(property, instance as ClassLoader);
94
96
  }
95
97
  return instance;
96
98
  },
@@ -110,8 +112,8 @@ function getInstance(values: any, ctx: Context) {
110
112
  // it's just an object
111
113
  instance = Class;
112
114
  }
113
- // Can't set property to primitive, so check again
114
- // e.x. module.exports = 1;
115
+ // Can't set property to primitive, so check again
116
+ // e.x. module.exports = 1;
115
117
  } else if (isPrimitive(values)) {
116
118
  instance = values;
117
119
  } else {