-
Notifications
You must be signed in to change notification settings - Fork 91
refactor: implement Loader instead of loading #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,135 @@ | ||
| 'use strict'; | ||
|
|
||
| const assert = require('assert'); | ||
| const fs = require('fs'); | ||
| const debug = require('debug')('egg-loader:loader'); | ||
| const path = require('path'); | ||
| const globby = require('globby'); | ||
| const interopRequire = require('interop-require'); | ||
| const is = require('is-type-of'); | ||
| const FULLPATH = Symbol('EGG_LOADER_ITEM_FULLPATH'); | ||
|
|
||
| const defaults = { | ||
| directory: null, | ||
| target: null, | ||
| ignore: undefined, | ||
| lowercaseFirst: false, | ||
| initializer: null, | ||
| call: true, | ||
| override: false, | ||
| inject: undefined, | ||
| }; | ||
|
|
||
| class Loader { | ||
|
|
||
| constructor(options) { | ||
| assert(options.directory, 'options.directory is required'); | ||
| assert(options.target, 'options.target is required'); | ||
| this.options = Object.assign({}, defaults, options); | ||
| } | ||
|
|
||
| load() { | ||
| const items = this.parse(); | ||
| const target = this.options.target; | ||
| for (const item of items) { | ||
| debug('loading item %j', item); | ||
| item.properties.reduce((target, property, index) => { | ||
| let obj; | ||
| const properties = item.properties.slice(0, index + 1).join('.'); | ||
| if (index === item.properties.length - 1) { | ||
| if (property in target) { | ||
| if (!this.options.override) throw new Error(`can't overwrite property '${properties}' from ${target[property][FULLPATH]} by ${item.fullpath}`); | ||
| } | ||
| obj = item.exports; | ||
| if (obj) obj[FULLPATH] = item.fullpath; | ||
| } else { | ||
| obj = target[property] || {}; | ||
| } | ||
| target[property] = obj; | ||
| debug('loaded %s', properties); | ||
| return obj; | ||
| }, target); | ||
| } | ||
| return target; | ||
| } | ||
|
|
||
| parse() { | ||
| const files = [ '**/*.js' ]; | ||
| if (typeof this.options.ignore === 'string') { | ||
| files.push('!' + this.options.ignore); | ||
| } | ||
|
|
||
| let directories = this.options.directory; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 可以直接
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 不是一个意思吧,directory 如果非数组会有问题吧。 |
||
| if (!Array.isArray(directories)) { | ||
| directories = [ directories ]; | ||
| } | ||
|
|
||
| const items = []; | ||
| debug('parsing %j', directories); | ||
| for (const directory of directories) { | ||
| const filepaths = globby.sync(files, { cwd: directory }); | ||
| for (const filepath of filepaths) { | ||
| const fullpath = path.join(directory, filepath); | ||
| if (!fs.statSync(fullpath).isFile()) { | ||
| continue; | ||
| } | ||
| const properties = getProperties(filepath, this.options.lowercaseFirst); | ||
| const exports = getExports(fullpath, this.options.initializer, this.options.call, this.options.inject); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里的 exports 和 config 那里是不是换个变量名,毕竟和 commonjs 的 exports 全局变量同名了,万一不小心~
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这里应该不影响吧,作用域关系
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 是不影响, 只是个人习惯不喜欢变量名覆盖, 一不小心就~
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. es6 完全没有这个问题。 |
||
| if (exports == null) continue; | ||
| items.push({ fullpath, properties, exports }); | ||
| debug('parse %s, properties %j, export %j', fullpath, properties, exports); | ||
| } | ||
| } | ||
|
|
||
| return items; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| module.exports = Loader; | ||
|
|
||
| // a/b/c.js => ['a', 'b', 'c'] | ||
| function getProperties(filepath, lowercaseFirst) { | ||
| return filepath | ||
| .replace('.js', '') | ||
| .split('/') | ||
| .map(function(property) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| if (!/^[a-z][a-z0-9_-]*$/i.test(property)) { | ||
| throw new Error(`${property} is not match 'a-z0-9_-' in ${filepath}`); | ||
| } | ||
| let result = property.replace(/[_-][a-z]/ig, function(s) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. const result
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个应该是 let |
||
| return s.substring(1).toUpperCase(); | ||
| }); | ||
| if (lowercaseFirst) { | ||
| result = result[0].toLowerCase() + result.substring(1); | ||
| } | ||
| return result; | ||
| }); | ||
| } | ||
|
|
||
| function getExports(fullpath, initializer, isCall, inject) { | ||
| let exports; | ||
| try { | ||
| exports = interopRequire(fullpath); | ||
| } catch (err) { | ||
| err.message = 'load file: ' + fullpath + ', error: ' + err.message; | ||
| throw err; | ||
| } | ||
|
|
||
| if (initializer) { | ||
| exports = initializer(exports); | ||
| } | ||
|
|
||
| if (is.class(exports) || is.generatorFunction(exports)) { | ||
| return exports; | ||
| } | ||
|
|
||
| if (isCall && is.function(exports)) { | ||
| exports = exports(inject); | ||
| if (exports != null) { | ||
| return exports; | ||
| } | ||
| } | ||
|
|
||
| return exports; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,6 @@ | ||
| 'use strict'; | ||
|
|
||
| const join = require('path').join; | ||
| const loading = require('loading'); | ||
| const classLoader = Symbol('classLoader'); | ||
| const utils = require('./utils'); | ||
|
|
||
|
|
@@ -21,8 +20,7 @@ module.exports = { | |
| opt = Object.assign({ call: true, lowercaseFirst: true }, opt); | ||
| const arr = this.loadDirs().map(dir => join(dir, 'app/proxy')); | ||
| // load proxy classes to app.proxyClasses | ||
| delete app.proxyClasses; | ||
| loading(arr, opt).into(app, 'proxyClasses'); | ||
| this.loadToApp(arr, 'proxyClasses', opt); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这样 proxy 就支持多级了?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这个还不支持,这里只是切换 loading
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 喔, 手机上不方便看, 看到 service 和 proxy 貌似现在 loader 差不多. |
||
|
|
||
| // this.proxy.demoQuery.getUser(uid) | ||
| Object.defineProperty(app.context, 'proxy', { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| 'use strict'; | ||
|
|
||
| var _temporalUndefined = {}; | ||
|
|
||
| var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
|
|
||
| var UserProxy = _temporalUndefined; | ||
|
|
||
| function _temporalAssertDefined(val, name, undef) { if (val === undef) { throw new ReferenceError(name + ' is not defined - temporal dead zone'); } return true; } | ||
|
|
||
| function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
|
|
||
| UserProxy = (function () { | ||
| function UserProxy() { | ||
| _classCallCheck(this, _temporalAssertDefined(UserProxy, 'UserProxy', _temporalUndefined) && UserProxy); | ||
|
|
||
| this.user = { | ||
| name: 'xiaochen.gaoxc' | ||
| }; | ||
| } | ||
|
|
||
| _createClass(_temporalAssertDefined(UserProxy, 'UserProxy', _temporalUndefined) && UserProxy, [{ | ||
| key: 'getUser', | ||
| value: function getUser() { | ||
| return this.user; | ||
| } | ||
| }]); | ||
|
|
||
| return _temporalAssertDefined(UserProxy, 'UserProxy', _temporalUndefined) && UserProxy; | ||
| })(); | ||
|
|
||
| module.exports = _temporalAssertDefined(UserProxy, 'UserProxy', _temporalUndefined) && UserProxy; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| 'use strict'; | ||
|
|
||
| class UserProxy { | ||
| constructor() { | ||
| this.user = { | ||
| name: 'xiaochen.gaoxc', | ||
| }; | ||
| } | ||
|
|
||
| getUser() { | ||
| return this.user; | ||
| } | ||
| } | ||
|
|
||
| module.exports = UserProxy; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| 'use strict'; | ||
|
|
||
| module.exports = class TestClass { | ||
| constructor() { | ||
| this.user = { | ||
| name: 'kai.fangk', | ||
| }; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| 'use strict'; | ||
|
|
||
| module.exports = function(obj) { | ||
| return { | ||
| user: { | ||
| name: 'kai.fangk', | ||
| }, | ||
| }; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| 'use strict'; | ||
|
|
||
| module.exports = function(obj) { | ||
| return function() { | ||
| return { | ||
| user: { | ||
| name: 'kai.fangk', | ||
| }, | ||
| } | ||
| }; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| 'use strict'; | ||
|
|
||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.default = function() { | ||
| return { a: 1 }; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| module.exports = function() { | ||
| return { a: 1 }; | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| module.exports = { | ||
| method1: function() { | ||
| } | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| module.exports = { b: 2 }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| exports.getByName = function (name, callback) { | ||
| setTimeout(function () { | ||
| callback(null, {name: name}); | ||
| }, 1); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| exports.getByName = function (name, callback) { | ||
| setTimeout(function () { | ||
| callback(null, {name: name}); | ||
| }, 1); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| module.exports = function () {}; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| module.exports = function () {}; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| module.exports = function () {}; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| module.exports = function () {}; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| module.exports = function () {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
missing name from package.json ?