@eggjs/core 6.3.0-beta.0 → 6.3.0-beta.1

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/package.json CHANGED
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "name": "@eggjs/core",
3
- "version": "6.3.0-beta.0"
3
+ "version": "6.3.0-beta.1"
4
4
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eggjs/core",
3
- "version": "6.3.0-beta.0",
3
+ "version": "6.3.0-beta.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -12,13 +12,14 @@
12
12
  },
13
13
  "description": "A core plugin framework based on @eggjs/koa",
14
14
  "scripts": {
15
+ "clean": "rimraf dist",
15
16
  "lint": "eslint src test --ext ts",
16
- "pretest": "npm run lint -- --fix && npm run prepublishOnly",
17
+ "pretest": "npm run clean && npm run lint -- --fix && npm run prepublishOnly",
17
18
  "test": "npm run test-local",
18
19
  "test-local": "egg-bin test",
19
- "preci": "npm run lint && npm run prepublishOnly && attw --pack",
20
+ "preci": "npm run clean && npm run lint && npm run prepublishOnly",
20
21
  "ci": "egg-bin cov",
21
- "prepublishOnly": "tshy && tshy-after"
22
+ "prepublishOnly": "tshy && tshy-after && attw --pack"
22
23
  },
23
24
  "repository": {
24
25
  "type": "git",
@@ -37,7 +38,7 @@
37
38
  "dependencies": {
38
39
  "@eggjs/koa": "^2.20.2",
39
40
  "@eggjs/router": "^3.0.5",
40
- "@eggjs/utils": "^4.0.2",
41
+ "@eggjs/utils": "^4.1.5",
41
42
  "egg-logger": "^3.5.0",
42
43
  "egg-path-matching": "^2.0.0",
43
44
  "extend2": "^4.0.0",
@@ -52,6 +53,7 @@
52
53
  },
53
54
  "devDependencies": {
54
55
  "@arethetypeswrong/cli": "^0.17.1",
56
+ "@eggjs/bin": "^7.0.0",
55
57
  "@eggjs/tsconfig": "1",
56
58
  "@types/js-yaml": "4",
57
59
  "@types/mocha": "10",
@@ -59,12 +61,13 @@
59
61
  "@types/supertest": "6",
60
62
  "await-event": "2",
61
63
  "coffee": "5",
62
- "@eggjs/bin": "beta",
63
64
  "eslint": "8",
64
65
  "eslint-config-egg": "14",
65
66
  "gals": "1",
66
67
  "js-yaml": "3",
67
68
  "mm": "3",
69
+ "pedding": "^2.0.0",
70
+ "rimraf": "6",
68
71
  "supertest": "7",
69
72
  "ts-node": "10",
70
73
  "tshy": "3",
package/src/egg.ts CHANGED
@@ -328,9 +328,9 @@ export class EggCore extends KoaApplication {
328
328
  *
329
329
  * @param {Function} fn - the function that can be generator function or async function.
330
330
  */
331
- beforeClose(fn: Fun) {
331
+ beforeClose(fn: Fun, name?: string) {
332
332
  this.deprecate('`beforeClose` was deprecated, please use "Life Cycles" instead, see https://www.eggjs.org/advanced/loader#life-cycles');
333
- this.lifecycle.registerBeforeClose(fn);
333
+ this.lifecycle.registerBeforeClose(fn, name);
334
334
  }
335
335
 
336
336
  /**
package/src/lifecycle.ts CHANGED
@@ -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;
@@ -96,10 +98,10 @@ 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 => {
@@ -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,17 +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);
200
- debug('close %d beforeClose functions', closeFns.length);
217
+ debug('%s start trigger %d beforeClose functions',
218
+ this.app.type, closeFns.length);
201
219
  for (const fn of closeFns.reverse()) {
220
+ debug('%s trigger beforeClose at %o', this.app.type, fn.fullPath);
202
221
  await utils.callFn(fn);
203
222
  this.#closeFunctionSet.delete(fn);
204
223
  }
@@ -207,13 +226,14 @@ export class Lifecycle extends EventEmitter {
207
226
  this.removeAllListeners();
208
227
  this.app.removeAllListeners();
209
228
  this.#isClosed = true;
210
- debug('%s closed', this.options.app.type);
229
+ debug('%s closed', this.app.type);
211
230
  }
212
231
 
213
232
  triggerConfigWillLoad() {
214
233
  debug('trigger configWillLoad start');
215
234
  for (const boot of this.#boots) {
216
235
  if (typeof boot.configWillLoad === 'function') {
236
+ debug('trigger configWillLoad at %o', boot.fullPath);
217
237
  boot.configWillLoad();
218
238
  }
219
239
  }
@@ -225,12 +245,13 @@ export class Lifecycle extends EventEmitter {
225
245
  debug('trigger configDidLoad start');
226
246
  for (const boot of this.#boots) {
227
247
  if (typeof boot.configDidLoad === 'function') {
248
+ debug('trigger configDidLoad at %o', boot.fullPath);
228
249
  boot.configDidLoad();
229
250
  }
230
251
  // function boot hook register after configDidLoad trigger
231
252
  if (typeof boot.beforeClose === 'function') {
232
253
  const beforeClose = boot.beforeClose.bind(boot);
233
- this.registerBeforeClose(beforeClose);
254
+ this.registerBeforeClose(beforeClose, boot.fullPath);
234
255
  }
235
256
  }
236
257
  debug('trigger configDidLoad end');
@@ -276,10 +297,12 @@ export class Lifecycle extends EventEmitter {
276
297
  return (async () => {
277
298
  for (const boot of this.#boots) {
278
299
  if (typeof boot.didReady === 'function') {
300
+ debug('trigger didReady at %o', boot.fullPath);
279
301
  try {
280
302
  await boot.didReady(err);
281
- } catch (e) {
282
- this.emit('error', e);
303
+ } catch (err) {
304
+ debug('trigger didReady error at %o, error: %s', boot.fullPath, err);
305
+ this.emit('error', err);
283
306
  }
284
307
  }
285
308
  }
@@ -294,9 +317,11 @@ export class Lifecycle extends EventEmitter {
294
317
  if (typeof boot.serverDidReady !== 'function') {
295
318
  continue;
296
319
  }
320
+ debug('trigger serverDidReady at %o', boot.fullPath);
297
321
  try {
298
322
  await boot.serverDidReady();
299
323
  } catch (err) {
324
+ debug('trigger serverDidReady error at %o, error: %s', boot.fullPath, err);
300
325
  this.emit('error', err);
301
326
  }
302
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
  }