Skip to content

Commit

Permalink
ir: port to koa@2
Browse files Browse the repository at this point in the history
  • Loading branch information
magicdawn committed Jul 12, 2016
1 parent 4413d6c commit 86be221
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 93 deletions.
4 changes: 4 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
# root
root: true

# globals
globals:
Promise: true

# code env
env:
node: true
Expand Down
51 changes: 26 additions & 25 deletions demo/app.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
'use strict';
const app = module.exports = require('koa')();
const Router = require('../lib/router');
const app = module.exports = new(require('koa'))();
const Router = require('../');
const co = require('co');
const router = Router();
const request = require('supertest');
app.use(router);

/**
* 在某一path上use middleware
*/
router.use('/public', function*() {
this.body = {
originalPath: this.originalPath,
basePath: this.basePath,
path: this.path
router.use('/public', function(ctx, next) {
ctx.body = {
originalPath: ctx.originalPath,
basePath: ctx.basePath,
path: ctx.path
};
});

/**
* simple route
*/
router.get('/hello', function*() {
this.body = 'world';
router.get('/hello', function(ctx, next) {
ctx.body = 'world';
});

/**
* nested router test
*/
const fn = function*(next) {
console.log('basePath: %s, path: %s', this.basePath, this.path);
yield next;
};
const fn = co.wrap(function*(ctx, next) {
console.log('basePath: %s, path: %s', ctx.basePath, ctx.path);
yield next();
});

const routerA = Router();
const routerB = Router();
Expand All @@ -38,21 +39,21 @@ const routerC = Router();
router.use('/a', fn, routerA);
routerA.use('/b', fn, routerB);
routerB.use('/c', fn, routerC);
routerC.get('/', function*() {
routerC.get('/', function(ctx, next) {
console.log('calling ');
this.body = {
path: this.path,
basePath: this.basePath,
originalPath: this.originalPath
ctx.body = {
path: ctx.path,
basePath: ctx.basePath,
originalPath: ctx.originalPath
};
});

/**
* param
*/
router.get('/user/:id/detail', function*(next) {
this.body = {
id: this.params.id
router.get('/user/:id/detail', function(ctx, next) {
ctx.body = {
id: ctx.params.id
};
});

Expand All @@ -63,9 +64,9 @@ const routerUser = Router({
mergeParams: true
});
router.use('/user/:id', routerUser);
routerUser.get('/detail/:field', function*() {
this.body = {
id: this.params.id,
field: this.params.field
routerUser.get('/:field', function(ctx, next) {
ctx.body = {
id: ctx.params.id,
field: ctx.params.field
};
});
2 changes: 1 addition & 1 deletion demo/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ request(server)
* nested params
*/
request(server)
.get('/user/magicdawn/detail/age')
.get('/user/magicdawn/age')
.end(function(err, res) {
console.log(res.body);
});
25 changes: 13 additions & 12 deletions lib/route.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
const METHODS = require('methods');
const compose = require('koa-compose');
const debug = require('debug')('impress:route');
const co = require('co');

/**
* exports
Expand Down Expand Up @@ -62,14 +63,14 @@ METHODS.concat('all').forEach(function(method) {
let fn;

// check
const msg = 'route.' + method + ' requires generator function';
const msg = 'route.' + method + ' requires function';
if (!fns.length) {
throw new Error(msg);
}

// ensure GeneratorFunction
// ensure function
fns.forEach(function(fn) {
if (!fn || typeof fn !== 'function' || fn.constructor.name !== 'GeneratorFunction') {
if (!fn || typeof fn !== 'function') {
throw new Error(msg);
}
});
Expand Down Expand Up @@ -99,7 +100,7 @@ METHODS.concat('all').forEach(function(method) {
* @param {generatoe} next
* @param {Object} ctx
*/
Route.prototype.dispatch = function*(next, ctx) {
Route.prototype.dispatch = co.wrap(function*(ctx, next) {
const route = this;
debug('dispatch on route : %s', ctx.path);

Expand All @@ -112,11 +113,9 @@ Route.prototype.dispatch = function*(next, ctx) {
method = 'get';
}

yield * findNext();

function* findNext() {
const findNext = co.wrap(function*() {
if (idx === stack.length) {
yield * next; // end of route, find next route
yield next(); // end of route, find next route
return;
}

Expand All @@ -130,7 +129,7 @@ Route.prototype.dispatch = function*(next, ctx) {

// end Route
if (idx === stack.length) {
yield * next; // end of route, find next route
yield next(); // end of route, find next route
return;
} else {
continue;
Expand All @@ -140,6 +139,8 @@ Route.prototype.dispatch = function*(next, ctx) {

// call the layer, make sure layer.fn(next) next as a generator
// then find_next
yield * layer.fn.call(ctx, findNext(), ctx);
}
};
yield Promise.resolve(layer.fn(ctx, findNext));
});

yield findNext();
});
89 changes: 39 additions & 50 deletions lib/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ const METHODS = require('methods');
const compose = require('koa-compose');
const debug = require('debug')('impress:router');
const _ = require('lodash');
const co = require('co');

/**
* expose `Router` & `Router.prototype`
*/
const proto = module.exports = function Router(options) {

// router definition
// add an `impressRouter` name
const router = function* impressRouter(next) {
yield * router.dispatch(this);
const router = co.wrap(function* impressRouter(ctx, next) {
yield router.dispatch(ctx);
if (router.options.goNext) {
yield * next;
yield next();
}
};
});

// router options
router.options = _.merge({
Expand All @@ -32,14 +32,10 @@ const proto = module.exports = function Router(options) {
mergeParams: true
}, options);

// keep constructor `GeneratorFunction` reference
const GenFn = router.constructor;

// setup proto
// keep constructor reference
const Con = router.constructor;
router.__proto__ = proto;

// restore constructor,or koa will raise error
router.constructor = GenFn;
router.constructor = Con;

// initialize
router.init();
Expand All @@ -55,21 +51,21 @@ proto.init = function() {
this.stack = [];

// build automatic `options` response
router.use(function* allowedMethods(next) {
if (this.method === 'OPTIONS') {
if (!this.allowedMethods) {
this.allowedMethods = []; // attcch `allowedMethods` on context
router.use(co.wrap(function* allowedMethods(ctx, next) {
if (ctx.method === 'OPTIONS') {
if (!ctx.allowedMethods) {
ctx.allowedMethods = []; // attcch `allowedMethods` on context
}
}

yield * next;
yield next();

if (this.method === 'OPTIONS' && this.allowedMethods.length) {
const allow = this.allowedMethods.join(',');
this.set('Allow', allow);
this.body = allow;
if (ctx.method === 'OPTIONS' && ctx.allowedMethods.length) {
const allow = ctx.allowedMethods.join(',');
ctx.set('Allow', allow);
ctx.body = allow;
}
});
}));

return this;
};
Expand All @@ -79,7 +75,7 @@ proto.init = function() {
*
* ctx : koa app's request & response context
*/
proto.dispatch = function*(ctx) {
proto.dispatch = co.wrap(function*(ctx) {
const router = this;
let index = 0;

Expand All @@ -93,21 +89,13 @@ proto.dispatch = function*(ctx) {
const baseParams = ctx.params || (ctx.params = {}); // params
const path = ctx.path; // path

yield * findNext();

// restore reference at end of `Router#dispatch`
ctx.basePath = basePath; // basePath
ctx.params = baseParams; // params
ctx.path = path; // path

function* findNext() {
let layer;

const findNext = co.wrap(function*() {
// no more layer
if (index === router.stack.length) {
return;
}

let layer;
while (index < router.stack.length) {
layer = router.stack[index++];

Expand Down Expand Up @@ -158,26 +146,27 @@ proto.dispatch = function*(ctx) {
ctx.params = layer.params;
}

// traverse the layer
// gen = next(), make sure we pass a generator, not a GeneratorFunction
// because
// - yield* gen : ok
// - yield* GenFn: error
//
// then restore & find_next
yield * layer.fn.call(ctx, next(), ctx);

function* next() {
// then restore & findNext
const routerNext = co.wrap(function*() {
// restore
ctx.path = pathBeforeLayer;
ctx.basePath = basePath;
ctx.params = baseParams;

// find the next
yield * findNext();
}
}
};
// findNext
yield findNext();
});

yield Promise.resolve(layer.fn(ctx, routerNext));
});

yield findNext();

// restore reference at end of `Router#dispatch`
ctx.basePath = basePath; // basePath
ctx.params = baseParams; // params
ctx.path = path; // path
});

/**
* use a middleware
Expand All @@ -195,12 +184,12 @@ proto.use = function(path) {
}

// check
const msg = 'router.use([path],fn) : fn expected to be GeneratorFunction';
const msg = 'router.use([path],fn) : fn expected to be a function';
if (!fns.length) throw new Error(msg);

// ensure GeneratorFunction
fns.forEach(function(m) {
if (!m || typeof m !== 'function' || m.constructor.name !== 'GeneratorFunction') {
if (!m || typeof m !== 'function') {
throw new Error(msg);
}
});
Expand Down
11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@
"description": "port Express router to koa",
"main": "lib/router.js",
"dependencies": {
"co": "^4.6.0",
"debug": "^2.2.0",
"koa-compose": "^2.4.0",
"lodash": "^4.6.1",
"koa-compose": "^3.1.0",
"lodash": "^4.13.1",
"methods": "^1.1.2",
"path-to-regexp": "1.2.x"
},
"devDependencies": {
"coveralls": "^2.11.8",
"eslint": "^2.3.0",
"istanbul-harmony": "^0.3.16",
"koa": "^1.2.0",
"mocha": "^2.4.5",
"koa": "^2.0.0",
"mocha": "^2.5.3",
"should": "^8.2.2",
"supertest": "^1.2.0"
},
Expand Down Expand Up @@ -47,4 +48,4 @@
"engines": {
"node": ">=4"
}
}
}

0 comments on commit 86be221

Please sign in to comment.