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

@medley/router

v0.2.1

Published

A high-performance URL router

Downloads

1,868

Readme

@medley/router

npm Version Build Status Coverage Status dependencies Status

A high-performance URL router for JavaScript/Node.js.

Features

  • Currently the fastest JavaScript router implementations out there (see benchmarks)
  • Supports multiple routes with the same prefix as dynamic routes (see here for details)
  • Only handles routing the URL, so it’s very flexible for building features on top of it
    • e.g. This makes it easy to support 405 Method Not Allowed responses

Installation

npm install @medley/router
# or
yarn add @medley/router

API

new Router([options])

  • options (object) - Optional object that may have any of the following options:
    • storeFactory (function) - Called when a new route is registered to create the route store.
      • Default: () => Object.create(null)

Constructs a new router instance.

const Router = require('@medley/router');
const router = new Router();

Use the storeFactory option to customize the route store object.

const Router = require('@medley/router');

const router = new Router({
  storeFactory() {
    return { handlers: new Map(), middlewares: [] };
  }
});

const store = router.register('/');
console.log(store); // { handlers: Map {}, middlewares: [] }

router.register(path)

  • path (string) - The route path.
  • Returns: object - The route store.

Registers a route and returns the route store object. If the route path has already been registered, the route store is simply returned.

const Router = require('@medley/router');
const router = new Router();

const store = router.register('/users/:id');
console.log(store); // [Object: null prototype] {}

HTTP example:

const Router = require('@medley/router');
const router = new Router();

function addRoute(method, path, handler) {
  const store = router.register(path);
  store[method] = handler;
}

addRoute('GET', '/', () => { /* ... */});
addRoute('GET', '/users', () => { /* ... */});
addRoute('POST', '/users', () => { /* ... */});

Path Formats

1. Static

Static routes match exactly the path provided.

/
/about
/api/login
2. Parametric

Path segments that begin with a : denote a parameter and will match anything up to the next / or to the end of the path.

/users/:userID
/users/:userID/posts
/users/:userID/posts/:postID

Everything after the : character will be the name of the parameter in the route params object.

router.register('/users/:userID');

const route = router.find('/users/100');
console.log(route.params); // { userID: '100' }

If multiple routes have a parameter in the same part of the route, the parameter names must be the same. For example, registering the following two routes would be an error because the :id and :userID parameters conflict with each other:

/users/:id
/users/:userID/posts

Parameters may start anywhere in the path. For example, the following are valid routes:

'/api/v:version' // Matches '/api/v1'
'/on-:event'     // Matches '/on-click'
3. Wildcard

Routes that end with a * are wildcard routes. The * will match any characters in the rest of the path, including / characters or no characters.

For example, the following route:

/static/*

will match all of these URLs:

/static/
/static/favicon.ico
/static/js/main.js
/static/css/vendor/bootstrap.css

The wildcard value will be set in the route params object with '*' as the key.

router.register('/static/*');

let route = router.find('/static/favicon.ico');
console.log(route.params); // { '*': 'favicon.ico' }

route = router.find('/static/');
console.log(route.params); // { '*': '' }

router.find(url)

  • url (string) - The URL used to find a matching route.
  • Returns: ({store: object, params: object} | null) - The route store and matching parameters, or null if the URL did not match any registered routes.

Finds a route that matches the provided URL. Returns null if no route matches the URL.

const Router = require('@medley/router');
const router = new Router();

function addRoute(method, path, handler) {
  const store = router.register(path);
  store[method] = handler;
}

addRoute('GET', '/', () => {});
addRoute('GET', '/users', () => {});
addRoute('POST', '/users', () => {});
addRoute('GET', '/users/:id', () => {});
addRoute('GET', '/static/*', () => {});

router.find('/');
// {
//   store: { GET: [Function] },
//   params: {}
// }

router.find('/users');
// {
//   store: { GET: [Function], POST: [Function] },
//   params: {}
// }

router.find('/users/100');
// {
//   store: { GET: [Function] },
//   params: { id: '100'}
// }

router.find('/static/js/common.js');
// {
//   store: { GET: [Function] },
//   params: { '*': 'js/common.js' }
// }

router.find('/not-defined');
// null

Path Match Order

This router allows different types of routes with the same prefix to overlap. Overlapping routes will match in the following order:

  1. Static
  2. Parametric
  3. Wildcard

For example, with the following routes defined:

/static/favicon.ico
/static/:hash/webpack/*
/static/*

incoming URLs will be matched like this:

'/static/favicon.ico'
// Matches '/static/favicon.ico'

'/static/00a8b09d8ef/webpack/runtime.js'
'/static/00a8b09d8ef/webpack/css/common.css'
// Matches '/static/:hash/webpack/*'

'/static/vendor/css/bootstrap.css'
'/static/images/header.jpg'
// Matches '/static/*'