routerify

0.3.0 • Public • Published
8888888b.                   888                    d8b  .d888
888   Y88b                  888                    Y8P d88P"
888    888                  888                        888
888   d88P .d88b.  888  888 888888 .d88b.  888d888 888 888888 888  888
8888888P" d88""88b 888  888 888   d8P  Y8b 888P"   888 888    888  888
888 T88b  888  888 888  888 888   88888888 888     888 888    888  888
888  T88b Y88..88P Y88b 888 Y88b. Y8b.     888     888 888    Y88b 888
888   T88b "Y88P"   "Y88888  "Y888 "Y8888  888     888 888     "Y88888
                                                                   888
                                                              Y8b d88P
                                                               "Y88P"

Routerify is an opinionated router loader for Express-like applications.

Build Coverage Dependencies Dev Dependencies License Release

Install

$ npm install --save routerify

You'll need to have at least Node.js 6 or newer.

Configurations

Routerify is opinionated. Routerify is also configurable and extensible via plugins. The two core plugin types that Routerify has are Registrars and Mounters. Through these, Routerify can be configured to load routes from modules in any pattern and mount them onto any server.

Registrars

Registrars are responsible for picking which source files within the directory should be loaded as modules and how the routes are extracted from the modules. These routes are then passed to the mounter.

Routerify includes some opinionated registrars. If you don't like our opinion, you can either not use Routerify or you can simply create your own and, optionally, create a pull request to share it with everyone, provided our opinions match :) If not, you can always release it as a plugin.

IndexRegistrar

Name: "index"
Default: Yes
How it works:

It expects the following file structure under the target directory:

- /
  - users/
    - _userId/
      - sessions/
        - index.js
      - index.js
    - helper.js
    - index.js

Only files whose base name is index will be loaded (e.g. helper.js in the above example would be ignored) and it expects each one of those modules to export an object whose values are either a single handler method or an array of handler methods. Only handlers associated with properties on the object whose name matches that of a supported verb will be registered.

If we were to build on the example above and say that the /users/index.js file looked something like this:

module.exports = {
  del(req, res, next) {
    ...
  }
  get(req, res, next) {
    ...
  },
  put(req, res, next) {
    ...
  },
  fetchUser(userId) {
    ...
  }
}

