@eggjs/core 6.2.3 → 6.2.5

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/src/lifecycle.ts CHANGED
@@ -10,7 +10,7 @@ import utils from './utils/index.js';
10
10
  import type { Fun } from './utils/index.js';
11
11
  import type { EggCore } from './egg.js';
12
12
 
13
- const debug = debuglog('@eggjs/core:lifecycle');
13
+ const debug = debuglog('@eggjs/core/lifecycle');
14
14
 
15
15
  export interface ILifecycleBoot {
16
16
  // loader auto set 'fullPath' property on boot class
@@ -62,13 +62,15 @@ export interface LifecycleOptions {
62
62
  logger: EggConsoleLogger;
63
63
  }
64
64
 
65
+ export type FunWithFullPath = Fun & { fullPath?: string };
66
+
65
67
  export class Lifecycle extends EventEmitter {
66
68
  #init: boolean;
67
69
  #readyObject: ReadyObject;
68
70
  #bootHooks: (BootImplClass | ILifecycleBoot)[];
69
71
  #boots: ILifecycleBoot[];
70
72
  #isClosed: boolean;
71
- #closeFunctionSet: Set<Fun>;
73
+ #closeFunctionSet: Set<FunWithFullPath>;
72
74
  loadReady: Ready;
73
75
  bootReady: Ready;
74
76
  options: LifecycleOptions;
@@ -85,7 +87,7 @@ export class Lifecycle extends EventEmitter {
85
87
  this.#isClosed = false;
86
88
  this.#init = false;
87
89
 
88
- this.timing.start('Application Start');
90
+ this.timing.start(`${this.options.app.type} Start`);
89
91
  // get app timeout from env or use default timeout 10 second
90
92
  const eggReadyTimeoutEnv = parseInt(process.env.EGG_READY_TIMEOUT_ENV || '10000');
91
93
  assert(
@@ -96,16 +98,16 @@ export class Lifecycle extends EventEmitter {
96
98
  this.#initReady();
97
99
  this
98
100
  .on('ready_stat', data => {
99
- this.logger.info('[egg:core:ready_stat] end ready task %s, remain %j', data.id, data.remain);
101
+ this.logger.info('[@eggjs/core/lifecycle:ready_stat] end ready task %s, remain %j', data.id, data.remain);
100
102
  })
101
103
  .on('ready_timeout', id => {
102
- this.logger.warn('[egg:core:ready_timeout] %s seconds later %s was still unable to finish.', this.readyTimeout / 1000, id);
104
+ this.logger.warn('[@eggjs/core/lifecycle:ready_timeout] %s seconds later %s was still unable to finish.', this.readyTimeout / 1000, id);
103
105
  });
104
106
 
105
107
  this.ready(err => {
106
108
  this.triggerDidReady(err);
107
109
  debug('app ready');
108
- this.timing.end('Application Start');
110
+ this.timing.end(`${this.options.app.type} Start`);
109
111
  });
110
112
  }
111
113
 
@@ -149,11 +151,12 @@ export class Lifecycle extends EventEmitter {
149
151
  this.#bootHooks.push(bootHootOrBootClass);
150
152
  }
151
153
 
152
- addFunctionAsBootHook<T = EggCore>(hook: (app: T) => void) {
154
+ addFunctionAsBootHook<T = EggCore>(hook: (app: T) => void, fullPath?: string) {
153
155
  assert(this.#init === false, 'do not add hook when lifecycle has been initialized');
154
156
  // app.js is exported as a function
155
157
  // call this function in configDidLoad
156
- this.#bootHooks.push(class Boot implements ILifecycleBoot {
158
+ class Boot implements ILifecycleBoot {
159
+ static fullPath?: string;
157
160
  app: T;
158
161
  constructor(app: T) {
159
162
  this.app = app;
@@ -161,25 +164,34 @@ export class Lifecycle extends EventEmitter {
161
164
  configDidLoad() {
162
165
  hook(this.app);
163
166
  }
164
- });
167
+ }
168
+ Boot.fullPath = fullPath;
169
+ this.#bootHooks.push(Boot);
165
170
  }
166
171
 
167
172
  /**
168
173
  * init boots and trigger config did config
169
174
  */
170
175
  init() {
176
+ debug('%s init lifecycle', this.app.type);
171
177
  assert(this.#init === false, 'lifecycle have been init');
172
178
  this.#init = true;
173
179
  this.#boots = this.#bootHooks.map(BootHootOrBootClass => {
180
+ let instance = BootHootOrBootClass as ILifecycleBoot;
174
181
  if (isClass(BootHootOrBootClass)) {
175
- return new BootHootOrBootClass(this.app);
182
+ instance = new BootHootOrBootClass(this.app);
183
+ if (!instance.fullPath && 'fullPath' in BootHootOrBootClass) {
184
+ instance.fullPath = BootHootOrBootClass.fullPath as string;
185
+ }
176
186
  }
177
- return BootHootOrBootClass;
187
+ debug('[init] add boot instance: %o', instance.fullPath);
188
+ return instance;
178
189
  });
179
190
  }
180
191
 
181
192
  registerBeforeStart(scope: Fun, name: string) {
182
- debug('add registerBeforeStart, name: %o', name);
193
+ debug('%s add registerBeforeStart, name: %o',
194
+ this.options.app.type, name);
183
195
  this.#registerReadyCallback({
184
196
  scope,
185
197
  ready: this.loadReady,
@@ -188,16 +200,24 @@ export class Lifecycle extends EventEmitter {
188
200
  });
189
201
  }
190
202
 
191
- registerBeforeClose(fn: Fun) {
203
+ registerBeforeClose(fn: FunWithFullPath, fullPath?: string) {
192
204
  assert(typeof fn === 'function', 'argument should be function');
193
205
  assert(this.#isClosed === false, 'app has been closed');
206
+ if (fullPath) {
207
+ fn.fullPath = fullPath;
208
+ }
194
209
  this.#closeFunctionSet.add(fn);
210
+ debug('%s register beforeClose at %o, count: %d',
211
+ this.app.type, fullPath, this.#closeFunctionSet.size);
195
212
  }
196
213
 
197
214
  async close() {
198
215
  // close in reverse order: first created, last closed
199
216
  const closeFns = Array.from(this.#closeFunctionSet);
217
+ debug('%s start trigger %d beforeClose functions',
218
+ this.app.type, closeFns.length);
200
219
  for (const fn of closeFns.reverse()) {
220
+ debug('%s trigger beforeClose at %o', this.app.type, fn.fullPath);
201
221
  await utils.callFn(fn);
202
222
  this.#closeFunctionSet.delete(fn);
203
223
  }
@@ -206,12 +226,14 @@ export class Lifecycle extends EventEmitter {
206
226
  this.removeAllListeners();
207
227
  this.app.removeAllListeners();
208
228
  this.#isClosed = true;
229
+ debug('%s closed', this.app.type);
209
230
  }
210
231
 
211
232
  triggerConfigWillLoad() {
212
233
  debug('trigger configWillLoad start');
213
234
  for (const boot of this.#boots) {
214
235
  if (typeof boot.configWillLoad === 'function') {
236
+ debug('trigger configWillLoad at %o', boot.fullPath);
215
237
  boot.configWillLoad();
216
238
  }
217
239
  }
@@ -223,12 +245,13 @@ export class Lifecycle extends EventEmitter {
223
245
  debug('trigger configDidLoad start');
224
246
  for (const boot of this.#boots) {
225
247
  if (typeof boot.configDidLoad === 'function') {
248
+ debug('trigger configDidLoad at %o', boot.fullPath);
226
249
  boot.configDidLoad();
227
250
  }
228
251
  // function boot hook register after configDidLoad trigger
229
252
  if (typeof boot.beforeClose === 'function') {
230
253
  const beforeClose = boot.beforeClose.bind(boot);
231
- this.registerBeforeClose(beforeClose);
254
+ this.registerBeforeClose(beforeClose, boot.fullPath);
232
255
  }
233
256
  }
234
257
  debug('trigger configDidLoad end');
@@ -274,10 +297,12 @@ export class Lifecycle extends EventEmitter {
274
297
  return (async () => {
275
298
  for (const boot of this.#boots) {
276
299
  if (typeof boot.didReady === 'function') {
300
+ debug('trigger didReady at %o', boot.fullPath);
277
301
  try {
278
302
  await boot.didReady(err);
279
- } catch (e) {
280
- this.emit('error', e);
303
+ } catch (err) {
304
+ debug('trigger didReady error at %o, error: %s', boot.fullPath, err);
305
+ this.emit('error', err);
281
306
  }
282
307
  }
283
308
  }
@@ -292,9 +317,11 @@ export class Lifecycle extends EventEmitter {
292
317
  if (typeof boot.serverDidReady !== 'function') {
293
318
  continue;
294
319
  }
320
+ debug('trigger serverDidReady at %o', boot.fullPath);
295
321
  try {
296
322
  await boot.serverDidReady();
297
323
  } catch (err) {
324
+ debug('trigger serverDidReady error at %o, error: %s', boot.fullPath, err);
298
325
  this.emit('error', err);
299
326
  }
300
327
  }
@@ -781,7 +781,7 @@ export class EggLoader {
781
781
  const pluginPkgFile = utils.resolvePath(`${name}/package.json`, { paths: [ ...this.lookupDirs ] });
782
782
  return path.dirname(pluginPkgFile);
783
783
  } catch (err) {
784
- debug('[resolvePluginPath] error: %o', err);
784
+ debug('[resolvePluginPath] error: %o, plugin info: %o', err, plugin);
785
785
  throw new Error(`Can not find plugin ${name} in "${[ ...this.lookupDirs ].join(', ')}"`, {
786
786
  cause: err,
787
787
  });
@@ -1166,8 +1166,10 @@ export class EggLoader {
1166
1166
  async #loadBootHook(fileName: string) {
1167
1167
  this.timing.start(`Load ${fileName}.js`);
1168
1168
  for (const unit of this.getLoadUnits()) {
1169
- const bootFilePath = this.resolveModule(path.join(unit.path, fileName));
1169
+ const bootFile = path.join(unit.path, fileName);
1170
+ const bootFilePath = this.resolveModule(bootFile);
1170
1171
  if (!bootFilePath) {
1172
+ // debug('[loadBootHook] %o not found', bootFile);
1171
1173
  continue;
1172
1174
  }
1173
1175
  const bootHook = await this.requireFile(bootFilePath);
@@ -1175,10 +1177,12 @@ export class EggLoader {
1175
1177
  bootHook.prototype.fullPath = bootFilePath;
1176
1178
  // if is boot class, add to lifecycle
1177
1179
  this.lifecycle.addBootHook(bootHook);
1180
+ debug('[loadBootHook] add BootHookClass from %o', bootFilePath);
1178
1181
  } else if (typeof bootHook === 'function') {
1179
1182
  // if is boot function, wrap to class
1180
1183
  // for compatibility
1181
- this.lifecycle.addFunctionAsBootHook(bootHook);
1184
+ this.lifecycle.addFunctionAsBootHook(bootHook, bootFilePath);
1185
+ debug('[loadBootHook] add bootHookFunction from %o', bootFilePath);
1182
1186
  } else {
1183
1187
  this.options.logger.warn('[@eggjs/core:egg_loader] %s must exports a boot class', bootFilePath);
1184
1188
  }
@@ -1595,13 +1599,13 @@ export class EggLoader {
1595
1599
  let fullPath;
1596
1600
  try {
1597
1601
  fullPath = utils.resolvePath(filepath);
1598
- } catch (e) {
1599
- return undefined;
1600
- }
1601
-
1602
- if (process.env.EGG_TYPESCRIPT !== 'true' && fullPath.endsWith('.ts')) {
1602
+ } catch (err: any) {
1603
+ // debug('[resolveModule] Module %o resolve error: %s', filepath, err.stack);
1603
1604
  return undefined;
1604
1605
  }
1606
+ // if (process.env.EGG_TYPESCRIPT !== 'true' && fullPath.endsWith('.ts')) {
1607
+ // return undefined;
1608
+ // }
1605
1609
  return fullPath;
1606
1610
  }
1607
1611
  }