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

@helpfulhuman/router-kit

v1.1.3

Published

Simple library for building custom frontend routing solutions for single page applications.

Downloads

6

Readme

Router Kit

Router Kit is meant to be a toolkit for building custom routing solutions for front-end, single page web applications. It provides a simple, middleware-based architecture for handling window.location changes. Router Kit does not include any particular implementation for tracking location changes, so you'll likely want to use a library like history for that.

Getting Started

Install via npm:

npm install --save @helpfulhuman/router-kit

The Router Class

This library provides you with a Router object for attaching middleware and route handlers for your application.

import { Router } from "@helpfulhuman/redux-router";

// create a router instance
var router = new Router();

// ...add middleware here

// export the router to add it to your store
export default router;

Adding Middleware

There are 2 methods available to you for adding middleware to your application. While both are similar, they offer very different implementations of a similar concept.

The first method is .use(), which is often used for general middleware that should be invoked before proceeding. You can optionally provide a partial "path" as the first argument in order to require that the current URI begins with the given path.

The second method, .exact(), is for when you want a middleware or handler to fire only when the given path matches in full. Unlike .use(), the .exact() method requires that a path string be provided. This is typically going to be used for the final step of a route.

// add middleware that will be applied to all routes
router.use(function logger (ctx, next) {
  console.log("router -> " + ctx.location.href);
  next();
});

// add middleware that applies to a partial route name and redirects
// the user if the "token" value isn't set
router.use("/account", function isLoggedIn (ctx, next) {
  if ( ! localStorage.getItem("authToken")) {
    next(null, "/login");
  } else {
    next();
  }
});

// load up the home page
router.exact("/", handleHome);

// add a handler that dispatches actions based on route parameters
router.exact("/account/:page", function (ctx, next) {
  var page = ctx.params.page;
  // do something with the page name
});

What is Middleware?

If you have experience working with Connect or Express, then the middleware system in this library should feel pretty familiar. Middleware are functions that accept a context object (often shortened to ctx) that contains details about the current route and a callback function referred to as next.

Middleware is executed in the order that it is added to the router. When a middleware finishes execution, it should invoke the given next() method to call the next middleware function in the stack.

function middleware (ctx, next) {
  // when done, call next() to invoke the next middleware
  // in the current router's stack
  next();
}

Router Depth & Error Handling

Middleware "stacks" have depth, meaning, the next() call can only invoke sibling (or nested middleware) in its stack. When any non-falsey arguments are passed to next(), the sibling stack call is skipped and any parent next() callback is invoked with the given arguments instead.

What this means: If middleware has a problem and wants to quit execution of further middleware, then an Error should be thrown or passed as the first argument to next(). The "hoisting" function will then be handed the Error object and can handle it.

function errorMiddleware (ctx, next) {
  // did we have an error? tell `next()` about it
  next(new Error("something went wrong"));
}

Redirects using connectHistory()

When using the connectHistory() function in conjunction with a Router, you can optionally pass a URI as a second parameter to next() to invoke a redirect, provided that the first "error" argument is null.

function redirectMiddleware (ctx, next) {
  // perform a redirect by passing the desired URI as the second argument
  next(null, "/example");
}

The context Object

Field | Type | Description ------|------|------------ location | Object | The location object provided by history when routing is initialized. params | Object | The parsed URI tokens for the route when a path with tokens has been provided for the middleware or route handler. Example: if you had a handler bound to /greet/:name and the route was /greet/world, then this value would be { name: "world" }. query | Object | A parsed version of the query string for the route. An example would be ?foo=bar being converted to { foo: "bar" }. uri | String | The URI or location.pathname for the request.

Support for history

This library does not include its own tooling for handling location or history changes. Instead, we recommend you use the history library on NPM, which has become an industry standard. To make integration with this library (or libraries with a similar contract) easier, we provide the connectHistory() method.

This function subscribes your router to history changes and also kicks off the initial routing call on load. Additionally, this is the step where error handling and creation of context object occurs.

import createHistory from "history/createBrowserHistory";
import { connectHistory } from "@helpfulhuman/router-kit";
import router from "./router";

const history = createHistory();

connectHistory(router, history);

Custom Context and Error Handling

An optional third argument can be provided to connectHistory() in the event that you need more control of the context object and error handling.

Note: This removes the default error handling support for redirects, so make sure you handle that as needed.

connectHistory(router, history, function (context, runMiddleware) {
  runMiddleware(context, function (err, redirect) {
    // handle this in a custom manner
  });
});

Aliases

Aliases allow you to work with a semantic route name as an abstraction over the actual route's URI. By not littering URIs throughout your code, you can reduce the risk of forming bad URIs or reduce the hastle often associating with having to refactor URIs.

Note: You can use tokens in the path that you're aliasing.

// add a named alias for routing to a specific task
router.alias("viewTask", "/tasks/:taskId");

// route to the aliased URI -> /tasks/1000
router.buildUri("viewTask", { taskId: "1000" });