Route Group on Multiple files

Can I use multiple files for routes and still import and add them to groups of routes? To add middleware or preffix to groups

start/routes/index.ts

import Route from '@ioc:Adonis/Core/Route'

import SessionsRoute from './sessions'

import HeathChecksRoute from './healthChecks'

import UsersRoute from './users'

import WorkShapesRoute from './workShapes'

Route.group(() => {

  SessionsRoute, 
  HeathChecksRoute, 
  UsersRoute, 
  WorkShapesRoute

}).prefix('apiv1').as('apiv1')

start/routes/sessions.ts

import Route from '@ioc:Adonis/Core/Route'

Route.post('sessions', 'SessionsController.store')

export default Route

Note: I’m using adonis v5

You can do that but will obviously not work with your pattern. Why would you re-export the Route object which is obviously a singleton? Well, in order to make it work, you have to export a function which would define routes on the Route object. For instance,
start/routes/sessions.ts

import Route from '@ioc:Adonis/Core/Route';

const routes = ()=>{
Route.post('sessions', 'SessionsController.store');
//other routes here

export default routes;

start/routes/index.ts

import Route from '@ioc:Adonis/Core/Route'

import SessionsRoute from './sessions'

Route.group(()=>{

SessionRoute();

}).prefix('apiv1');
3 Likes

I knew it wouldn’t work. But the answer I wanted was exactly how to make it work. Wonderful, thank you very much!

This pattern is used on express routes…

@iammrsea Could you give your opinion on this pattern? For systems with many routes and middleware and validators.

start/routes.ts


import Route from '@ioc:Adonis/Core/Route'

import sessionsRoute from './routes/sessions'
import healthChecksRoute from './routes/healthChecks'
import usersRoute from './routes/users'
import rolesRoute from './routes/roles'
import enterprisesRoute from './routes/enterprises'
import workShapesRoute from './routes/workShapes'

Route.group(() => {
  sessionsRoute()
  healthChecksRoute()

  Route.group(() => {
    usersRoute()
    rolesRoute()
    enterprisesRoute()
    workShapesRoute()
  }).middleware('auth')
}).prefix('api/v1')

start/routes/users.ts

import Route from '@ioc:Adonis/Core/Route'

export default () => {
  Route.resource('users', 'UsersController')
    .validator(
      new Map([
        [['users.store'], ['User/Store']],
        [['users.update'], ['User/Update']],
      ]),
    )
    .middleware(
      new Map([
        [['users.store'], ['guard: user.create']],
        [['users.index'], ['guard: user.read']],
        [['users.show'], ['guard: user.read']],
        [['users.update'], ['guard: user.update']],
        [['users.destroy'], ['guard: user.delete']],
      ]),
    )
}

I am a bit curious, is the validator method a new addition to the object returned by Route.resource()?

I was thinking, why not wrap your validators in middleware since there is no router level validator method? If you really want to have the same interface as you showed above, you could write a proxy of the Route object as shown below:

//proxy.ts

import Route from "@ioc:Adonis/Core/Route";

class ProxyRoute {
  constructor(private route) {}
  public static resource(route: string, controller: string) {
    const router = Route.resource(route, controller);
    return new ProxyRoute(router);
  }
  public middleware(auth: object) {
    this.route.middleware(auth);
    return this;
  }
  public validator(validator: object) {
    this.route.middleware(validator);
    return this;
  }
}
export default ProxyRoute;
//Usage

ProxyRoute.resource("/users", "UsersController")
  .validator({store:['validateStore']})
  .middleware({
  destroy: ["auth"],
  update: ["auth"],
});

Though it looks stupid and unnecessary, but that’s the only thing I could come up with right now

1 Like

Sorry, this validation method was used in adonis v4.1.

I am migrating to version 5. So I was not understanding how the validation was done in this new version

Thank you very much for the opinion