koa2: How to organize a router controller logic (middleware vs none-middleware)?

1.6k Views Asked by At

I have a "controller" middleware (connected to koa-router).

I am wondering what is the best approach to organize my "internal" app logic (beyond my controller, the middleware function connected to koa-router router.post('/', createCtrl)).

  1. First case: "Everything is a middleware". My controller simply composes the set of middleware functions required to progressively go from the initial request object to a well suited response object. (I read and pass the arguments required by the next middleware through ctx.state).

    import * as view from './views'
    import * as repo from './repository'
    import * as response from '../../services/response'
    import { sign } from '../../services/jwt'
    import compose from 'koa-compose'
    const createCtrl = compose([
      repo.create(),
      sign(),
      view.sessionUser(),
      response.success(201)
    ])
    
  2. Second case: The application logic is "decoupled" completely from Koa. The controller would be a koa middleware calling none-middleware functions as follow:

    import * as view from './views'
    import * as repo from './repository'
    import * as response from '../../services/response'
    import { sign } from '../../services/jwt'
    const createCtrl = async function (ctx) {
      try {
        const entity = await repo.create()
        const token = await sign(entity.id) 
        const dto = view.sessionUser(token, entity)
        const response = response.success(201)
        response(ctx, dto) // <- this is also a middleware
      } catch(err) {
        ctx.throw(500, 'my not very well handled error')
      }
    }
    

Is it a good idea to think of the controller as a composition of middleware functions? Or is this a misuse of what middleware functions are meant for?

1

There are 1 best solutions below

1
On BEST ANSWER

The best way, is to separate the logic from the controller. Having this separation will allow you reuse the same logic in other parts of the application and it's much easier to test it.

Please check this repository: https://github.com/Talento90/typescript-node

I have a server folder where I put all server infrastructure like controllers and routes (both separated) and then I pass my managers to the server. Managers contain the application logic and are passed to the server.

To summarise: Application logic must NEVER depend on infrastructure in this case an HTTP Server.