Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3699562

Browse files
committedAug 3, 2016
refactor: loadFrameworkPaths -> getEggPaths
Load order has changed from `app > framework > plugin > egg` to `app > framework(contain egg) > plugin` Remove options.eggPath, egg is one of the framework. Remove options.customEgg, every framework should specify `Symbol.for('egg#eggPath')`
1 parent b7df00b commit 3699562

File tree

18 files changed

+173
-196
lines changed

18 files changed

+173
-196
lines changed
 

‎lib/base_loader.js

+68-79
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,25 @@ const isFunction = require('is-type-of').function;
77
const interopRequire = require('interop-require');
88
const debug = require('debug')('egg:loader');
99
const Loader = require('./loader');
10+
const Emitter = require('events').EventEmitter;
1011

1112
class EggLoader {
1213

1314
/**
1415
* @constructor
1516
* @param {Object} options
1617
* - {String} [baseDir] - 应用根目录
17-
* - {String} [eggPath] - 使用 egg-loader 的框架的路径,如 egg
18-
* - {String} [customEgg] - 自定义入口框架的路径,每个异构技术 bu 都可以自定义自己的插件集合
19-
* - {Object} [plugins] - 自定义插件配置,测试用
2018
* - {Object} [app] - app 实例,如果是 Agent Worker 则传入 agent 实例,可为空
19+
* - {Object} [plugins] - 自定义插件配置,测试用
2120
* - {Logger} [logger] - logger 实例,默认是 console
2221
*/
2322
constructor(options) {
24-
this.options = options || {};
23+
options = options || {};
24+
assert(fs.existsSync(options.baseDir), `${options.baseDir} not exists`);
25+
26+
this.options = options;
2527
this.options.logger = this.options.logger || console;
2628
this.app = this.options.app || {}; // master 没有 app
27-
assert(fs.existsSync(this.options.baseDir), `${this.options.baseDir} not exists`);
2829

2930
/**
3031
* 读取 package.json
@@ -33,48 +34,22 @@ class EggLoader {
3334
this.pkg = require(path.join(this.options.baseDir, 'package.json'));
3435

3536
/**
36-
* 初始化时传入,见 {@link EggLoader}
37-
* @member {String} EggLoader#eggPath
38-
*/
39-
this.eggPath = fs.realpathSync(this.options.eggPath);
40-
debug('Loaded eggPath %j', this.eggPath);
41-
42-
/**
43-
* 框架可以继承,从入口框架(CustomEgg)找到所有的框架的根目录
44-
*
45-
* 需要通过配置 getter 来指定 eggPath 才能被加载到
46-
*
47-
* ```
48-
* // lib/xx.js
49-
* const egg = require('egg');
50-
* class XxApplication extends egg.Application {
51-
* constructor(options) {
52-
* super(options);
53-
* }
54-
*
55-
* get [Symbol.for('egg#eggPath')]() {
56-
* return path.join(__dirname, '..');
57-
* }
58-
* }
59-
* ```
60-
* @member {Array} EggLoader#frameworkPaths
61-
*/
62-
this.frameworkPaths = this.loadFrameworkPaths();
63-
debug('Loaded frameworkPaths %j', this.frameworkPaths);
64-
65-
/**
66-
* = this.eggPath + this.frameworkPaths
6737
* @member {Array} EggLoader#eggPaths
38+
* @see EggLoader#getEggPaths
6839
*/
69-
this.eggPaths = [ this.eggPath ].concat(this.frameworkPaths);
40+
this.eggPaths = this.getEggPaths();
7041
debug('Loaded eggPaths %j', this.eggPaths);
7142

43+
/**
44+
* @member {String} EggLoader#serverEnv
45+
* @see EggLoader#getServerEnv
46+
*/
7247
this.serverEnv = this.getServerEnv();
7348
debug('Loaded serverEnv %j', this.serverEnv);
7449
}
7550

7651
/**
77-
* Get environment of Egg, it's not NODE_ENV
52+
* Get environment of Egg, **it's not NODE_ENV**
7853
*
7954
* 1. from `$baseDir/config/serverEnv`
8055
* 2. from EGG_SERVER_ENV
@@ -115,6 +90,53 @@ class EggLoader {
11590
return serverEnv;
11691
}
11792

93+
/**
94+
* Get all framework directories.
95+
*
96+
* You can extend Application of egg, the extrypoint is options.app,
97+
*
98+
* loader will find all directories from the prototype of Application,
99+
* you should define `Symbol.for('egg#eggPath')` property.
100+
*
101+
* ```
102+
* // lib/xx.js
103+
* const egg = require('egg');
104+
* class XxApplication extends egg.Application {
105+
* constructor(options) {
106+
* super(options);
107+
* }
108+
*
109+
* get [Symbol.for('egg#eggPath')]() {
110+
* return path.join(__dirname, '..');
111+
* }
112+
* }
113+
* ```
114+
*
115+
* @return {Array} framework directories
116+
*/
117+
getEggPaths() {
118+
const eggPaths = [];
119+
120+
let proto = this.app;
121+
while (proto) {
122+
proto = Object.getPrototypeOf(proto);
123+
if (proto) {
124+
if (isKoa(proto)) {
125+
break;
126+
}
127+
const eggPath = proto[Symbol.for('egg#eggPath')];
128+
assert(eggPath, 'Symbol.for(\'egg#eggPath\') is required on Application');
129+
// 使用 fs.realpathSync 来找到最终路径
130+
const realpath = fs.realpathSync(eggPath);
131+
if (eggPaths.indexOf(realpath) === -1) {
132+
eggPaths.unshift(realpath);
133+
}
134+
}
135+
}
136+
137+
return eggPaths;
138+
}
139+
118140
/**
119141
* 加载自定义的 app.js,**在 app.js 可做任何操作,但建议尽量减少此操作,做该做的事**。
120142
*
@@ -209,9 +231,6 @@ class EggLoader {
209231

210232
const dirs = this.dirs = [];
211233

212-
// egg 本身路径,在 lib/core 目录下
213-
dirs.push(path.join(this.eggPath, 'lib/core'));
214-
215234
// 插件目录,master 没有 plugin
216235
if (this.orderPlugins) {
217236
for (const plugin of this.orderPlugins) {
@@ -220,8 +239,8 @@ class EggLoader {
220239
}
221240

222241
// egg 框架路径,在 lib/core 目录下
223-
for (const frameworkPath of this.frameworkPaths) {
224-
dirs.push(path.join(frameworkPath, 'lib/core'));
242+
for (const eggPath of this.eggPaths) {
243+
dirs.push(path.join(eggPath, 'lib/core'));
225244
}
226245

227246
// 应用目录
@@ -231,42 +250,6 @@ class EggLoader {
231250
return dirs;
232251
}
233252

234-
235-
/**
236-
* 获取 {@link EggLoader#frameworkPaths}
237-
* @return {Array} 框架目录
238-
* @private
239-
*/
240-
loadFrameworkPaths() {
241-
const eggPath = this.eggPath;
242-
const frameworkPaths = [];
243-
244-
addEggPath(this.options.customEgg);
245-
246-
// 遍历整个原型链,获取原型链上所有的 eggPath
247-
// 越核心的优先级越高
248-
let proto = this.app;
249-
while (proto) {
250-
proto = Object.getPrototypeOf(proto);
251-
if (proto) {
252-
const eggPath = proto[Symbol.for('egg#eggPath')];
253-
addEggPath(eggPath);
254-
}
255-
}
256-
257-
return frameworkPaths;
258-
259-
function addEggPath(dirpath) {
260-
if (dirpath) {
261-
// 使用 fs.realpathSync 来找到最终路径
262-
const realpath = fs.realpathSync(dirpath);
263-
if (frameworkPaths.indexOf(realpath) === -1 && realpath !== eggPath) {
264-
frameworkPaths.unshift(realpath);
265-
}
266-
}
267-
}
268-
}
269-
270253
/**
271254
* 返回应用 appname,默认获取 pkg.name
272255
*
@@ -316,3 +299,9 @@ for (const loader of loaders) {
316299
}
317300

318301
module.exports = EggLoader;
302+
303+
function isKoa(app) {
304+
return app.hasOwnProperty('use') &&
305+
app.hasOwnProperty('listen') &&
306+
Object.getPrototypeOf(app) === Emitter.prototype;
307+
}

‎lib/loader.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,11 @@ function getProperties(filepath, lowercaseFirst) {
9393
return filepath
9494
.replace('.js', '')
9595
.split('/')
96-
.map(function(property) {
96+
.map(property => {
9797
if (!/^[a-z][a-z0-9_-]*$/i.test(property)) {
9898
throw new Error(`${property} is not match 'a-z0-9_-' in ${filepath}`);
9999
}
100-
let result = property.replace(/[_-][a-z]/ig, function(s) {
101-
return s.substring(1).toUpperCase();
102-
});
100+
let result = property.replace(/[_-][a-z]/ig, s => s.substring(1).toUpperCase());
103101
if (lowercaseFirst) {
104102
result = result[0].toLowerCase() + result.substring(1);
105103
}

‎lib/loader/config.js

Whitespace-only changes.

‎test/egg_loader.test.js

-48
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,13 @@
11
'use strict';
22

33
require('should');
4-
const path = require('path');
54
const mm = require('mm');
65
const utils = require('./utils');
7-
const BaseLoader = require('../index');
86

97
describe('test/egg_loader.test.js', function() {
108

119
afterEach(mm.restore);
1210

13-
describe('eggPaths', function() {
14-
15-
it('should get from paramter', function() {
16-
const app = utils.createApp('eggpath');
17-
app.loader.eggPath.should.equal(utils.getFilepath('egg'));
18-
});
19-
20-
it('should get from framework', function() {
21-
const Application = require('./fixtures/framework');
22-
const app = new Application();
23-
app.coreLogger = console;
24-
app.loader = new utils.Loader('eggpath', { app });
25-
app.loader.loadConfig();
26-
app.loader.eggPaths.should.eql([
27-
utils.getFilepath('egg'),
28-
utils.getFilepath('framework/node_modules/framework2'),
29-
utils.getFilepath('framework'),
30-
]);
31-
return app;
32-
});
33-
34-
it('should get from framework using symbol', function() {
35-
const Application = require('./fixtures/framework-symbol');
36-
const app = new Application();
37-
app.coreLogger = console;
38-
app.loader = new utils.Loader('eggpath', { app });
39-
app.loader.loadConfig();
40-
app.loader.eggPaths.should.eql([
41-
utils.getFilepath('egg'),
42-
utils.getFilepath('framework-symbol/node_modules/framework2'),
43-
utils.getFilepath('framework-symbol'),
44-
]);
45-
return app;
46-
});
47-
48-
it('frameworkPaths should not container eggPath', function() {
49-
const eggPath = path.join(__dirname, 'fixtures/egg');
50-
const loader = new BaseLoader({
51-
baseDir: path.join(__dirname, 'fixtures/eggpath'),
52-
eggPath,
53-
customEgg: eggPath,
54-
});
55-
loader.frameworkPaths.should.not.containEql(eggPath);
56-
});
57-
});
58-
5911

6012
describe('loadDirs', function() {
6113

‎test/fixtures/custom-app/app/router.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ module.exports = function(app) {
66
customFoo: app.customFoo,
77
env: app.config.env,
88
eggPaths: app.loader.eggPaths,
9-
frameworkPaths: app.loader.frameworkPaths,
9+
eggPaths: app.loader.eggPaths,
1010
eggPath: app.loader.eggPath,
1111
};
1212
});
+8-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
'use strict';
22

3-
module.exports = require('../../../');
4-
const startCluster = module.exports.startCluster;
3+
const KoaApplication = require('koa');
54

6-
module.exports.startCluster = function(options) {
7-
options.customEgg = __dirname;
8-
return startCluster(options);
9-
};
5+
class Application extends KoaApplication {
6+
get [Symbol.for('egg#eggPath')]() {
7+
return __dirname;
8+
}
9+
}
10+
11+
module.exports = Application;

‎test/fixtures/egg/index.js

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
'use strict';
2+
3+
const path = require('path');
4+
const KoaApplication = require('koa');
5+
6+
class EggApplication extends KoaApplication {
7+
get [Symbol.for('egg#eggPath')]() {
8+
return __dirname;
9+
}
10+
}
11+
12+
module.exports = EggApplication;

‎test/fixtures/egg/package.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"name": "egg"
3+
}

‎test/fixtures/framework/index.js

-16
This file was deleted.

‎test/fixtures/framework/lib/core/config/config.js

-5
This file was deleted.

‎test/fixtures/framework/node_modules/framework2/index.js

-16
This file was deleted.

‎test/fixtures/framework/node_modules/framework2/lib/core/config/config.js

-5
This file was deleted.

‎test/fixtures/framework/node_modules/framework2/package.json

-3
This file was deleted.

‎test/fixtures/framework/package.json

-3
This file was deleted.

0 commit comments

Comments
 (0)
Please sign in to comment.