README
shan
koa with Promise-based middleware
Installation
$ npm install shan
Usage
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)
.
ctx
is just instance of KoaContext.next
contains info about next middleware. To invoke next middleware, just callnext(ctx)
. It will return aPromise<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