code: function controllerWrap(ctx, ctrl, hooks, next) {
    let result
    const preHooks = []
    hooks.pre.map(pre => {
      preHooks.push(() => pre(ctx))
    })
  
    return sequenceAndReturnOne(preHooks)
      .then(() => {
        return ctrl(ctx)
      })
      .then(data => {
        if (!data && ctx.body && ctx.body.data) {
          data = ctx.body.data
        }
        result = data
        const postHooks = []
        hooks.post.map(post => {
          // Use pre action's result for next action's data
          postHooks.push(preResult => post(ctx, preResult || result))
        })
        return sequenceAndReturnOne(postHooks)
      })
      .then(ret => {
        if (!ctx.body) {
          ctx.body = {
            code: 0,
            data: ret || result
          }
        }
        next && next()
      })
      .catch(err => {
        // throw errors to app error handler
        throw err
      })
  }
docs: controller wrap
  wrap controllers for router
  
  @param {object} ctx context
  @param {function} ctrl controller function
  @param {object} hooks controller hook functions
  @param {function} next koa router next function
  @returns