From 1d58b7c83ec743a9aa7c3d5a28efafef714af342 Mon Sep 17 00:00:00 2001 From: gyson Date: Fri, 6 Nov 2015 10:26:04 -0500 Subject: [PATCH] add convert.back() --- index.js | 37 ++++++++++++++++++++++++++++------- package.json | 1 + test.js | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index aba6a0e..1b60b0a 100644 --- a/index.js +++ b/index.js @@ -9,14 +9,17 @@ function convert (mw) { if (typeof mw !== 'function') { throw new TypeError('middleware must be a function') } - if (mw.constructor.name === 'GeneratorFunction') { - return function (ctx, next) { - return co.call(ctx, mw.call(ctx, createGenerator(next))) - } - } else { + if (mw.constructor.name !== 'GeneratorFunction') { // assume it's Promise-based middleware return mw } + return function (ctx, next) { + return co.call(ctx, mw.call(ctx, createGenerator(next))) + } +} + +function * createGenerator (next) { + return yield next() } // convert.compose(mw, mw, mw) @@ -28,6 +31,26 @@ convert.compose = function (arr) { return compose(arr.map(convert)) } -function * createGenerator (next) { - return yield next() +convert.back = function (mw) { + if (typeof mw !== 'function') { + throw new TypeError('middleware must be a function') + } + if (mw.constructor.name === 'GeneratorFunction') { + // assume it's generator middleware + return mw + } + return function * (next) { + let ctx = this + let called = false + // no need try...catch here, it's ok even `mw()` throw exception + yield Promise.resolve(mw(ctx, function () { + if (called) { + // guard against multiple next() calls + // https://github.com/koajs/compose/blob/4e3e96baf58b817d71bd44a8c0d78bb42623aa95/index.js#L36 + return Promise.reject(new Error('next() called multiple times')) + } + called = true + return co.call(ctx, next) + })) + } } diff --git a/package.json b/package.json index 7e1dcf9..b321870 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ }, "devDependencies": { "koa": "^2.0.0-alpha.2", + "koa-v1": "^1.0.0", "mocha": "^2.3.3", "standard": "^5.3.1", "supertest": "^1.1.0" diff --git a/test.js b/test.js index 6d5d34e..ca0b797 100644 --- a/test.js +++ b/test.js @@ -4,6 +4,7 @@ const co = require('co') const Koa = require('koa') +const KoaV1 = require('koa-v1') const assert = require('assert') const convert = require('./index') const request = require('supertest') @@ -143,6 +144,60 @@ describe('convert.compose()', () => { }) }) +describe('convert.back()', () => { + it('should work with koa 1', done => { + let app = new KoaV1() + + app.use(function * (next) { + this.body = [1] + yield next + this.body.push(6) + }) + + app.use(convert.back((ctx, next) => { + ctx.body.push(2) + return next().then(() => { + ctx.body.push(5) + }) + })) + + app.use(convert.back(co.wrap(function * (ctx, next) { + ctx.body.push(3) + yield next() + ctx.body.push(4) + }))) + + request(app.callback()) + .get('/') + .expect(200, [1, 2, 3, 4, 5, 6]) + .end(done) + }) + + it('should guard multiple calls', done => { + let app = new KoaV1() + + app.use(function * (next) { + try { + this.body = [1] + yield next + } catch (e) { + this.body.push(e.message) + } + }) + + app.use(convert.back(co.wrap(function * (ctx, next) { + ctx.body.push(2) + yield next() + yield next() // this should throw new Error('next() called multiple times') + }))) + + request(app.callback()) + .get('/') + .expect(200, [1, 2, 'next() called multiple times']) + .end(done) + }) +}) + describe('migration snippet', () => { let app = new Koa()