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

@websdk/rhumb

v0.4.0

Published

URL routing in js

Downloads

15

Readme

Rhumb

Rhumb is a highly efficient and flexible router.

Given a URI – where the constituent parts may be fixed or variable – Rhumb will unambiguously and with negligable overhead find a matching function, then apply it with whatever parameters might have been extracted from the URI.

Read more.

Bells and Whistles

  • automatic path precedence
  • ambiguity detection
  • variables parts
  • partially variable parts
  • optional parts
  • parameter parsing
  • interpolate params to produce paths

Basic Usage

Rhumb allows you to map paths to functions

rhumb.add("/happy/shoes", function(){
  return shoes
})

If those paths contain variable parts, rhumb will grab them for you

rhumb.add("/happy/shoes/{color}", function(params){
  return shoes.inColor(params.color)
})

Whatever you return in the callback will to handed back to the caller of match

redShoes = rhumb.match("/happy/shoes/red")

When you need to create a URI from a set of params, the interpolate function can be used

redShoesUri = rhumb.interpolate("/happy/shoes/{color}", { color: "red" })

Route Syntax

fixed paths

Fixed paths are the most simple

rhumb.add("/latest/potatoes")

will match /latest/potatoes only

variable parts

Use variable parts in your path to allow a range of options

rhumb.add("/potatoes/{variety}")

This route will match when anything is provided as a variety e.g.

  • /potatoes/osprey
  • /potatoes/saxon
  • /potatoes/marabel
  • /potatoes/321
  • /potatoes/chips

A variety must be provided, so /potatoes alone will not match

Paths with variable parts generate a params object which is passed to the callback

rhumb.add("/potatoes/{variety}", function(params){
  console.log(params.variety)
})
rhumb.match("/potatoes/marabel")
// > "marabel"

partially variable parts

Partially variable parts allow you to capture more than one variable from a single segment of a URL.

If you wanted to capture a date in a url like /news-from/tue-march-1900 you could do so using partial parts.

rhumb.add("/news-from/{day}-{month}-{year}", function(params){
  console.log(
    params.day
  , params.month
  , params.year
  )
})

optional parts

Optional parts, well, are optional

rhumb.add("/stories(/{name})")

The above route matches for /stories and for /stories/anything

Optionals can be nested e.g.

rhumb.add("/stories(/{author}(/{genre}))")

Will match

  • /stories
  • /stories/bob
  • /stories/sarah/scary

Have fun!

Parameter Interpolation

Rhumb allows you to take a route and a set of params and produce a path that can be matched against a route.

fixed paths

When you give .interpolate(...) a route without any declared variables or partial variable parts, then a valid path will be returned and you will typically not see any changes:

rhumb.interpolate("/stories", {})
// returns "/stories"

rhumb.interpolate("/stories?sortBy=publishedDate", {})
// returns "/stories?sortBy=publishedDate"

When the route you supplied is not a valid path, Rhumb will step in and escape some of the characters, so that a valid path can be produced.

If your route has empty parts, then some of the slash characters will be encoded to %2F:

rhumb.interpolate('//sarah/scary', {})
// returns "/%2Fsarah/scary"

rhumb.interpolate('stories//scary', {})
// returns "stories%2F/scary"

variable parts

When variables are present, Rhumb will interpolate the variables with the params you supply:

rhumb.interpolate("/potatoes/{variety}", { variety: "marabel" })
// returns "/potatoes/marabel"

rhumb.interpolate("/shoes/{color}/{size}", { color: "red", size: "6" })
// returns "/shoes/red/6"

For interpolation to produce a valid path, it will throw an error when a required variable is absent, "", null or undefined:

rhumb.interpolate("/potatoes/{variety}", {})
// throws 'Invalid parameter: "variety" is missing'

rhumb.interpolate("/shoes/{color}/{size}", { color: "red", size: null })
// throws 'Invalid parameter: "size" is null'

To mark a variable part as not-required, it has to be wrapped in an optional path, as shown later.

partially variable parts

Like variables, Rhumb will interpolate partially variable parts when they are defined and not empty in the supplied params:

rhumb.interpolate("/orders/{days}-days-ago", { days: "40" })
// returns "/orders/40-days-ago"

rhumb.interpolate("/author/{forename}-{surname}", { forename: "susan", surname: "smith" })
// returns "/author/susan-smith"

It will also throw an error when a required partial variable is absent, "", null or undefined:

rhumb.interpolate("/orders/{days}-days-ago", { days: "" })
// throws 'Invalid parameter: "days" is empty'

rhumb.interpolate("/author/{forename}-{surname}", { forename: "susan", surname: undefined })
// throws 'Invalid parameter: "surname" is undefined'

To mark a partially variable part as not-required, it has to be wrapped in an optional path, as shown later.

optional parts

Rhumb is greedy with how it handles optional paths when interpolating, so expect optional parts to be included whenever possible.

rhumb.interpolate("/stories(/bob)", {})
// returns "/stories/bob"

rhumb.interpolate("/stories(/sarah(/scary))", {})
// returns "/stories/sarah/scary"

When variables or partially variables in optional parts are absent, "", null or undefined then no error is thrown and the optional part is dropped.

rhumb.interpolate("/stories(/by-{name})", {})
// returns "/stories"

rhumb.interpolate("/stories(/{author}(/{genre}))", { author: "sarah", genre: "" })
// returns "/stories/sarah"

Found an issue, or want to contribute?

If you find an issue, want to start a discussion on something related to this project, or have suggestions on how to improve it? Please create an issue!

See an error and want to fix it? Want to add a file or otherwise make some changes? All contributions are welcome! Please refer to the contribution guidelines for more information.

License

Please refer to the license for more information on licensing and copyright information.