Then we could say that at least (we're ignoring routes defined in the other files for the purpose of this example) the following routes would be registered:

  • DELETE /users/:userId
  • GET /users/:userId
  • PUT /users/:userId

The fetchUser method is ignored because it does not match a supported verb.

VerbRegistrar

Name: "verb"
Default: No
How it works:

It expects the following file structure under the target directory:

- /
  - users/
    - _userId/
      - sessions/
        - get.js
      - del.js
      - get.js
      - put.js
    - get.js
    - helper.js
    - post.js

Only files whose base name matches that of a supported verb will be loaded (e.g. helper.js in the above example would be ignored) and it expects each one of those modules to export either a single handler method or an array of handler methods.

In the example above, the following routes would be registered:

  • GET /users
  • POST /users
  • DELETE /users/:userId
  • GET /users/:userId
  • PUT /users/:userId
  • GET /users/:userId/sessions

Create your own Registrar

In order to create your own registrar you simply need to extend the Registrar class and tell Routerify about it:

const routerify = require('routerify')
const Registrar = require('routerify/src/registrar')
 
class CustomRegistrar extends Registrar {
 
  getPluginName() {
    return 'custom'
  }
 
  register(file, options) {
    // Load the module, extract the routes, and mount them via this.mounter
    ...
  }
}
 
routerify.use(new CustomRegistrar())
 
module.exports = CustomRegistrar

Now your new registrar can be used by simply specifying its name in the options:

routerify({
  dir: path.join(__dirname, 'routes'),
  registrar: 'custom',
  server: app
})

You probably want to take a look at the relevant source code before trying to create your own registrar.

Mounters

Mounters are primarily responsible for taking the routes and mounting them onto the server. However, they also provide the default verbs (methods supported by the framework to make route requests for specific HTTP methods) when no verbs option is specified, and they determine how parameter path variables are formatted.

Routerify includes some mounters for common server frameworks. If your favorite framework is not supported, you can create your own and, optionally, create a pull request to share it with everyone.

ExpressMounter

Name: "express"
Default: Yes
Description:

Supports all Express-like frameworks.

RestifyMounter

Name: "restify"
Default: No
Description:

Supports the Restify framework. Since Restify is an Express-like framework itself, the ExpressMounter will work well for the most part, however, this extension of ExpressMounter provides additional benefits for Restify applications by allowing extra optional information (e.g. version/versions) to be used when mounting routes.

This can be done by simply adding an options property containing the additional information to one of the route handlers and it will be passed in.

Create your own Mounter

In order to create your own mounter you simply need to extend the Mounter class and tell Routerify about it:

const routerify = require('routerify')
const Mounter = require('routerify/src/mounter')
 
class CustomMounter extends Mounter {
 
  formatParamPath(param) {
    // Format param for insertion into the route URL
    return ...
  }
 
  getDefaultVerbs() {
    // Specify the supported verbs
    return [...]
  }
 
  getPluginName() {
    return 'custom'
  }
 
  mount(url, verb, handlers, options) {
    // Mount the route onto options.server
    ...
  }
}
 
routerify.use(new CustomMounter())
 
module.exports = CustomMounter

Now your new mounter can be used by simply specifying its name in the options:

routerify({
  dir: path.join(__dirname, 'routes'),
  mounter: 'custom',
  server: app
})

You probably want to take a look at the relevant source code before trying to create your own mounter.

API

Routerify exposes its API primarily through a single method.

routerify(options)

This is the primary method for Routerify and it will go through the target directory, find all routes using the registrar, and finally mounts them onto the server using the mounter.

const express = require('express')
const path = require('path')
const routerify = require('routerify')
const app = express()
 
routerify({
  dir: path.join(__dirname, 'routes'),
  server: app
})
 
app.listen(3000, () => {
  console.log('Example app listening on port 3000!')
})

Options

The following options can be passed to Routerify:

Option Description Default Value
dir The directory containing the routes to be loaded. process.cwd()
ext The extension of the source files to be loaded. ".js"
glob Any options to be passed to the glob module when searching for source files within dir. {}
mounter The name of the Mounter to be used to mount the discovered routes on to the server. "express"
paramPattern The regular expression to be used to match path parameter variables. /^_(.+)/
registrar The name of the Registrar used to load routes from source files in a given structure and then mount them via the mounter. "index"
server The server object (e.g. express()) to which the routes are to be mounted. N/A
verbs The verbs (corresponding to HTTP methods) to be supported. Defaults to those provided by the mounter if not specified. mounter.getDefaultValues()

Only the server option is required. All others have defaults.

routerify.lookup(type[, name])

This method is primarily intended for internal use and provides a means of looking up register Plugin instances of a given type. If no name is provided, it will return all instances that inherit from type. Otherwise, this method will return the first instance that inherits from type that has the given name and will throw an error if no matching plugin could be found.

const Plugin = require('routerify/src/plugin')
const Registrar = require('routerify/src/registrar')
 
routerify.lookup(Plugin)
=> [ ExpressMounter {}, RestifyMounter {}, IndexRegistrar {}, VerbRegistrar {} ]
routerify.lookup(Registrar)
=> [ IndexRegistrar {}, VerbRegistrar {} ]
routerify.lookup(Registrar, 'verb')
=> VerbRegistrar {}
routerify.lookup(Registrar, 'foo')
=> throws Error

routerify.use(plugin)

Routerify can be configured via the use of plugins, which can be registered by this method. It takes a given instance of Plugin.

The previous examples for creating your own mounters and registrars cover how to use this method.

routerify.version

The current version of Routerify.

routerify.version
=> "0.3.0"

Bugs

If you have any problems with Routerify or would like to see changes currently in development you can do so here.

Contributors

If you want to contribute, you're a legend! Information on how you can do so can be found in CONTRIBUTING.md. We want your suggestions and pull requests!

A list of Routerify contributors can be found in AUTHORS.md.

License

See LICENSE.md for more information on our MIT license.

Copyright !ninja

Readme

Keywords

Package Sidebar

Install

npm i routerify

Weekly Downloads

0

Version

0.3.0

License

MIT

Last publish

Collaborators

  • neocotic