This repo has been archived — https://github.com/tmarshall/soda is an active replacement
This library walks a directory and turns it into express routes.
The current version requires express >= 5, so that async handlers are supported.
npm install @conjurelabs/route
or
yarn add @conjurelabs/route
!! This requires express>=5
, since earlier versions of Express don't work with async
route handlers.
Let's say you have your routes in a directory like:
.
└── routes
└── account
├── $accountId
│ ├── delete.js
│ ├── get.js
│ ├── patch.js
│ ├── post.js
│ └── put.js
└── all.js
Note that params are defined with a $
, not a :
. Colons cause issues when searching in editors.
Each file just needs to export an express route handler:
module.exports = (req, res, next) => {
res.send('result')
}
You can also export an array of handlers:
const fn1 = (req, res, next) => { /* logic */ }
const fn2 = (req, res, next) => { /* logic */ }
module.exports = [fn1, fn2]
This library will automatically convert these exported functions into express route handlers. You will need to walk your route directory, and mount them on your express server:
const express = require('express')
const walkRoutes = require('@conjurelabs/route')
const routes = await walkRoutes(path.resolve(__dirname, 'routes'))
const server = express()
server.use(routes)
This library supports the following express verbs: get
, post
, put
, patch
, delete
, and all
. Any verb the library does not recognize will be ignored.
A file get.js
will expose a GET
route.
You can append anything after get.
if you want to chain multiple handlers. E.g. get.0.js
, get.1.js
. Filenames are sorted before being exposed, so get.0.js
will be mounted first, on the given path.
You can add middleware methods in a .middleware
directory. All routes in that directory, or any sub-directory, will have access to these middleware functions.
They are disabled by default, and can be enabled for all files in the directory, and sub-directories, by providing a .middleware.flags.js
file.
Let's say you have the following structure:
.
└── routes
├── .middleware
│ ├── requireLoggedIn.js
│ └── appendSession.js
├── .middleware.flags.js
└── account
├── $accountId
│ ├── delete.js
│ ├── get.js
│ ├── patch.js
│ ├── post.js
│ └── put.js
└── all.js
Where middleware files look like:
// routes/.middleware/requireLoggedIn.js
module.exports = async (req, res, next) => {
if (!req.user) {
return next(new Error('Invalid auth'))
}
next()
}
And we have a root .middleware.flags.js
of:
module.exports = {
requireLoggedIn: true,
appendSession: false
}
This will only implement the requireLoggedIn
middleware on all routes, by default. If you wanted to turn that off inside a specific sub-directory, you can add a .middleware.flags.js
in that sub-directory.
Middleware functions are run before route handlers.
If you want to see examples, take a look at the test mock directories
If you need to set middleware flags on a specific route, instead of a whole directory, you can do so:
module.exports = (req, res) => {
res.send('some route')
}
module.exports.middlewareFlags = {
appendSession: true
}
Flags are resolved bottom-up. Route-exported flags come first, then flags set in .middleware.flags.js
files, going upward in the directory.
Sometimes you'll want to simply skip all the route handlers in a file or directory based on some condition. For example, you might have an API directory of debug routes that should only be available if you're in Development.
Middleware methods get four args: (req, res, next, skip)
. skip
is a function that will skip over any handlers. So, in the example of debug routes, you could have a middleware function like this:
// routes/.middleware/devOnly.js
const { NODE_ENV } = process.env
module.exports = (req, res, next, skip) => {
if (NODE_ENV !== 'development') {
return skip()
}
next()
}
Then, wherever you enable this middleware, the routes will only be available if NODE_ENV === 'development'
, or else they will 404.