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

@goa/router

v1.2.0

Published

The Router For Creating Middleware For Goa Apps.

Downloads

16

Readme

@goa/router

npm version

@goa/router is The Router For Creating Middleware For Goa Apps.

yarn add @goa/router

Table Of Contents

API

The package is available by importing its default class:

import Router from '@goa/router'

The example below creates a really simple router that responds to the GET / and POST /users/:uid requests. Because of allowedMethods, it will also send a response to the OPTIONS request with the allow header.

import rqt, { aqt } from 'rqt'
import Goa from '@goa/koa'
import Router from '@goa/router'

const goa = new Goa()
const router = new Router()
router
  .get('/', (ctx) => {
    ctx.body = `Hello world`
  })
  .post('/users/:uid', (ctx) => {
    ctx.body = `You have edited the user ${ctx.params.uid}`
  })
goa.use(router.routes())

goa.use(router.allowedMethods())
​






# GET /
Hello world

# POST /users/100
You have edited the user 100


# OPTIONS /
HEAD, GET

Router: Router For Goa Apps.

Create a new router.

import Goa from '@goa/koa'
import Router from '@goa/router'

const app = new Goa()
const router = new Router()

router.get('/', (ctx, next) => {
  // ctx.router available
})

app
  .use(router.routes())
  .use(router.allowedMethods())

Generate URL from url pattern and given params.

const url = Router.url('/users/:id', { id: 1 })
// => "/users/1"

Returns separate middleware for responding to OPTIONS requests with an Allow header containing the allowed methods, as well as responding with 405 Method Not Allowed and 501 Not Implemented as appropriate.

import Goa from '@goa/koa'
import Router from '@goa/router'

const app = new Goa()
const router = new Router()

app.use(router.routes())
app.use(router.allowedMethods())

Run middleware for named route parameters. Useful for auto-loading or validation.

router
  .param('user', (id, ctx, next) => {
    ctx.user = users[id]
    if (!ctx.user) return ctx.status = 404
    return next()
  })
  .get('/users/:user', ctx => {
    ctx.body = ctx.user
  })
  .get('/users/:user/friends', async ctx => {
    ctx.body = await ctx.user.getFriends()
  })

Generate URL for route. Takes a route name and map of named params. If the route is not found, returns an error. The last argument can be an object with the query property.

// To use urls, a named route should be created:
router.get('user', '/users/:id', (ctx, next) => {
  // ...
})

Get the URL by passing a simple parameter

router.url('user', 3)
// => "/users/3"

Get the URL by passing parameters in an object

router.url('user', { id: 3 })
// => "/users/3"

Use the url method for redirects to named routes:

router.use((ctx) => {
  ctx.redirect(ctx.router.url('sign-in'))
})

Pass an object query:

router.url('user', { id: 3 }, { query: { limit: 1 } })
// => "/users/3?limit=1"

Pass an already serialised query:

router.url('user', { id: 3 }, { query: 'limit=1' })
// => "/users/3?limit=1"

Use given middleware. Middleware run in the order they are defined by .use(). They are invoked sequentially, requests start at the first middleware and work their way "down" the middleware stack.

// session middleware will run before authorize
router
  .use(session())
  .use(authorize())
// use middleware only with given path
router.use('/users', userAuth())
// or with an array of paths
router.use(['/users', '/admin'], userAuth())
app.use(router.routes())

Set the path prefix for a Router instance that was already initialized.

router.prefix('/things/:thing_id')

| Name | Type | Description | | ---------- | ----------------------------- | --------------------------------------------------------------------------------------------- | | methods | !Array<string> | The methods to serve.Default HEAD, OPTIONS, GET, PUT, PATCH, POST, DELETE. | | prefix | string | Prefix router paths. | | routerPath | string | Custom routing path. |

Verbs

Routes are assigned to the router by calling HTTP method verbs on the instance:

router
  .get('/', (ctx, next) => {
    ctx.body = 'Hello World!'
  })
  .post('/users', (ctx, next) => {
    // ...
  })
  .put('/users/:id', (ctx, next) => {
    // ...
  })
  .del('/users/:id', (ctx, next) => {
    // ...
  })
  .all('/users/:id', (ctx, next) => {
    // ...
  })

Additionally, router.all() can be used to match against all methods. router.del() is an alias for router.delete().

When a route is matched, its path is available at ctx._matchedRoute and if named, the name is available at ctx._matchedRouteName.

Route paths will be translated to regular expressions using path-to-regexp.

Query strings will not be considered when matching requests.

Allowed Methods

The router can respond to the OPTIONS request with the allow header.

Example with Boom

const app = new Goa()
const router = new Router()

app.use(router.routes())
app.use(router.allowedMethods({
  throw: true,
  notImplemented: () => new Boom.notImplemented(),
  methodNotAllowed: () => new Boom.methodNotAllowed(),
}))

AllowedMethodsOptions: The options for the allowedMethods middleware generation.

| Name | Type | Description | | ---------------- | --------------------- | -------------------------------------------------------------------------- | | throw | boolean | Throw error instead of setting status and header. | | notImplemented | () => !Error | Throw the returned value in place of the default NotImplemented error. | | methodNotAllowed | () => !Error | Throw the returned value in place of the default MethodNotAllowed error. |

Named Routes

Routes can optionally have names. This allows generation of URLs and easy renaming of URLs during development.

router.get('user', '/users/:id', (ctx, next) => {
  // ...
})

router.url('user', 3)
// => "/users/3"

Multiple Middleware

Multiple middleware may be passed to the router.

router.get(
  '/users/:id',
  async (ctx, next) => {
    const user = await User.findOne(ctx.params.id)
    ctx.user = user
    await next()
  },
  ctx => {
    console.log(ctx.user)
    // => { id: 17, name: "Alex" }
  }
)

Nested Routes

It's possible to create a Router instance, and then pass another Router instance to its .use call to nest the two.

const forums = new Router()
const posts = new Router()

posts.get('/', (ctx) => {
  ctx.body = ctx.params
})
posts.get('/:pid', (ctx) => {
  ctx.body = ctx.params
})
forums.use('/forums/:fid/posts',
  posts.routes(),
  posts.allowedMethods())

goa.use(forums.routes())
​


// GET /forums/123/posts
{ fid: '123' }

// GET /forums/123/posts/123
{ fid: '123', pid: '123' }





​

Router Prefixes

Route paths can be prefixed at the router level.

const router = new Router({
  prefix: '/users',
})

router.get('/', (ctx) => {
  // responds to "/users"
  ctx.body = ctx.params
})
router.get('/:id', (ctx) => {
  // responds to "/users/:id"
  ctx.body = ctx.params
})

goa.use(router.routes())
// Request /users
{}
// Request /users/123
{ id: '123' }

URL Parameters

Named route parameters are captured and added to ctx.params.

const router = new Router()

router.get('/:category/:title', (ctx) => {
  // the params are exposed to the context.
  ctx.body = ctx.params
})

goa.use(router.routes())
// Request /programming/how-to-node
{ category: 'programming', title: 'how-to-node' }

Copyright & License

GNU Affero General Public License v3.0

Original Work by Alexander C. Mingoia under MIT License found in COPYING.

There's also a fork in the Koa org.