npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

koa-branch-router

v1.0.9

Published

Radix tree like router middleware for koa

Downloads

1,638

Readme

Koa branch router

Coverage Status

Koa branch router is a simple radix tree (-ish) router for koa.

Why?

  • There seem to be no radix tree routers with nested router support (at the time of writing).
  • Popular routers handle middlewares in an inconvenient way. See Middleware Routing.

Features

  • Express-style routing using verbs like router.get, router.put, router.post, etc.
  • Nested routes and middlewares.
  • Path params and wildcard capturing.

Usage

const Koa = require('koa');
const Router = require('koa-branch-router');

const app = new Koa();
const router = new Router();

router.get('/', (ctx) => {
  ctx.body = 'Hello World!';
});

app.use(router.routes());
app.listen(9000);

Middleware Routing

Middlewares are only called if a handler registered in the same router matches agaist the path.

Note

Middlewares and Handlers are essentially the same except:

// treated as a middleware if added using .use()
router.use('/', middleware)

// treated as a handler if added using .all() or .get(), .post() etc
router.all('/', handler)

Routing Example

// the path `/users/42/images`

router
  .use('/users', new Router()
    .use(userMiddleware) // <-- not called
    .get('/', listUsers)
    .get('/:userId', getUser)

  .use('/users/:userId/images', new Router()
    .use(imageMiddleware) // <-- called
    .get('/', listImages) // <-- called
    .get('/:imageId', getImage);

If you dont want this behaviour, you should use a route fragment.

// the path `/users/42/images`

router
  .use('/users', new Router.Fragment()
    .use(userMiddleware)) // <-- called

      // fragments don't add a routing boundary and
      // behave like a middleware registered on the
      // parent router.

  .use('/users', new Router()
    .use(userMiddleware) // <-- not called
    .get('/', listUsers)
    .get('/:userId', getUser)

  .use('/users/:userId/images', new Router()
    .use(imageMiddleware) // <-- called
    .get('/', listImages) // <-- called
    .get('/:imageId', getImage);

Nested Routers

You may nest routers.


const userRouter = new Router()
  .use('/', listUsers) // becomes `/users/`
  .use('/:id', getUser); // becomes `/users/:id`

const tokenRouter = new Router({ prefix: '/tokens' })
  .use('/', listUsers) // becomes `/auth/tokens/`
  .use('/:id', getUser); // becomes `/auth/tokens/:id`

const fileRouter = new Router()
  .use('/files', listFiles) // remains `/files/`
  .use('/files/:id', getFile)); // remains `/files/:id`

const rootRouter = router
  .use('/users', userRouter)
  .use('/auth', tokenRouter)
  .use(fileRouter);

Path Matching

Static

router.all('/users', ...)

| Path | Match | | ----------- | ----- | | /users | true | | /users/42 | false |

Named Parameters

Named parameters like :name match a single path segment delimited by /

router.all('/users/:name', ...)

| Path | Match | Captured Params | | --------------------- | ----- | --------------------- | | /users | false | | | /users/gwen | true | { name: 'gwen' } | | /users/profile | true | { name: 'profile' } | | /users/gwen/profile | false | |

Wildcard

Catches paths starting with the provided path, and captures the rest until the end.

router.all('/users/*path', ...)

| Path | Match | Captured Params | | --------------------- | ----- | --------------------------- | | /users | false | | | /users/gwen | true | { path: 'gwen' } | | /users/profile | true | { path: 'profile' } | | /users/gwen/profile | true | { path: 'gwen/profile' } |

Wildcards can be used without capturing as well.

router.all('/users/*', ...)

Quirks

  • Captured parameters are decoded using decodeURIComponent, whereas wildcard captures are not.

API

new Router([options])

Initialize a new router.

Options

| Option | Default | Description | | ------------------------ | -------- | ----------------------------------- | | options.prefix | '' | Router prefix | | options.caseSensitive | false | Case sensitive paths | | options.strict | false | Treat /foo and /foo/ as different urls |

router.verb()

Registers handlers for path. Supported verbs are:

router
  .get(path, ctx => ...)
  .post(path, ctx => ...)
  .patch(path, ctx => ...)
  .put(path, ctx => ...)
  .delete(path, ctx => ...)
  .del(path, ctx => ...) // alias for `.delete()`
  .all(path, ctx => ...); // matches all methods

You may pass multiple handlers.

router.get(
  path,
  (ctx, next) => ...,
  (ctx) => ...);

router.use()

Registers middleware for path

router
  .use(parseToken)
  .use(authorize);
// or multiple
router.use(parseToken, authorize);
// or with path
router.use('/users', authUser);

router.routes()

Returns router middleware.

app.use(router.routes());

new Router.Fragment([options])

Initialize a new route fragment. Fragments don't add a routing boundary and behave like a middleware registered on the parent router. See Middleware Routing.

Accepts the same options as a router. See Router Options

The API is again similar to the router except that there is no .routes() method. Only routers can be mounted on apps.

ctx.params

This object contains key-value pairs of named route parameters.

// GET /user/42
router.get('/user/:name', (ctx) => {
  ctx.params.name // => '42'
});