@eggjs/core 6.0.0-beta.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 (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +296 -0
  3. package/dist/commonjs/base_context_class.d.ts +16 -0
  4. package/dist/commonjs/base_context_class.js +41 -0
  5. package/dist/commonjs/egg.d.ts +204 -0
  6. package/dist/commonjs/egg.js +346 -0
  7. package/dist/commonjs/index.d.ts +5 -0
  8. package/dist/commonjs/index.js +26 -0
  9. package/dist/commonjs/lifecycle.d.ts +75 -0
  10. package/dist/commonjs/lifecycle.js +306 -0
  11. package/dist/commonjs/loader/context_loader.d.ts +24 -0
  12. package/dist/commonjs/loader/context_loader.js +109 -0
  13. package/dist/commonjs/loader/egg_loader.d.ts +405 -0
  14. package/dist/commonjs/loader/egg_loader.js +1497 -0
  15. package/dist/commonjs/loader/file_loader.d.ts +96 -0
  16. package/dist/commonjs/loader/file_loader.js +248 -0
  17. package/dist/commonjs/package.json +3 -0
  18. package/dist/commonjs/types.d.ts +1 -0
  19. package/dist/commonjs/types.js +403 -0
  20. package/dist/commonjs/utils/index.d.ts +14 -0
  21. package/dist/commonjs/utils/index.js +146 -0
  22. package/dist/commonjs/utils/sequencify.d.ts +13 -0
  23. package/dist/commonjs/utils/sequencify.js +59 -0
  24. package/dist/commonjs/utils/timing.d.ts +22 -0
  25. package/dist/commonjs/utils/timing.js +100 -0
  26. package/dist/esm/base_context_class.d.ts +16 -0
  27. package/dist/esm/base_context_class.js +37 -0
  28. package/dist/esm/egg.d.ts +204 -0
  29. package/dist/esm/egg.js +339 -0
  30. package/dist/esm/index.d.ts +5 -0
  31. package/dist/esm/index.js +6 -0
  32. package/dist/esm/lifecycle.d.ts +75 -0
  33. package/dist/esm/lifecycle.js +276 -0
  34. package/dist/esm/loader/context_loader.d.ts +24 -0
  35. package/dist/esm/loader/context_loader.js +102 -0
  36. package/dist/esm/loader/egg_loader.d.ts +405 -0
  37. package/dist/esm/loader/egg_loader.js +1490 -0
  38. package/dist/esm/loader/file_loader.d.ts +96 -0
  39. package/dist/esm/loader/file_loader.js +241 -0
  40. package/dist/esm/package.json +3 -0
  41. package/dist/esm/types.d.ts +1 -0
  42. package/dist/esm/types.js +402 -0
  43. package/dist/esm/utils/index.d.ts +14 -0
  44. package/dist/esm/utils/index.js +141 -0
  45. package/dist/esm/utils/sequencify.d.ts +13 -0
  46. package/dist/esm/utils/sequencify.js +56 -0
  47. package/dist/esm/utils/timing.d.ts +22 -0
  48. package/dist/esm/utils/timing.js +93 -0
  49. package/package.json +103 -0
  50. package/src/base_context_class.ts +39 -0
  51. package/src/egg.ts +430 -0
  52. package/src/index.ts +6 -0
  53. package/src/lifecycle.ts +363 -0
  54. package/src/loader/context_loader.ts +121 -0
  55. package/src/loader/egg_loader.ts +1703 -0
  56. package/src/loader/file_loader.ts +295 -0
  57. package/src/types.ts +447 -0
  58. package/src/utils/index.ts +154 -0
  59. package/src/utils/sequencify.ts +70 -0
  60. package/src/utils/timing.ts +114 -0
@@ -0,0 +1,1490 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import assert from 'node:assert';
4
+ import { debuglog, inspect } from 'node:util';
5
+ import { isAsyncFunction, isClass, isGeneratorFunction, isObject } from 'is-type-of';
6
+ import homedir from 'node-homedir';
7
+ import { getParamNames, readJSONSync } from 'utility';
8
+ import { extend } from 'extend2';
9
+ import { Request, Response, Context, Application } from '@eggjs/koa';
10
+ import { pathMatching } from 'egg-path-matching';
11
+ import { now, diff } from 'performance-ms';
12
+ import { FULLPATH, FileLoader } from './file_loader.js';
13
+ import { ContextLoader } from './context_loader.js';
14
+ import utils from '../utils/index.js';
15
+ import sequencify from '../utils/sequencify.js';
16
+ import { Timing } from '../utils/timing.js';
17
+ const debug = debuglog('@eggjs/core:egg_loader');
18
+ const originalPrototypes = {
19
+ request: Request.prototype,
20
+ response: Response.prototype,
21
+ context: Context.prototype,
22
+ application: Application.prototype,
23
+ };
24
+ export class EggLoader {
25
+ #requiredCount = 0;
26
+ options;
27
+ timing;
28
+ pkg;
29
+ eggPaths;
30
+ serverEnv;
31
+ serverScope;
32
+ appInfo;
33
+ dirs;
34
+ /**
35
+ * @class
36
+ * @param {Object} options - options
37
+ * @param {String} options.baseDir - the directory of application
38
+ * @param {EggCore} options.app - Application instance
39
+ * @param {Logger} options.logger - logger
40
+ * @param {Object} [options.plugins] - custom plugins
41
+ * @since 1.0.0
42
+ */
43
+ constructor(options) {
44
+ this.options = options;
45
+ assert(fs.existsSync(this.options.baseDir), `${this.options.baseDir} not exists`);
46
+ assert(this.options.app, 'options.app is required');
47
+ assert(this.options.logger, 'options.logger is required');
48
+ this.timing = this.app.timing || new Timing();
49
+ /**
50
+ * @member {Object} EggLoader#pkg
51
+ * @see {@link AppInfo#pkg}
52
+ * @since 1.0.0
53
+ */
54
+ this.pkg = readJSONSync(path.join(this.options.baseDir, 'package.json'));
55
+ // auto require('tsconfig-paths/register') on typescript app
56
+ // support env.EGG_TYPESCRIPT = true or { "egg": { "typescript": true } } on package.json
57
+ if (process.env.EGG_TYPESCRIPT === 'true' || (this.pkg.egg && this.pkg.egg.typescript)) {
58
+ // skip require tsconfig-paths if tsconfig.json not exists
59
+ const tsConfigFile = path.join(this.options.baseDir, 'tsconfig.json');
60
+ // FIXME: support esm
61
+ if (fs.existsSync(tsConfigFile) && typeof require === 'function') {
62
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
63
+ require('tsconfig-paths').register({ cwd: this.options.baseDir });
64
+ }
65
+ else {
66
+ this.logger.info('[@eggjs/core:egg_loader] skip register "tsconfig-paths" because tsconfig.json not exists at %s', tsConfigFile);
67
+ }
68
+ }
69
+ /**
70
+ * All framework directories.
71
+ *
72
+ * You can extend Application of egg, the entry point is options.app,
73
+ *
74
+ * loader will find all directories from the prototype of Application,
75
+ * you should define `Symbol.for('egg#eggPath')` property.
76
+ *
77
+ * ```
78
+ * // lib/example.js
79
+ * const egg = require('egg');
80
+ * class ExampleApplication extends egg.Application {
81
+ * constructor(options) {
82
+ * super(options);
83
+ * }
84
+ *
85
+ * get [Symbol.for('egg#eggPath')]() {
86
+ * return path.join(__dirname, '..');
87
+ * }
88
+ * }
89
+ * ```
90
+ * @member {Array} EggLoader#eggPaths
91
+ * @see EggLoader#getEggPaths
92
+ * @since 1.0.0
93
+ */
94
+ this.eggPaths = this.getEggPaths();
95
+ debug('Loaded eggPaths %j', this.eggPaths);
96
+ /**
97
+ * @member {String} EggLoader#serverEnv
98
+ * @see AppInfo#env
99
+ * @since 1.0.0
100
+ */
101
+ this.serverEnv = this.getServerEnv();
102
+ debug('Loaded serverEnv %j', this.serverEnv);
103
+ /**
104
+ * @member {String} EggLoader#serverScope
105
+ * @see AppInfo#serverScope
106
+ */
107
+ this.serverScope = options.serverScope !== undefined
108
+ ? options.serverScope
109
+ : this.getServerScope();
110
+ /**
111
+ * @member {AppInfo} EggLoader#appInfo
112
+ * @since 1.0.0
113
+ */
114
+ this.appInfo = this.getAppInfo();
115
+ }
116
+ get app() {
117
+ return this.options.app;
118
+ }
119
+ get lifecycle() {
120
+ return this.app.lifecycle;
121
+ }
122
+ get logger() {
123
+ return this.options.logger;
124
+ }
125
+ /**
126
+ * Get {@link AppInfo#env}
127
+ * @return {String} env
128
+ * @see AppInfo#env
129
+ * @private
130
+ * @since 1.0.0
131
+ */
132
+ getServerEnv() {
133
+ let serverEnv = this.options.env;
134
+ const envPath = path.join(this.options.baseDir, 'config/env');
135
+ if (!serverEnv && fs.existsSync(envPath)) {
136
+ serverEnv = fs.readFileSync(envPath, 'utf8').trim();
137
+ }
138
+ if (!serverEnv && process.env.EGG_SERVER_ENV) {
139
+ serverEnv = process.env.EGG_SERVER_ENV;
140
+ }
141
+ if (!serverEnv) {
142
+ if (process.env.NODE_ENV === 'test') {
143
+ serverEnv = 'unittest';
144
+ }
145
+ else if (process.env.NODE_ENV === 'production') {
146
+ serverEnv = 'prod';
147
+ }
148
+ else {
149
+ serverEnv = 'local';
150
+ }
151
+ }
152
+ else {
153
+ serverEnv = serverEnv.trim();
154
+ }
155
+ return serverEnv;
156
+ }
157
+ /**
158
+ * Get {@link AppInfo#scope}
159
+ * @return {String} serverScope
160
+ * @private
161
+ */
162
+ getServerScope() {
163
+ return process.env.EGG_SERVER_SCOPE || '';
164
+ }
165
+ /**
166
+ * Get {@link AppInfo#name}
167
+ * @return {String} appname
168
+ * @private
169
+ * @since 1.0.0
170
+ */
171
+ getAppname() {
172
+ if (this.pkg.name) {
173
+ debug('Loaded appname(%s) from package.json', this.pkg.name);
174
+ return this.pkg.name;
175
+ }
176
+ const pkg = path.join(this.options.baseDir, 'package.json');
177
+ throw new Error(`name is required from ${pkg}`);
178
+ }
179
+ /**
180
+ * Get home directory
181
+ * @return {String} home directory
182
+ * @since 3.4.0
183
+ */
184
+ getHomedir() {
185
+ // EGG_HOME for test
186
+ return process.env.EGG_HOME || homedir() || '/home/admin';
187
+ }
188
+ /**
189
+ * Get app info
190
+ * @return {AppInfo} appInfo
191
+ * @since 1.0.0
192
+ */
193
+ getAppInfo() {
194
+ const env = this.serverEnv;
195
+ const scope = this.serverScope;
196
+ const home = this.getHomedir();
197
+ const baseDir = this.options.baseDir;
198
+ /**
199
+ * Meta information of the application
200
+ * @class AppInfo
201
+ */
202
+ return {
203
+ /**
204
+ * The name of the application, retrieve from the name property in `package.json`.
205
+ * @member {String} AppInfo#name
206
+ */
207
+ name: this.getAppname(),
208
+ /**
209
+ * The current directory, where the application code is.
210
+ * @member {String} AppInfo#baseDir
211
+ */
212
+ baseDir,
213
+ /**
214
+ * The environment of the application, **it's not NODE_ENV**
215
+ *
216
+ * 1. from `$baseDir/config/env`
217
+ * 2. from EGG_SERVER_ENV
218
+ * 3. from NODE_ENV
219
+ *
220
+ * env | description
221
+ * --- | ---
222
+ * test | system integration testing
223
+ * prod | production
224
+ * local | local on your own computer
225
+ * unittest | unit test
226
+ *
227
+ * @member {String} AppInfo#env
228
+ * @see https://eggjs.org/zh-cn/basics/env.html
229
+ */
230
+ env,
231
+ /**
232
+ * @member {String} AppInfo#scope
233
+ */
234
+ scope,
235
+ /**
236
+ * The use directory, same as `process.env.HOME`
237
+ * @member {String} AppInfo#HOME
238
+ */
239
+ HOME: home,
240
+ /**
241
+ * parsed from `package.json`
242
+ * @member {Object} AppInfo#pkg
243
+ */
244
+ pkg: this.pkg,
245
+ /**
246
+ * The directory whether is baseDir or HOME depend on env.
247
+ * it's good for test when you want to write some file to HOME,
248
+ * but don't want to write to the real directory,
249
+ * so use root to write file to baseDir instead of HOME when unittest.
250
+ * keep root directory in baseDir when local and unittest
251
+ * @member {String} AppInfo#root
252
+ */
253
+ root: env === 'local' || env === 'unittest' ? baseDir : home,
254
+ };
255
+ }
256
+ /**
257
+ * Get {@link EggLoader#eggPaths}
258
+ * @return {Array} framework directories
259
+ * @see {@link EggLoader#eggPaths}
260
+ * @private
261
+ * @since 1.0.0
262
+ */
263
+ getEggPaths() {
264
+ // avoid require recursively
265
+ const EggCore = this.options.EggCoreClass;
266
+ const eggPaths = [];
267
+ let proto = this.app;
268
+ // Loop for the prototype chain
269
+ while (proto) {
270
+ proto = Object.getPrototypeOf(proto);
271
+ // stop the loop if
272
+ // - object extends Object
273
+ // - object extends EggCore
274
+ if (proto === Object.prototype || proto === EggCore.prototype) {
275
+ break;
276
+ }
277
+ assert(proto.hasOwnProperty(Symbol.for('egg#eggPath')), 'Symbol.for(\'egg#eggPath\') is required on Application');
278
+ const eggPath = Reflect.get(proto, Symbol.for('egg#eggPath'));
279
+ assert(eggPath && typeof eggPath === 'string', 'Symbol.for(\'egg#eggPath\') should be string');
280
+ assert(fs.existsSync(eggPath), `${eggPath} not exists`);
281
+ const realpath = fs.realpathSync(eggPath);
282
+ if (!eggPaths.includes(realpath)) {
283
+ eggPaths.unshift(realpath);
284
+ }
285
+ }
286
+ return eggPaths;
287
+ }
288
+ /** start Plugin loader */
289
+ lookupDirs;
290
+ eggPlugins;
291
+ appPlugins;
292
+ customPlugins;
293
+ allPlugins;
294
+ orderPlugins;
295
+ /** enable plugins */
296
+ plugins;
297
+ /**
298
+ * Load config/plugin.js from {EggLoader#loadUnits}
299
+ *
300
+ * plugin.js is written below
301
+ *
302
+ * ```js
303
+ * {
304
+ * 'xxx-client': {
305
+ * enable: true,
306
+ * package: 'xxx-client',
307
+ * dep: [],
308
+ * env: [],
309
+ * },
310
+ * // short hand
311
+ * 'rds': false,
312
+ * 'depd': {
313
+ * enable: true,
314
+ * path: 'path/to/depd'
315
+ * }
316
+ * }
317
+ * ```
318
+ *
319
+ * If the plugin has path, Loader will find the module from it.
320
+ *
321
+ * Otherwise Loader will lookup follow the order by packageName
322
+ *
323
+ * 1. $APP_BASE/node_modules/${package}
324
+ * 2. $EGG_BASE/node_modules/${package}
325
+ *
326
+ * You can call `loader.plugins` that retrieve enabled plugins.
327
+ *
328
+ * ```js
329
+ * loader.plugins['xxx-client'] = {
330
+ * name: 'xxx-client', // the plugin name, it can be used in `dep`
331
+ * package: 'xxx-client', // the package name of plugin
332
+ * enable: true, // whether enabled
333
+ * path: 'path/to/xxx-client', // the directory of the plugin package
334
+ * dep: [], // the dependent plugins, you can use the plugin name
335
+ * env: [ 'local', 'unittest' ], // specify the serverEnv that only enable the plugin in it
336
+ * }
337
+ * ```
338
+ *
339
+ * `loader.allPlugins` can be used when retrieve all plugins.
340
+ * @function EggLoader#loadPlugin
341
+ * @since 1.0.0
342
+ */
343
+ async loadPlugin() {
344
+ this.timing.start('Load Plugin');
345
+ this.lookupDirs = this.getLookupDirs();
346
+ this.allPlugins = {};
347
+ this.eggPlugins = await this.loadEggPlugins();
348
+ this.appPlugins = await this.loadAppPlugins();
349
+ this.customPlugins = this.loadCustomPlugins();
350
+ this.#extendPlugins(this.allPlugins, this.eggPlugins);
351
+ this.#extendPlugins(this.allPlugins, this.appPlugins);
352
+ this.#extendPlugins(this.allPlugins, this.customPlugins);
353
+ const enabledPluginNames = []; // enabled plugins that configured explicitly
354
+ const plugins = {};
355
+ const env = this.serverEnv;
356
+ for (const name in this.allPlugins) {
357
+ const plugin = this.allPlugins[name];
358
+ // resolve the real plugin.path based on plugin or package
359
+ plugin.path = this.getPluginPath(plugin);
360
+ // read plugin information from ${plugin.path}/package.json
361
+ this.#mergePluginConfig(plugin);
362
+ // disable the plugin that not match the serverEnv
363
+ if (env && plugin.env.length > 0 && !plugin.env.includes(env)) {
364
+ this.logger.info('[@eggjs/core] Plugin %o is disabled by env unmatched, require env(%o) but got env is %o', name, plugin.env, env);
365
+ plugin.enable = false;
366
+ continue;
367
+ }
368
+ plugins[name] = plugin;
369
+ if (plugin.enable) {
370
+ enabledPluginNames.push(name);
371
+ }
372
+ }
373
+ // retrieve the ordered plugins
374
+ this.orderPlugins = this.getOrderPlugins(plugins, enabledPluginNames, this.appPlugins);
375
+ const enablePlugins = {};
376
+ for (const plugin of this.orderPlugins) {
377
+ enablePlugins[plugin.name] = plugin;
378
+ }
379
+ debug('Loaded enable plugins: %j', Object.keys(enablePlugins));
380
+ /**
381
+ * Retrieve enabled plugins
382
+ * @member {Object} EggLoader#plugins
383
+ * @since 1.0.0
384
+ */
385
+ this.plugins = enablePlugins;
386
+ this.timing.end('Load Plugin');
387
+ }
388
+ async loadAppPlugins() {
389
+ // loader plugins from application
390
+ const appPlugins = await this.readPluginConfigs(path.join(this.options.baseDir, 'config/plugin.default'));
391
+ debug('Loaded app plugins: %j', Object.keys(appPlugins).map(k => `${k}:${appPlugins[k].enable}`));
392
+ return appPlugins;
393
+ }
394
+ async loadEggPlugins() {
395
+ // loader plugins from framework
396
+ const eggPluginConfigPaths = this.eggPaths.map(eggPath => path.join(eggPath, 'config/plugin.default'));
397
+ const eggPlugins = await this.readPluginConfigs(eggPluginConfigPaths);
398
+ debug('Loaded egg plugins: %j', Object.keys(eggPlugins).map(k => `${k}:${eggPlugins[k].enable}`));
399
+ return eggPlugins;
400
+ }
401
+ loadCustomPlugins() {
402
+ // loader plugins from process.env.EGG_PLUGINS
403
+ let customPlugins = {};
404
+ const configPaths = [];
405
+ if (process.env.EGG_PLUGINS) {
406
+ try {
407
+ customPlugins = JSON.parse(process.env.EGG_PLUGINS);
408
+ configPaths.push('<process.env.EGG_PLUGINS>');
409
+ }
410
+ catch (e) {
411
+ debug('parse EGG_PLUGINS failed, %s', e);
412
+ }
413
+ }
414
+ // loader plugins from options.plugins
415
+ if (this.options.plugins) {
416
+ customPlugins = {
417
+ ...customPlugins,
418
+ ...this.options.plugins,
419
+ };
420
+ configPaths.push('<options.plugins>');
421
+ }
422
+ if (customPlugins) {
423
+ const configPath = configPaths.join(' or ');
424
+ for (const name in customPlugins) {
425
+ this.#normalizePluginConfig(customPlugins, name, configPath);
426
+ }
427
+ debug('Loaded custom plugins: %j', Object.keys(customPlugins));
428
+ }
429
+ return customPlugins;
430
+ }
431
+ /*
432
+ * Read plugin.js from multiple directory
433
+ */
434
+ async readPluginConfigs(configPaths) {
435
+ if (!Array.isArray(configPaths)) {
436
+ configPaths = [configPaths];
437
+ }
438
+ // Get all plugin configurations
439
+ // plugin.default.js
440
+ // plugin.${scope}.js
441
+ // plugin.${env}.js
442
+ // plugin.${scope}_${env}.js
443
+ const newConfigPaths = [];
444
+ for (const filename of this.getTypeFiles('plugin')) {
445
+ for (let configPath of configPaths) {
446
+ configPath = path.join(path.dirname(configPath), filename);
447
+ newConfigPaths.push(configPath);
448
+ }
449
+ }
450
+ const plugins = {};
451
+ for (const configPath of newConfigPaths) {
452
+ let filepath = this.resolveModule(configPath);
453
+ // let plugin.js compatible
454
+ if (configPath.endsWith('plugin.default') && !filepath) {
455
+ filepath = this.resolveModule(configPath.replace(/plugin\.default$/, 'plugin'));
456
+ }
457
+ if (!filepath) {
458
+ continue;
459
+ }
460
+ const config = await utils.loadFile(filepath);
461
+ for (const name in config) {
462
+ this.#normalizePluginConfig(config, name, filepath);
463
+ }
464
+ this.#extendPlugins(plugins, config);
465
+ }
466
+ return plugins;
467
+ }
468
+ #normalizePluginConfig(plugins, name, configPath) {
469
+ const plugin = plugins[name];
470
+ // plugin_name: false
471
+ if (typeof plugin === 'boolean') {
472
+ plugins[name] = {
473
+ name,
474
+ enable: plugin,
475
+ dependencies: [],
476
+ optionalDependencies: [],
477
+ env: [],
478
+ from: configPath,
479
+ };
480
+ return;
481
+ }
482
+ if (!('enable' in plugin)) {
483
+ Reflect.set(plugin, 'enable', true);
484
+ }
485
+ plugin.name = name;
486
+ plugin.dependencies = plugin.dependencies || [];
487
+ plugin.optionalDependencies = plugin.optionalDependencies || [];
488
+ plugin.env = plugin.env || [];
489
+ plugin.from = plugin.from || configPath;
490
+ depCompatible(plugin);
491
+ }
492
+ // Read plugin information from package.json and merge
493
+ // {
494
+ // eggPlugin: {
495
+ // "name": "", plugin name, must be same as name in config/plugin.js
496
+ // "dep": [], dependent plugins
497
+ // "env": "" env
498
+ // "strict": true, whether check plugin name, default to true.
499
+ // }
500
+ // }
501
+ #mergePluginConfig(plugin) {
502
+ let pkg;
503
+ let config;
504
+ const pluginPackage = path.join(plugin.path, 'package.json');
505
+ if (fs.existsSync(pluginPackage)) {
506
+ pkg = readJSONSync(pluginPackage);
507
+ config = pkg.eggPlugin;
508
+ if (pkg.version) {
509
+ plugin.version = pkg.version;
510
+ }
511
+ }
512
+ const logger = this.options.logger;
513
+ if (!config) {
514
+ logger.warn(`[@eggjs/core:egg_loader] pkg.eggPlugin is missing in ${pluginPackage}`);
515
+ return;
516
+ }
517
+ if (config.name && config.strict !== false && config.name !== plugin.name) {
518
+ // pluginName is configured in config/plugin.js
519
+ // pluginConfigName is pkg.eggPlugin.name
520
+ logger.warn(`[@eggjs/core:egg_loader] pluginName(${plugin.name}) is different from pluginConfigName(${config.name})`);
521
+ }
522
+ // dep compatible
523
+ depCompatible(config);
524
+ for (const key of ['dependencies', 'optionalDependencies', 'env']) {
525
+ const values = config[key];
526
+ const existsValues = Reflect.get(plugin, key);
527
+ if (Array.isArray(values) && !existsValues?.length) {
528
+ Reflect.set(plugin, key, values);
529
+ }
530
+ }
531
+ }
532
+ getOrderPlugins(allPlugins, enabledPluginNames, appPlugins) {
533
+ // no plugins enabled
534
+ if (!enabledPluginNames.length) {
535
+ return [];
536
+ }
537
+ const result = sequencify(allPlugins, enabledPluginNames);
538
+ debug('Got plugins %j after sequencify', result);
539
+ // catch error when result.sequence is empty
540
+ if (!result.sequence.length) {
541
+ const err = new Error(`sequencify plugins has problem, missing: [${result.missingTasks}], recursive: [${result.recursiveDependencies}]`);
542
+ // find plugins which is required by the missing plugin
543
+ for (const missName of result.missingTasks) {
544
+ const requires = [];
545
+ for (const name in allPlugins) {
546
+ if (allPlugins[name].dependencies.includes(missName)) {
547
+ requires.push(name);
548
+ }
549
+ }
550
+ err.message += `\n\t>> Plugin [${missName}] is disabled or missed, but is required by [${requires}]`;
551
+ }
552
+ err.name = 'PluginSequencifyError';
553
+ throw err;
554
+ }
555
+ // log the plugins that be enabled implicitly
556
+ const implicitEnabledPlugins = [];
557
+ const requireMap = {};
558
+ result.sequence.forEach(name => {
559
+ for (const depName of allPlugins[name].dependencies) {
560
+ if (!requireMap[depName]) {
561
+ requireMap[depName] = [];
562
+ }
563
+ requireMap[depName].push(name);
564
+ }
565
+ if (!allPlugins[name].enable) {
566
+ implicitEnabledPlugins.push(name);
567
+ allPlugins[name].enable = true;
568
+ allPlugins[name].implicitEnable = true;
569
+ }
570
+ });
571
+ for (const [name, dependents] of Object.entries(requireMap)) {
572
+ // note:`dependents` will not includes `optionalDependencies`
573
+ allPlugins[name].dependents = dependents;
574
+ }
575
+ // Following plugins will be enabled implicitly.
576
+ // - configclient required by [hsfclient]
577
+ // - eagleeye required by [hsfclient]
578
+ // - diamond required by [hsfclient]
579
+ if (implicitEnabledPlugins.length) {
580
+ let message = implicitEnabledPlugins
581
+ .map(name => ` - ${name} required by [${requireMap[name]}]`)
582
+ .join('\n');
583
+ this.options.logger.info(`Following plugins will be enabled implicitly.\n${message}`);
584
+ // should warn when the plugin is disabled by app
585
+ const disabledPlugins = implicitEnabledPlugins.filter(name => appPlugins[name] && appPlugins[name].enable === false);
586
+ if (disabledPlugins.length) {
587
+ message = disabledPlugins
588
+ .map(name => ` - ${name} required by [${requireMap[name]}]`)
589
+ .join('\n');
590
+ this.options.logger.warn(`Following plugins will be enabled implicitly that is disabled by application.\n${message}`);
591
+ }
592
+ }
593
+ return result.sequence.map(name => allPlugins[name]);
594
+ }
595
+ getLookupDirs() {
596
+ const lookupDirs = new Set();
597
+ // try to locate the plugin in the following directories's node_modules
598
+ // -> {APP_PATH} -> {EGG_PATH} -> $CWD
599
+ lookupDirs.add(this.options.baseDir);
600
+ // try to locate the plugin at framework from upper to lower
601
+ for (let i = this.eggPaths.length - 1; i >= 0; i--) {
602
+ const eggPath = this.eggPaths[i];
603
+ lookupDirs.add(eggPath);
604
+ }
605
+ // should find the $cwd when test the plugins under npm3
606
+ lookupDirs.add(process.cwd());
607
+ return lookupDirs;
608
+ }
609
+ // Get the real plugin path
610
+ getPluginPath(plugin) {
611
+ if (plugin.path) {
612
+ return plugin.path;
613
+ }
614
+ if (plugin.package) {
615
+ assert(isValidatePackageName(plugin.package), `plugin ${plugin.name} invalid, use 'path' instead of package: "${plugin.package}"`);
616
+ }
617
+ return this.#resolvePluginPath(plugin);
618
+ }
619
+ #resolvePluginPath(plugin) {
620
+ const name = plugin.package || plugin.name;
621
+ try {
622
+ // should find the plugin directory
623
+ // pnpm will lift the node_modules to the sibling directory
624
+ // 'node_modules/.pnpm/yadan@2.0.0/node_modules/yadan/node_modules',
625
+ // 'node_modules/.pnpm/yadan@2.0.0/node_modules', <- this is the sibling directory
626
+ // 'node_modules/.pnpm/egg@2.33.1/node_modules/egg/node_modules',
627
+ // 'node_modules/.pnpm/egg@2.33.1/node_modules', <- this is the sibling directory
628
+ const filePath = utils.resolvePath(`${name}/package.json`, { paths: [...this.lookupDirs] });
629
+ return path.dirname(filePath);
630
+ }
631
+ catch (err) {
632
+ debug('[resolvePluginPath] error: %o', err);
633
+ throw new Error(`Can not find plugin ${name} in "${[...this.lookupDirs].join(', ')}"`);
634
+ }
635
+ }
636
+ #extendPlugins(targets, plugins) {
637
+ if (!plugins) {
638
+ return;
639
+ }
640
+ for (const name in plugins) {
641
+ const plugin = plugins[name];
642
+ let targetPlugin = targets[name];
643
+ if (!targetPlugin) {
644
+ targetPlugin = targets[name] = {};
645
+ }
646
+ if (targetPlugin.package && targetPlugin.package === plugin.package) {
647
+ this.logger.warn('[@eggjs/core] plugin %s has been defined that is %j, but you define again in %s', name, targetPlugin, plugin.from);
648
+ }
649
+ if (plugin.path || plugin.package) {
650
+ delete targetPlugin.path;
651
+ delete targetPlugin.package;
652
+ }
653
+ for (const [prop, value] of Object.entries(plugin)) {
654
+ if (value === undefined) {
655
+ continue;
656
+ }
657
+ if (Reflect.get(targetPlugin, prop) && Array.isArray(value) && !value.length) {
658
+ continue;
659
+ }
660
+ Reflect.set(targetPlugin, prop, value);
661
+ }
662
+ }
663
+ }
664
+ /** end Plugin loader */
665
+ /** start Config loader */
666
+ configMeta;
667
+ config;
668
+ /**
669
+ * Load config/config.js
670
+ *
671
+ * Will merge config.default.js 和 config.${env}.js
672
+ *
673
+ * @function EggLoader#loadConfig
674
+ * @since 1.0.0
675
+ */
676
+ async loadConfig() {
677
+ this.timing.start('Load Config');
678
+ this.configMeta = {};
679
+ const target = {};
680
+ // Load Application config first
681
+ const appConfig = await this.#preloadAppConfig();
682
+ // plugin config.default
683
+ // framework config.default
684
+ // app config.default
685
+ // plugin config.{env}
686
+ // framework config.{env}
687
+ // app config.{env}
688
+ for (const filename of this.getTypeFiles('config')) {
689
+ for (const unit of this.getLoadUnits()) {
690
+ const isApp = unit.type === 'app';
691
+ const config = await this.#loadConfig(unit.path, filename, isApp ? undefined : appConfig, unit.type);
692
+ if (!config) {
693
+ continue;
694
+ }
695
+ debug('[loadConfig] Loaded config %s/%s, %j', unit.path, filename, config);
696
+ extend(true, target, config);
697
+ }
698
+ }
699
+ // load env from process.env.EGG_APP_CONFIG
700
+ const envConfig = this.#loadConfigFromEnv();
701
+ debug('[loadConfig] Loaded config from env, %j', envConfig);
702
+ extend(true, target, envConfig);
703
+ // You can manipulate the order of app.config.coreMiddleware and app.config.appMiddleware in app.js
704
+ target.coreMiddleware = target.coreMiddlewares = target.coreMiddleware || [];
705
+ target.appMiddleware = target.appMiddlewares = target.middleware || [];
706
+ this.config = target;
707
+ debug('[loadConfig] all config: %o', this.config);
708
+ this.timing.end('Load Config');
709
+ }
710
+ async #preloadAppConfig() {
711
+ const names = [
712
+ 'config.default',
713
+ `config.${this.serverEnv}`,
714
+ ];
715
+ const target = {};
716
+ for (const filename of names) {
717
+ const config = await this.#loadConfig(this.options.baseDir, filename, undefined, 'app');
718
+ if (!config) {
719
+ continue;
720
+ }
721
+ extend(true, target, config);
722
+ }
723
+ return target;
724
+ }
725
+ async #loadConfig(dirpath, filename, extraInject, type) {
726
+ const isPlugin = type === 'plugin';
727
+ const isApp = type === 'app';
728
+ let filepath = this.resolveModule(path.join(dirpath, 'config', filename));
729
+ // let config.js compatible
730
+ if (filename === 'config.default' && !filepath) {
731
+ filepath = this.resolveModule(path.join(dirpath, 'config/config'));
732
+ }
733
+ const config = await this.loadFile(filepath, this.appInfo, extraInject);
734
+ if (!config)
735
+ return;
736
+ if (isPlugin || isApp) {
737
+ assert(!config.coreMiddleware, 'Can not define coreMiddleware in app or plugin');
738
+ }
739
+ if (!isApp) {
740
+ assert(!config.middleware, 'Can not define middleware in ' + filepath);
741
+ }
742
+ // store config meta, check where is the property of config come from.
743
+ this.#setConfigMeta(config, filepath);
744
+ return config;
745
+ }
746
+ #loadConfigFromEnv() {
747
+ const envConfigStr = process.env.EGG_APP_CONFIG;
748
+ if (!envConfigStr)
749
+ return;
750
+ try {
751
+ const envConfig = JSON.parse(envConfigStr);
752
+ this.#setConfigMeta(envConfig, '<process.env.EGG_APP_CONFIG>');
753
+ return envConfig;
754
+ }
755
+ catch (err) {
756
+ this.options.logger.warn('[egg-loader] process.env.EGG_APP_CONFIG is not invalid JSON: %s', envConfigStr);
757
+ }
758
+ }
759
+ #setConfigMeta(config, filepath) {
760
+ config = extend(true, {}, config);
761
+ this.#setConfig(config, filepath);
762
+ extend(true, this.configMeta, config);
763
+ }
764
+ #setConfig(obj, filepath) {
765
+ for (const key of Object.keys(obj)) {
766
+ const val = obj[key];
767
+ // ignore console
768
+ if (key === 'console' && val && typeof val.Console === 'function' && val.Console === console.Console) {
769
+ obj[key] = filepath;
770
+ continue;
771
+ }
772
+ if (val && Object.getPrototypeOf(val) === Object.prototype && Object.keys(val).length > 0) {
773
+ this.#setConfig(val, filepath);
774
+ continue;
775
+ }
776
+ obj[key] = filepath;
777
+ }
778
+ }
779
+ /** end Config loader */
780
+ /** start Extend loader */
781
+ /**
782
+ * mixin Agent.prototype
783
+ * @function EggLoader#loadAgentExtend
784
+ * @since 1.0.0
785
+ */
786
+ async loadAgentExtend() {
787
+ await this.loadExtend('agent', this.app);
788
+ }
789
+ /**
790
+ * mixin Application.prototype
791
+ * @function EggLoader#loadApplicationExtend
792
+ * @since 1.0.0
793
+ */
794
+ async loadApplicationExtend() {
795
+ await this.loadExtend('application', this.app);
796
+ }
797
+ /**
798
+ * mixin Request.prototype
799
+ * @function EggLoader#loadRequestExtend
800
+ * @since 1.0.0
801
+ */
802
+ async loadRequestExtend() {
803
+ await this.loadExtend('request', this.app.request);
804
+ }
805
+ /**
806
+ * mixin Response.prototype
807
+ * @function EggLoader#loadResponseExtend
808
+ * @since 1.0.0
809
+ */
810
+ async loadResponseExtend() {
811
+ await this.loadExtend('response', this.app.response);
812
+ }
813
+ /**
814
+ * mixin Context.prototype
815
+ * @function EggLoader#loadContextExtend
816
+ * @since 1.0.0
817
+ */
818
+ async loadContextExtend() {
819
+ await this.loadExtend('context', this.app.context);
820
+ }
821
+ /**
822
+ * mixin app.Helper.prototype
823
+ * @function EggLoader#loadHelperExtend
824
+ * @since 1.0.0
825
+ */
826
+ async loadHelperExtend() {
827
+ if (this.app.Helper) {
828
+ await this.loadExtend('helper', this.app.Helper.prototype);
829
+ }
830
+ }
831
+ /**
832
+ * Find all extend file paths by name
833
+ * can be override in top level framework to support load `app/extends/{name}.js`
834
+ *
835
+ * @param {String} name - filename which may be `app/extend/{name}.js`
836
+ * @return {Array} filepaths extend file paths
837
+ * @private
838
+ */
839
+ getExtendFilePaths(name) {
840
+ return this.getLoadUnits().map(unit => path.join(unit.path, 'app/extend', name));
841
+ }
842
+ /**
843
+ * Loader app/extend/xx.js to `prototype`,
844
+ * @function loadExtend
845
+ * @param {String} name - filename which may be `app/extend/{name}.js`
846
+ * @param {Object} proto - prototype that mixed
847
+ * @since 1.0.0
848
+ */
849
+ async loadExtend(name, proto) {
850
+ this.timing.start(`Load extend/${name}.js`);
851
+ // All extend files
852
+ const filepaths = this.getExtendFilePaths(name);
853
+ // if use mm.env and serverEnv is not unittest
854
+ const needUnittest = 'EGG_MOCK_SERVER_ENV' in process.env && this.serverEnv !== 'unittest';
855
+ const length = filepaths.length;
856
+ for (let i = 0; i < length; i++) {
857
+ const filepath = filepaths[i];
858
+ filepaths.push(filepath + `.${this.serverEnv}`);
859
+ if (needUnittest) {
860
+ filepaths.push(filepath + '.unittest');
861
+ }
862
+ }
863
+ debug('loadExtend %s, filepaths: %j', name, filepaths);
864
+ const mergeRecord = new Map();
865
+ for (let filepath of filepaths) {
866
+ filepath = this.resolveModule(filepath);
867
+ if (!filepath) {
868
+ continue;
869
+ }
870
+ if (filepath.endsWith('/index.js')) {
871
+ this.app.deprecate(`app/extend/${name}/index.js is deprecated, use app/extend/${name}.js instead`);
872
+ }
873
+ else if (filepath.endsWith('/index.ts')) {
874
+ this.app.deprecate(`app/extend/${name}/index.ts is deprecated, use app/extend/${name}.ts instead`);
875
+ }
876
+ const ext = await this.requireFile(filepath);
877
+ const properties = Object.getOwnPropertyNames(ext)
878
+ .concat(Object.getOwnPropertySymbols(ext));
879
+ for (const property of properties) {
880
+ if (mergeRecord.has(property)) {
881
+ debug('Property: "%s" already exists in "%s",it will be redefined by "%s"', property, mergeRecord.get(property), filepath);
882
+ }
883
+ // Copy descriptor
884
+ let descriptor = Object.getOwnPropertyDescriptor(ext, property);
885
+ let originalDescriptor = Object.getOwnPropertyDescriptor(proto, property);
886
+ if (!originalDescriptor) {
887
+ // try to get descriptor from originalPrototypes
888
+ const originalProto = originalPrototypes[name];
889
+ if (originalProto) {
890
+ originalDescriptor = Object.getOwnPropertyDescriptor(originalProto, property);
891
+ }
892
+ }
893
+ if (originalDescriptor) {
894
+ // don't override descriptor
895
+ descriptor = {
896
+ ...descriptor,
897
+ };
898
+ if (!descriptor.set && originalDescriptor.set) {
899
+ descriptor.set = originalDescriptor.set;
900
+ }
901
+ if (!descriptor.get && originalDescriptor.get) {
902
+ descriptor.get = originalDescriptor.get;
903
+ }
904
+ }
905
+ Object.defineProperty(proto, property, descriptor);
906
+ mergeRecord.set(property, filepath);
907
+ }
908
+ debug('merge %j to %s from %s', Object.keys(ext), name, filepath);
909
+ }
910
+ this.timing.end(`Load extend/${name}.js`);
911
+ }
912
+ /** end Extend loader */
913
+ /** start Custom loader */
914
+ /**
915
+ * load app.js
916
+ *
917
+ * @example
918
+ * - old:
919
+ *
920
+ * ```js
921
+ * module.exports = function(app) {
922
+ * doSomething();
923
+ * }
924
+ * ```
925
+ *
926
+ * - new:
927
+ *
928
+ * ```js
929
+ * module.exports = class Boot {
930
+ * constructor(app) {
931
+ * this.app = app;
932
+ * }
933
+ * configDidLoad() {
934
+ * doSomething();
935
+ * }
936
+ * }
937
+ * @since 1.0.0
938
+ */
939
+ async loadCustomApp() {
940
+ await this.#loadBootHook('app');
941
+ this.lifecycle.triggerConfigWillLoad();
942
+ }
943
+ /**
944
+ * Load agent.js, same as {@link EggLoader#loadCustomApp}
945
+ */
946
+ async loadCustomAgent() {
947
+ await this.#loadBootHook('agent');
948
+ this.lifecycle.triggerConfigWillLoad();
949
+ }
950
+ // FIXME: no logger used after egg removed
951
+ loadBootHook() {
952
+ // do nothing
953
+ }
954
+ async #loadBootHook(fileName) {
955
+ this.timing.start(`Load ${fileName}.js`);
956
+ for (const unit of this.getLoadUnits()) {
957
+ const bootFilePath = this.resolveModule(path.join(unit.path, fileName));
958
+ if (!bootFilePath) {
959
+ continue;
960
+ }
961
+ const bootHook = await this.requireFile(bootFilePath);
962
+ if (isClass(bootHook)) {
963
+ bootHook.prototype.fullPath = bootFilePath;
964
+ // if is boot class, add to lifecycle
965
+ this.lifecycle.addBootHook(bootHook);
966
+ }
967
+ else if (typeof bootHook === 'function') {
968
+ // if is boot function, wrap to class
969
+ // for compatibility
970
+ this.lifecycle.addFunctionAsBootHook(bootHook);
971
+ }
972
+ else {
973
+ this.options.logger.warn('[@eggjs/core:egg_loader] %s must exports a boot class', bootFilePath);
974
+ }
975
+ }
976
+ // init boots
977
+ this.lifecycle.init();
978
+ this.timing.end(`Load ${fileName}.js`);
979
+ }
980
+ /** end Custom loader */
981
+ /** start Service loader */
982
+ /**
983
+ * Load app/service
984
+ * @function EggLoader#loadService
985
+ * @param {Object} options - LoaderOptions
986
+ * @since 1.0.0
987
+ */
988
+ async loadService(options) {
989
+ this.timing.start('Load Service');
990
+ // 载入到 app.serviceClasses
991
+ const servicePaths = this.getLoadUnits().map(unit => path.join(unit.path, 'app/service'));
992
+ options = {
993
+ call: true,
994
+ caseStyle: 'lower',
995
+ fieldClass: 'serviceClasses',
996
+ directory: servicePaths,
997
+ ...options,
998
+ };
999
+ debug('[loadService] options: %o', options);
1000
+ await this.loadToContext(servicePaths, 'service', options);
1001
+ this.timing.end('Load Service');
1002
+ }
1003
+ /** end Service loader */
1004
+ /** start Middleware loader */
1005
+ /**
1006
+ * Load app/middleware
1007
+ *
1008
+ * app.config.xx is the options of the middleware xx that has same name as config
1009
+ *
1010
+ * @function EggLoader#loadMiddleware
1011
+ * @param {Object} opt - LoaderOptions
1012
+ * @example
1013
+ * ```js
1014
+ * // app/middleware/status.js
1015
+ * module.exports = function(options, app) {
1016
+ * // options == app.config.status
1017
+ * return async next => {
1018
+ * await next();
1019
+ * }
1020
+ * }
1021
+ * ```
1022
+ * @since 1.0.0
1023
+ */
1024
+ async loadMiddleware(opt) {
1025
+ this.timing.start('Load Middleware');
1026
+ const app = this.app;
1027
+ // load middleware to app.middleware
1028
+ const middlewarePaths = this.getLoadUnits().map(unit => path.join(unit.path, 'app/middleware'));
1029
+ opt = {
1030
+ call: false,
1031
+ override: true,
1032
+ caseStyle: 'lower',
1033
+ directory: middlewarePaths,
1034
+ ...opt,
1035
+ };
1036
+ await this.loadToApp(middlewarePaths, 'middlewares', opt);
1037
+ for (const name in app.middlewares) {
1038
+ Object.defineProperty(app.middleware, name, {
1039
+ get() {
1040
+ return app.middlewares[name];
1041
+ },
1042
+ enumerable: false,
1043
+ configurable: false,
1044
+ });
1045
+ }
1046
+ this.options.logger.info('Use coreMiddleware order: %j', this.config.coreMiddleware);
1047
+ this.options.logger.info('Use appMiddleware order: %j', this.config.appMiddleware);
1048
+ // use middleware ordered by app.config.coreMiddleware and app.config.appMiddleware
1049
+ const middlewareNames = this.config.coreMiddleware.concat(this.config.appMiddleware);
1050
+ debug('[loadMiddleware] middlewareNames: %j', middlewareNames);
1051
+ const middlewaresMap = new Map();
1052
+ for (const name of middlewareNames) {
1053
+ const createMiddleware = app.middlewares[name];
1054
+ if (!createMiddleware) {
1055
+ throw new TypeError(`Middleware ${name} not found`);
1056
+ }
1057
+ if (middlewaresMap.has(name)) {
1058
+ throw new TypeError(`Middleware ${name} redefined`);
1059
+ }
1060
+ middlewaresMap.set(name, true);
1061
+ const options = this.config[name] || {};
1062
+ let mw = createMiddleware(options, app);
1063
+ assert(typeof mw === 'function', `Middleware ${name} must be a function, but actual is ${inspect(mw)}`);
1064
+ if (isGeneratorFunction(mw)) {
1065
+ const fullpath = Reflect.get(createMiddleware, FULLPATH);
1066
+ throw new TypeError(`Support for generators was removed, middleware: ${name}, fullpath: ${fullpath}`);
1067
+ }
1068
+ mw._name = name;
1069
+ // middlewares support options.enable, options.ignore and options.match
1070
+ mw = wrapMiddleware(mw, options);
1071
+ if (mw) {
1072
+ if (debug.enabled) {
1073
+ // show mw debug log on every request
1074
+ mw = debugMiddlewareWrapper(mw);
1075
+ }
1076
+ app.use(mw);
1077
+ debug('[loadMiddleware] Use middleware: %s with options: %j', name, options);
1078
+ this.options.logger.info('[@eggjs/core:egg_loader] Use middleware: %s', name);
1079
+ }
1080
+ else {
1081
+ this.options.logger.info('[@eggjs/core:egg_loader] Disable middleware: %s', name);
1082
+ }
1083
+ }
1084
+ this.options.logger.info('[@eggjs/core:egg_loader] Loaded middleware from %j', middlewarePaths);
1085
+ this.timing.end('Load Middleware');
1086
+ }
1087
+ /** end Middleware loader */
1088
+ /** start Controller loader */
1089
+ /**
1090
+ * Load app/controller
1091
+ * @param {Object} opt - LoaderOptions
1092
+ * @since 1.0.0
1093
+ */
1094
+ async loadController(opt) {
1095
+ this.timing.start('Load Controller');
1096
+ const controllerBase = path.join(this.options.baseDir, 'app/controller');
1097
+ opt = {
1098
+ caseStyle: 'lower',
1099
+ directory: controllerBase,
1100
+ initializer: (obj, opt) => {
1101
+ // return class if it exports a function
1102
+ // ```js
1103
+ // module.exports = app => {
1104
+ // return class HomeController extends app.Controller {};
1105
+ // }
1106
+ // ```
1107
+ if (isGeneratorFunction(obj)) {
1108
+ throw new TypeError(`Support for generators was removed, fullpath: ${opt.path}`);
1109
+ }
1110
+ if (!isClass(obj) && !isAsyncFunction(obj)) {
1111
+ if (typeof obj === 'function') {
1112
+ obj = obj(this.app);
1113
+ debug('[loadController] after init(app) => %o, meta: %j', obj, opt);
1114
+ if (isGeneratorFunction(obj)) {
1115
+ throw new TypeError(`Support for generators was removed, fullpath: ${opt.path}`);
1116
+ }
1117
+ }
1118
+ }
1119
+ if (isClass(obj)) {
1120
+ obj.prototype.pathName = opt.pathName;
1121
+ obj.prototype.fullPath = opt.path;
1122
+ return wrapControllerClass(obj, opt.path);
1123
+ }
1124
+ if (isObject(obj)) {
1125
+ return wrapObject(obj, opt.path);
1126
+ }
1127
+ if (isAsyncFunction(obj)) {
1128
+ return wrapObject({ 'module.exports': obj }, opt.path)['module.exports'];
1129
+ }
1130
+ return obj;
1131
+ },
1132
+ ...opt,
1133
+ };
1134
+ await this.loadToApp(controllerBase, 'controller', opt);
1135
+ debug('[loadController] app.controller => %o', this.app.controller);
1136
+ this.options.logger.info('[@eggjs/core:egg_loader] Controller loaded: %s', controllerBase);
1137
+ this.timing.end('Load Controller');
1138
+ }
1139
+ /** end Controller loader */
1140
+ /** start Router loader */
1141
+ /**
1142
+ * Load app/router.js
1143
+ * @function EggLoader#loadRouter
1144
+ * @since 1.0.0
1145
+ */
1146
+ async loadRouter() {
1147
+ this.timing.start('Load Router');
1148
+ await this.loadFile(path.join(this.options.baseDir, 'app/router'));
1149
+ // add router middleware
1150
+ const mw = this.app.router.middleware();
1151
+ Reflect.set(mw, '_name', 'routerMiddleware');
1152
+ this.app.use(mw);
1153
+ this.timing.end('Load Router');
1154
+ }
1155
+ /** end Router loader */
1156
+ /** start CustomLoader loader */
1157
+ async loadCustomLoader() {
1158
+ assert(this.config, 'should loadConfig first');
1159
+ const customLoader = this.config.customLoader || {};
1160
+ for (const property of Object.keys(customLoader)) {
1161
+ const loaderConfig = {
1162
+ ...customLoader[property],
1163
+ };
1164
+ assert(loaderConfig.directory, `directory is required for config.customLoader.${property}`);
1165
+ let directory;
1166
+ if (loaderConfig.loadunit === true) {
1167
+ directory = this.getLoadUnits().map(unit => path.join(unit.path, loaderConfig.directory));
1168
+ }
1169
+ else {
1170
+ directory = path.join(this.appInfo.baseDir, loaderConfig.directory);
1171
+ }
1172
+ const inject = loaderConfig.inject || 'app';
1173
+ debug('[loadCustomLoader] loaderConfig: %o, inject: %o, directory: %o', loaderConfig, inject, directory);
1174
+ switch (inject) {
1175
+ case 'ctx': {
1176
+ assert(!(property in this.app.context), `customLoader should not override ctx.${property}`);
1177
+ const options = {
1178
+ caseStyle: 'lower',
1179
+ fieldClass: `${property}Classes`,
1180
+ ...loaderConfig,
1181
+ directory,
1182
+ };
1183
+ await this.loadToContext(directory, property, options);
1184
+ break;
1185
+ }
1186
+ case 'app': {
1187
+ assert(!(property in this.app), `customLoader should not override app.${property}`);
1188
+ const options = {
1189
+ caseStyle: 'lower',
1190
+ initializer: (Clazz) => {
1191
+ return isClass(Clazz) ? new Clazz(this.app) : Clazz;
1192
+ },
1193
+ ...loaderConfig,
1194
+ directory,
1195
+ };
1196
+ await this.loadToApp(directory, property, options);
1197
+ break;
1198
+ }
1199
+ default:
1200
+ throw new Error('inject only support app or ctx');
1201
+ }
1202
+ }
1203
+ }
1204
+ /** end CustomLoader loader */
1205
+ // Low Level API
1206
+ /**
1207
+ * Load single file, will invoke when export is function
1208
+ *
1209
+ * @param {String} filepath - fullpath
1210
+ * @param {Array} inject - pass rest arguments into the function when invoke
1211
+ * @return {Object} exports
1212
+ * @example
1213
+ * ```js
1214
+ * app.loader.loadFile(path.join(app.options.baseDir, 'config/router.js'));
1215
+ * ```
1216
+ * @since 1.0.0
1217
+ */
1218
+ async loadFile(filepath, ...inject) {
1219
+ const fullpath = filepath && this.resolveModule(filepath);
1220
+ if (!fullpath) {
1221
+ return null;
1222
+ }
1223
+ // function(arg1, args, ...) {}
1224
+ if (inject.length === 0) {
1225
+ inject = [this.app];
1226
+ }
1227
+ let mod = await this.requireFile(fullpath);
1228
+ if (typeof mod === 'function' && !isClass(mod)) {
1229
+ mod = mod(...inject);
1230
+ }
1231
+ return mod;
1232
+ }
1233
+ /**
1234
+ * @param {String} filepath - fullpath
1235
+ * @return {Object} exports
1236
+ * @private
1237
+ */
1238
+ async requireFile(filepath) {
1239
+ const timingKey = `Require(${this.#requiredCount++}) ${utils.getResolvedFilename(filepath, this.options.baseDir)}`;
1240
+ this.timing.start(timingKey);
1241
+ const mod = await utils.loadFile(filepath);
1242
+ this.timing.end(timingKey);
1243
+ return mod;
1244
+ }
1245
+ /**
1246
+ * Get all loadUnit
1247
+ *
1248
+ * loadUnit is a directory that can be loaded by EggLoader, it has the same structure.
1249
+ * loadUnit has a path and a type(app, framework, plugin).
1250
+ *
1251
+ * The order of the loadUnits:
1252
+ *
1253
+ * 1. plugin
1254
+ * 2. framework
1255
+ * 3. app
1256
+ *
1257
+ * @return {Array} loadUnits
1258
+ * @since 1.0.0
1259
+ */
1260
+ getLoadUnits() {
1261
+ if (this.dirs) {
1262
+ return this.dirs;
1263
+ }
1264
+ this.dirs = [];
1265
+ if (this.orderPlugins) {
1266
+ for (const plugin of this.orderPlugins) {
1267
+ this.dirs.push({
1268
+ path: plugin.path,
1269
+ type: 'plugin',
1270
+ });
1271
+ }
1272
+ }
1273
+ // framework or egg path
1274
+ for (const eggPath of this.eggPaths) {
1275
+ this.dirs.push({
1276
+ path: eggPath,
1277
+ type: 'framework',
1278
+ });
1279
+ }
1280
+ // application
1281
+ this.dirs.push({
1282
+ path: this.options.baseDir,
1283
+ type: 'app',
1284
+ });
1285
+ debug('Loaded dirs %j', this.dirs);
1286
+ return this.dirs;
1287
+ }
1288
+ /**
1289
+ * Load files using {@link FileLoader}, inject to {@link Application}
1290
+ * @param {String|Array} directory - see {@link FileLoader}
1291
+ * @param {String} property - see {@link FileLoader}
1292
+ * @param {Object} options - see {@link FileLoader}
1293
+ * @since 1.0.0
1294
+ */
1295
+ async loadToApp(directory, property, options) {
1296
+ const target = {};
1297
+ Reflect.set(this.app, property, target);
1298
+ options = {
1299
+ ...options,
1300
+ directory: options.directory ?? directory,
1301
+ target,
1302
+ inject: this.app,
1303
+ };
1304
+ const timingKey = `Load "${String(property)}" to Application`;
1305
+ this.timing.start(timingKey);
1306
+ await new FileLoader(options).load();
1307
+ this.timing.end(timingKey);
1308
+ }
1309
+ /**
1310
+ * Load files using {@link ContextLoader}
1311
+ * @param {String|Array} directory - see {@link ContextLoader}
1312
+ * @param {String} property - see {@link ContextLoader}
1313
+ * @param {Object} options - see {@link ContextLoader}
1314
+ * @since 1.0.0
1315
+ */
1316
+ async loadToContext(directory, property, options) {
1317
+ options = {
1318
+ ...options,
1319
+ directory: options?.directory || directory,
1320
+ property,
1321
+ inject: this.app,
1322
+ };
1323
+ const timingKey = `Load "${String(property)}" to Context`;
1324
+ this.timing.start(timingKey);
1325
+ await new ContextLoader(options).load();
1326
+ this.timing.end(timingKey);
1327
+ }
1328
+ /**
1329
+ * @member {FileLoader} EggLoader#FileLoader
1330
+ * @since 1.0.0
1331
+ */
1332
+ get FileLoader() {
1333
+ return FileLoader;
1334
+ }
1335
+ /**
1336
+ * @member {ContextLoader} EggLoader#ContextLoader
1337
+ * @since 1.0.0
1338
+ */
1339
+ get ContextLoader() {
1340
+ return ContextLoader;
1341
+ }
1342
+ getTypeFiles(filename) {
1343
+ const files = [`${filename}.default`];
1344
+ if (this.serverScope)
1345
+ files.push(`${filename}.${this.serverScope}`);
1346
+ if (this.serverEnv === 'default')
1347
+ return files;
1348
+ files.push(`${filename}.${this.serverEnv}`);
1349
+ if (this.serverScope) {
1350
+ files.push(`${filename}.${this.serverScope}_${this.serverEnv}`);
1351
+ }
1352
+ return files;
1353
+ }
1354
+ resolveModule(filepath) {
1355
+ let fullPath;
1356
+ try {
1357
+ fullPath = utils.resolvePath(filepath);
1358
+ }
1359
+ catch (e) {
1360
+ return undefined;
1361
+ }
1362
+ if (process.env.EGG_TYPESCRIPT !== 'true' && fullPath.endsWith('.ts')) {
1363
+ return undefined;
1364
+ }
1365
+ return fullPath;
1366
+ }
1367
+ }
1368
+ function depCompatible(plugin) {
1369
+ if (plugin.dep && !(Array.isArray(plugin.dependencies) && plugin.dependencies.length)) {
1370
+ plugin.dependencies = plugin.dep;
1371
+ delete plugin.dep;
1372
+ }
1373
+ }
1374
+ function isValidatePackageName(name) {
1375
+ // only check file path style
1376
+ if (name.startsWith('.'))
1377
+ return false;
1378
+ if (name.startsWith('/'))
1379
+ return false;
1380
+ if (name.includes(':'))
1381
+ return false;
1382
+ return true;
1383
+ }
1384
+ // support pathMatching on middleware
1385
+ function wrapMiddleware(mw, options) {
1386
+ // support options.enable
1387
+ if (options.enable === false) {
1388
+ return null;
1389
+ }
1390
+ // support options.match and options.ignore
1391
+ if (!options.match && !options.ignore) {
1392
+ return mw;
1393
+ }
1394
+ const match = pathMatching(options);
1395
+ const fn = (ctx, next) => {
1396
+ if (!match(ctx))
1397
+ return next();
1398
+ return mw(ctx, next);
1399
+ };
1400
+ fn._name = `${mw._name}middlewareWrapper`;
1401
+ return fn;
1402
+ }
1403
+ function debugMiddlewareWrapper(mw) {
1404
+ const fn = async (ctx, next) => {
1405
+ const startTime = now();
1406
+ debug('[debugMiddlewareWrapper] [%s %s] enter middleware: %s', ctx.method, ctx.url, mw._name);
1407
+ await mw(ctx, next);
1408
+ const rt = diff(startTime);
1409
+ debug('[debugMiddlewareWrapper] [%s %s] after middleware: %s [%sms]', ctx.method, ctx.url, mw._name, rt);
1410
+ };
1411
+ fn._name = `${mw._name}DebugWrapper`;
1412
+ return fn;
1413
+ }
1414
+ // wrap the controller class, yield a object with middlewares
1415
+ function wrapControllerClass(Controller, fullPath) {
1416
+ let proto = Controller.prototype;
1417
+ const ret = {};
1418
+ // tracing the prototype chain
1419
+ while (proto !== Object.prototype) {
1420
+ const keys = Object.getOwnPropertyNames(proto);
1421
+ for (const key of keys) {
1422
+ // getOwnPropertyNames will return constructor
1423
+ // that should be ignored
1424
+ if (key === 'constructor') {
1425
+ continue;
1426
+ }
1427
+ // skip getter, setter & non-function properties
1428
+ const d = Object.getOwnPropertyDescriptor(proto, key);
1429
+ // prevent to override sub method
1430
+ if (typeof d?.value === 'function' && !ret.hasOwnProperty(key)) {
1431
+ const controllerMethodName = `${Controller.name}.${key}`;
1432
+ if (isGeneratorFunction(d.value)) {
1433
+ throw new TypeError(`Support for generators was removed, controller \`${controllerMethodName}\`, fullpath: ${fullPath}`);
1434
+ }
1435
+ ret[key] = controllerMethodToMiddleware(Controller, key);
1436
+ ret[key][FULLPATH] = `${fullPath}#${controllerMethodName}()`;
1437
+ }
1438
+ }
1439
+ proto = Object.getPrototypeOf(proto);
1440
+ }
1441
+ return ret;
1442
+ }
1443
+ function controllerMethodToMiddleware(Controller, key) {
1444
+ return function classControllerMiddleware(...args) {
1445
+ const controller = new Controller(this);
1446
+ if (!this.app.config.controller?.supportParams) {
1447
+ args = [this];
1448
+ }
1449
+ return controller[key](...args);
1450
+ };
1451
+ }
1452
+ // wrap the method of the object, method can receive ctx as it's first argument
1453
+ function wrapObject(obj, fullPath, prefix) {
1454
+ const keys = Object.keys(obj);
1455
+ const ret = {};
1456
+ prefix = prefix ?? '';
1457
+ for (const key of keys) {
1458
+ const controllerMethodName = `${prefix}${key}`;
1459
+ const item = obj[key];
1460
+ if (isGeneratorFunction(item)) {
1461
+ throw new TypeError(`Support for generators was removed, controller \`${controllerMethodName}\`, fullpath: ${fullPath}`);
1462
+ }
1463
+ if (typeof item === 'function') {
1464
+ const names = getParamNames(item);
1465
+ if (names[0] === 'next') {
1466
+ throw new Error(`controller \`${controllerMethodName}\` should not use next as argument from file ${fullPath}`);
1467
+ }
1468
+ ret[key] = objectFunctionToMiddleware(item);
1469
+ ret[key][FULLPATH] = `${fullPath}#${controllerMethodName}()`;
1470
+ }
1471
+ else if (isObject(item)) {
1472
+ ret[key] = wrapObject(item, fullPath, `${controllerMethodName}.`);
1473
+ }
1474
+ }
1475
+ debug('[wrapObject] fullPath: %s, prefix: %s => %o', fullPath, prefix, ret);
1476
+ return ret;
1477
+ }
1478
+ function objectFunctionToMiddleware(func) {
1479
+ async function objectControllerMiddleware(...args) {
1480
+ if (!this.app.config.controller?.supportParams) {
1481
+ args = [this];
1482
+ }
1483
+ return await func.apply(this, args);
1484
+ }
1485
+ for (const key in func) {
1486
+ Reflect.set(objectControllerMiddleware, key, Reflect.get(func, key));
1487
+ }
1488
+ return objectControllerMiddleware;
1489
+ }
1490
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWdnX2xvYWRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sb2FkZXIvZWdnX2xvYWRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDekIsT0FBTyxJQUFJLE1BQU0sV0FBVyxDQUFDO0FBQzdCLE9BQU8sTUFBTSxNQUFNLGFBQWEsQ0FBQztBQUNqQyxPQUFPLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUM5QyxPQUFPLEVBQUUsZUFBZSxFQUFFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxRQUFRLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDckYsT0FBTyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBRW5DLE9BQU8sRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLE1BQU0sU0FBUyxDQUFDO0FBQ3RELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDakMsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBUSxNQUFNLFlBQVksQ0FBQztBQUMzRSxPQUFPLEVBQUUsWUFBWSxFQUE0QixNQUFNLG1CQUFtQixDQUFDO0FBQzNFLE9BQU8sRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQXFCLE1BQU0sa0JBQWtCLENBQUM7QUFDM0UsT0FBTyxFQUFFLGFBQWEsRUFBd0IsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRSxPQUFPLEtBQWMsTUFBTSxtQkFBbUIsQ0FBQztBQUMvQyxPQUFPLFVBQVUsTUFBTSx3QkFBd0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFJNUMsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLHdCQUF3QixDQUFDLENBQUM7QUFFakQsTUFBTSxrQkFB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