steambap / koa-tree-router

high performance router for Koa

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Allow nested routers

ewrogers opened this issue · comments

Would be helpful to allow nested routers using router.use(...) syntax, similar to koa-router.

Here's an example:

const apiRouter = new Router({ prefix: '/api' })
apiRouter.use(usersRouter.routes())  // assume prefix '/users'
apiRouter.use(todosRouter.routes()) // assume prefix '/todos'
...

app.use(apiRouter.routes())  // would allow /api/users and /api/todos

I personally use awilix to dynamically load a lot of my routers/controllers and then build a parent apiRouter like so (iterating through the IoC container via listModules()).

This is definitely a great feature to have. PRs are welcome.

Hi, I have added route group in v0.7.0 release. It can be used like this:

const Koa = require("koa");
const Router = require("koa-tree-router");

const app = new Koa();
const router = new Router();
const group = router.newGroup("/foo");
// add a handler for /foo/bar
group.get("/bar", function(ctx) {
  ctx.body = "hello, world";
});

app.use(router.routes());

app.listen(8080);

In the future, I want to make every router a route group so it is easier to use. For now, this should be enough for all kinds of nested routers.

Groups seems like a nice way of partition routes. However, I've run into a bit of trouble using it with ES6 modules. Consider the following example:

/root-apis.js

import Router from 'koa-tree-router'

export const rootApis = new Router()

rootApis.get('/ping', async (ctx, next) => {
  ctx.body = `APIs — ${new Date()}`
})

/admin-apis.js

import { rootApis } from './index.js'

const adminApis = rootApis.newGroup('/admin')

adminApis.get('/ping', async (ctx, next) => {
  ctx.body = `Admin APIs — ${new Date()}`
})

In order to create a new group and separate that group into a different file, I need to import the rootApis object into the admin-apis.js file. However, in order for the code in admin-apis.js to run, I need to import it somewhere. If I update my root-apis.js file like so:

/root-apis.js

import Router from 'koa-tree-router'

export const rootApis = new Router()
import 'admin-apis.js' // <-- THIS LINE ADDED

rootApis.get('/ping', async (ctx, next) => {
  ctx.body = `APIs — ${new Date()}`
})

I now get an error message of

ReferenceError: Cannot access 'rootApis' before initialization

This error occurs despite adding the import 'admin-apis.js' statement below the initialization of rootApis because in ES6 modules, all import statements are hoisted, and therefore occur before all other code, despite placement in the file.


As a fix for this, I'm imagining an API along the lines of this:

import Koa from 'koa'
import Router from 'koa-tree-router'


const subRouter = Router.newGroup('/foo')
subRouter.get('/bar', function(ctx) {
  ctx.body = 'hello, world'
})

const rootRouter = new Router()
rootRouter.addGroup(subRouter)

const app = new Koa()
app.use(router.routes())
app.listen(8080)