shan v0.0.5
shan
koa with Promise-based middleware
Installation
$ npm install shanUsage
You may need babel-node to run following code (for async arrow function).
const shan = require('shan')
const favicon = require('koa-favicon')
let app = shan()
app.useKoa(favicon())
app.use(async (ctx, next) => {
    let start = Date.now()
    await next(ctx)
    ctx.response.set('X-Response-Time', (Date.now() - start) + 'ms')
})
app.use(ctx => {
    ctx.response.body = 'hello'
})
app.listen(4321)About
This is an application inherits from koa but override app.use to accept promise-based middleware instead of generator-based middleware.
Promise-based Middleware
Promise-based middleware is a function with two arguments, ctx and next, and return a any or Promise<any>.
If any is returned, it will be wrapped to Promise using Promise.resolve(value). If there is any exception, the
error will be wrapped to Promise using Promise.reject(error).
- ctxis just instance of KoaContext.
- nextcontains info about next middleware. To invoke next middleware, just call- next(ctx). It will return a- Promise<any>result from next middleware.
// ctx: KoaContext
// next: (KoaContext) => Promise<any>
app.use((ctx, next) => {
    console.log(1)
    return next(ctx).then(() => {
        console.log(8)
    })
})
// use async arrow function, may need help from babel
app.use(async (ctx, next) => {
    console.log(2)
    await next(ctx)
    console.log(7)
})
// use co
app.use(co.wrap(function* (ctx, next) {
    console.log(3)
    yield next(ctx)
    console.log(6)
}))
// use bluebird
app.use(Bluebird.coroutine(function* (ctx, next) {
    console.log(4)
    yield next(ctx)
    console.log(5)
}))Utility Middleware
A few utility middleware are included for convenience.
Koa Converter Middleware
Convert koa generator-based middleware to promise-based middleware.
You can use any generator-based middleware from koa ecosystem.
app.useKoa(require('koa-favicon')())
app.useKoa(function* (next) {
    // ...
    yield next
})Logger Middleware
Print request message to console when it flows through.
app.useLogger(ctx => `> ${ctx.method} ${ctx.path}`)
// it's equivalent to
app.use((ctx, next) => {
    console.log(`> ${ctx.method} ${ctx.path}`)
    return next(ctx)
})Router Middleware
Simple router with fluent interface.
app.useRouter(it => it
    .get('/', (ctx, next) => {
    })
    .post('/signup', (ctx, next) => {
    })
    .all('/repos/:id', (ctx, next) => {
    })
    .route('/users/:id', {
        get: (ctx, next) => {
        },
        post: (ctx, next) => {
        },
        delete: (ctx, next) => {
        }
    })
)Tracer Middleware
Profiling time spent within in one or multiple middleware.
app.useTracer('name1')
app.use(async (ctx, next) => {
    await sleep(100)
    await next(ctx)
    await sleep(400)
})
app.useTracer('name2')
app.use(async (ctx, next) => {
    await sleep(200)
    await next(ctx)
    await sleep(300)
})
app.useTracer('name3')It will provide info like following:
name1 | +0           |     +403.419
name2 |   +102.017   |   +305.734  
name3 |     +202.964 | +0.449     Try Middleware
Shortcut for try...catch...finally.
app.useTry({
    catch(ctx, err) {
        // catch block
    },
    finally(ctx) {
        // finally block
    }
})
// it's equivalent to
app.use(async (ctx, next) => {
    try {
        await next(ctx)
    }
    catch (err) {
        // catch block
    }
    finally {
        // finally block
    }
})License
MIT