Comparing version 1.8.0 to 2.0.0
2.0.0 / 2017-02-10 | ||
================== | ||
* feat: [BREAKING_CHANGE] can get error from .ready() (#53) | ||
* fix: make sure close once (#51) | ||
* feat: imporve error message of async controller (#52) | ||
* deps: remove unuse devDeps (#49) | ||
* feat: [BREAKING_CHANGE] all middleware support async function and common function (#50) | ||
1.8.0 / 2017-02-06 | ||
@@ -3,0 +12,0 @@ ================== |
@@ -17,2 +17,3 @@ 'use strict'; | ||
const ISCLOSE = Symbol('EggCore#isClose'); | ||
const CLOSE_PROMISE = Symbol('EggCore#closePromise'); | ||
@@ -83,2 +84,16 @@ class EggCore extends KoaApplication { | ||
/** | ||
* override koa's app.use | ||
* support async function | ||
* @param {Function} fn middleware | ||
* @return {Application} app | ||
* @since 1.0.0 | ||
*/ | ||
use(fn) { | ||
assert(is.function(fn), 'app.use() requires a function'); | ||
debug('use %s', fn._name || fn.name || '-'); | ||
this.middleware.push(utils.middleware(fn)); | ||
return this; | ||
} | ||
/** | ||
* alias to options.type | ||
@@ -164,3 +179,9 @@ * @member {String} | ||
/** | ||
* close all listeners | ||
* close all, it wil close | ||
* - callbacks registered by beforeClose | ||
* - emit `close` event | ||
* - remove add listeners | ||
* | ||
* If error is thrown when it's closing, the promise will reject. | ||
* It will also reject after following call. | ||
* @member {Function} | ||
@@ -171,11 +192,13 @@ * @return {Promise} promise | ||
close() { | ||
return co(function* () { | ||
if (this[ISCLOSE] === true) return; | ||
if (this[CLOSE_PROMISE]) return this[CLOSE_PROMISE]; | ||
this[CLOSE_PROMISE] = co(function* closeFunction() { | ||
// close in reverse order: first created, last closed | ||
const closeFns = Array.from(this[CLOSESET]); | ||
for (let i = closeFns.length - 1; i >= 0; i--) { | ||
yield utils.callFn(closeFns[i]); | ||
for (const fn of closeFns.reverse()) { | ||
yield utils.callFn(fn); | ||
this[CLOSESET].delete(fn); | ||
} | ||
// Be called after other close callbacks | ||
this.emit('close'); | ||
@@ -185,2 +208,3 @@ this.removeAllListeners(); | ||
}.bind(this)); | ||
return this[CLOSE_PROMISE]; | ||
} | ||
@@ -187,0 +211,0 @@ |
@@ -28,2 +28,7 @@ 'use strict'; | ||
} | ||
if (is.promise(obj)) { | ||
// module.exports = async ctx => ctx.body = 'hello'; | ||
const displayPath = path.relative(this.app.baseDir, opt.path); | ||
throw new Error(`${displayPath} cannot be async function`); | ||
} | ||
if (is.class(obj)) { | ||
@@ -30,0 +35,0 @@ obj.prototype.pathName = utils.getPathName(opt.path, this.app); |
@@ -5,5 +5,7 @@ 'use strict'; | ||
const is = require('is-type-of'); | ||
const inspect = require('util').inspect; | ||
const assert = require('assert'); | ||
const debug = require('debug')('egg-core:middleware'); | ||
const inspect = require('util').inspect; | ||
const pathMatching = require('egg-path-matching'); | ||
const utils = require('../../utils'); | ||
@@ -62,5 +64,3 @@ module.exports = { | ||
mw = mw(options, app); | ||
if (!is.generatorFunction(mw)) { | ||
throw new TypeError(`Middleware ${name} must be a generator function, but actual is ${inspect(mw)}`); | ||
} | ||
assert(is.function(mw), `Middleware ${name} must be a function, but actual is ${inspect(mw)}`); | ||
mw._name = name; | ||
@@ -84,6 +84,12 @@ // middlewares support options.enable, options.ignore and options.match | ||
function wrapMiddleware(mw, options) { | ||
// support options.enable | ||
if (options.enable === false) return null; | ||
// support async function | ||
mw = utils.middleware(mw); | ||
// support options.match and options.ignore | ||
if (!options.match && !options.ignore) return mw; | ||
const match = pathMatching(options); | ||
const match = pathMatching(options); | ||
const fn = function* (next) { | ||
@@ -90,0 +96,0 @@ if (!match(this)) return yield next; |
'use strict'; | ||
const co = require('co'); | ||
const path = require('path'); | ||
@@ -60,2 +61,12 @@ const interopRequire = require('interop-require'); | ||
}, | ||
middleware(fn) { | ||
if (is.generatorFunction(fn)) return fn; | ||
// support async function | ||
return function* (next) { | ||
// next is a generator | ||
yield module.exports.callFn(fn, [ this, () => co(next) ]); | ||
}; | ||
}, | ||
}; |
'use strict'; | ||
const is = require('is-type-of'); | ||
const KoaRouter = require('koa-router'); | ||
@@ -7,2 +8,3 @@ const utility = require('utility'); | ||
const methods = require('./index').methods; | ||
const utils = require('./index'); | ||
@@ -60,22 +62,34 @@ const REST_MAP = { | ||
super(opts); | ||
this.app = app; | ||
// patch koa-router@5.x | ||
this.patchRouter(app); | ||
} | ||
// patch koa-router@5.x | ||
patchRouter(app) { | ||
const router = this; | ||
app.url = this.url.bind(this); | ||
app.router = this; | ||
router.app = app; | ||
app.url = router.url.bind(router); | ||
app.router = router; | ||
// regist router by http method. | ||
methods.concat([ 'all', 'del', 'resources', 'register' ]).forEach(method => { | ||
app[method] = function() { | ||
const args = formatRouterArguments(app, arguments); | ||
router[method].apply(router, args); | ||
return this; | ||
// patch router methods to support async function middleware and string controller | ||
methods.concat([ 'all', 'del', 'resources' ]).forEach(method => { | ||
const orignalMethod = router[method].bind(router); | ||
router[method] = function(...args) { | ||
const splited = splitedRouterParams(args); | ||
args = splited.prefix.concat(convertMiddlewares(splited.middlewares, app)); | ||
return orignalMethod(...args); | ||
}; | ||
}); | ||
// other methods | ||
[ 'redirect', 'param' ].forEach(method => { | ||
app[method] = function() { | ||
router[method].apply(router, arguments); | ||
// patch register to support async function middleware and string controller | ||
const register = router.register.bind(router); | ||
router.register = function(path, methods, middlewares, opts) { | ||
middlewares = Array.isArray(middlewares) ? middlewares : [ middlewares ]; | ||
middlewares = convertMiddlewares(middlewares, app); | ||
return register(path, methods, middlewares, opts); | ||
}; | ||
// delegate | ||
methods.concat([ 'all', 'del', 'resources', 'register', 'redirect' ]).forEach(method => { | ||
app[method] = function(...args) { | ||
router[method](...args); | ||
return this; | ||
@@ -232,3 +246,28 @@ }; | ||
/** | ||
* controller(last argument) support string | ||
* split (name, url, ...middleware, controller) to | ||
* { | ||
* prefix: [name, url] | ||
* middlewares [...middleware, controller] | ||
* } | ||
* | ||
* @param {Array} args router params | ||
* @return {Object} prefix and middlewares | ||
*/ | ||
function splitedRouterParams(args) { | ||
let prefix; | ||
let middlewares; | ||
if (args.length >= 3 && is.string(args[1])) { | ||
// app.get(name, url, [...middleware], controller) | ||
prefix = args.slice(0, 2); | ||
middlewares = args.slice(2); | ||
} else { | ||
// app.get(url, [...middleware], controller) | ||
prefix = args.slice(0, 1); | ||
middlewares = args.slice(1); | ||
} | ||
return { prefix, middlewares }; | ||
} | ||
/** | ||
* 1. make controller(last argument) support string | ||
* - [url, controller]: app.get('/home', 'home'); | ||
@@ -240,18 +279,27 @@ * - [name, url, controller(string)]: app.get('posts', '/posts', 'posts.list'); | ||
* | ||
* 2. make middleware support async function | ||
* | ||
* @param {Array} middlewares middlewares and controller(last middleware) | ||
* @param {Application} app egg application instance | ||
* @param {arguments} args egg router arguments | ||
* @return {Array} koa-router arguments | ||
* @return {Array} middlewares | ||
*/ | ||
function formatRouterArguments(app, args) { | ||
const controller = args[args.length - 1]; | ||
if (typeof controller !== 'string') return args; | ||
const actions = controller.split('.'); | ||
let obj = app.controller; | ||
actions.forEach(key => { | ||
obj = obj[key]; | ||
if (!obj) throw new Error(`controller '${controller}' not exists`); | ||
}); | ||
return Array.prototype.slice.call(args, 0, -1).concat([ obj ]); | ||
function convertMiddlewares(middlewares, app) { | ||
let controller = middlewares.pop(); | ||
// make middleware support async function | ||
middlewares = middlewares.map(utils.middleware); | ||
// make controller(last argument) support string | ||
if (is.string(controller)) { | ||
const actions = controller.split('.'); | ||
let obj = app.controller; | ||
actions.forEach(key => { | ||
obj = obj[key]; | ||
if (!obj) throw new Error(`controller '${controller}' not exists`); | ||
}); | ||
controller = obj; | ||
} | ||
return middlewares.concat([ controller ]); | ||
} | ||
module.exports = Router; |
{ | ||
"name": "egg-core", | ||
"version": "1.8.0", | ||
"version": "2.0.0", | ||
"description": "A core Pluggable framework based on koa", | ||
@@ -36,16 +36,16 @@ "main": "index.js", | ||
"autod": "^2.7.1", | ||
"egg-bin": "1", | ||
"egg-ci": "1", | ||
"eslint": "3", | ||
"eslint-config-egg": "3", | ||
"koa": "1", | ||
"koa-router": "4", | ||
"mm": "^2.0.0", | ||
"egg-bin": "^2.0.2", | ||
"egg-ci": "^1.1.0", | ||
"eslint": "^3.15.0", | ||
"eslint-config-egg": "^3.2.0", | ||
"mm": "^2.1.0", | ||
"mz-modules": "^1.0.0", | ||
"pedding": "^1.1.0", | ||
"rimraf": "^2.5.4", | ||
"supertest": "^2.0.1" | ||
"spy": "^1.0.0", | ||
"supertest": "^3.0.0" | ||
}, | ||
"dependencies": { | ||
"co": "^4.6.0", | ||
"debug": "^2.5.2", | ||
"debug": "^2.6.0", | ||
"depd": "^1.1.0", | ||
@@ -56,3 +56,3 @@ "egg-logger": "^1.5.0", | ||
"globby": "^6.1.0", | ||
"inflection": "^1.10.0", | ||
"inflection": "^1.12.0", | ||
"interop-require": "^1.0.0", | ||
@@ -63,3 +63,3 @@ "is-type-of": "^1.0.0", | ||
"node-homedir": "^1.0.0", | ||
"ready-callback": "^1.0.0", | ||
"ready-callback": "^2.0.0", | ||
"utility": "^1.9.0" | ||
@@ -66,0 +66,0 @@ }, |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
70872
1879
+ Addedget-ready@2.0.1(transitive)
+ Addedready-callback@2.1.0(transitive)
+ Addeduuid@3.4.0(transitive)
- Removeddebug@2.2.0(transitive)
- Removedget-ready@1.0.0(transitive)
- Removedms@0.7.1(transitive)
- Removedonce@1.3.3(transitive)
- Removedready-callback@1.0.0(transitive)
- Removeduuid@2.0.3(transitive)
Updateddebug@^2.6.0
Updatedinflection@^1.12.0
Updatedready-callback@^2.0.0