m10
Centralized configuration development for Express APIs. Describe your api in one file and just point to handlers and joi validations. All routes with middlewares, handler and validation will be automatically loaded on start-up.
Suitable for:
-
MVPs
-
Prototypes
-
Small APIs
-
Microservices
Scaffold tool: m10-cli
Work in progress
Install
npm install --save m10
or yarn add m10
Supported only Node.js 8+
Usage
const express = const app = const m10 = const config = // m10 configuration // load m10 config into this appm10 app
Config example
{
"global": { // apply to all routes
"middleware": "./middleware/auth.user" // point to file.functionName
},
"routes": [ // list of routes
{
"path": "/todo/:id",
"method": "GET",
"validate": "./schema/todo.findOne" // Joi schema to validate the user input - can be omitted if is not required
"handler": "./handler/todo.findOne",
// Optional (one of):
/*
Overwrite global middleware for this route only
you can also use a single path or null
"middleware": ["./utils/onlyMobileDevice", "./middleware/auth.user"]
*/
/*
Append this middleware (after the global one), for this route only
you can also use an array
"append_middleware": "./middleware/auth.premiumPlan"
*/
/*
Prepend this middleware (before the global one), for this route only
you can also use an array
"prepend_middleware": "./middleware/device.mobileOnly"
*/
},
{
"path": "/ping",
"method": "GET",
"handler": "./handler/ping.js",
"middleware": null // overwrite global middleware settings
},
{
"path": "/todo",
"method": "POST",
"manager": "./todo.insertOne" // with manager you mean that `todo.insertOne` will have `handler` (todo.insertOne.handler) and `validate` (todo.insertOne.validate) objects
}
]
}
Lifecycle
middleware(s)
--> validate
--> handler
This flow will stop if one fails/throws (e.g. if validate
fails the handler
will not be called and the request is returned, same for custom middlewares) - see examples below
File example
global.middleware
Value: ./middleware/auth.user
Will resolve to:
-
File:
./middleware/auth.js
-
Middleware function
user
moduleexports { let token = reqheaders'x-api-key' if !token || token !== 'password' return resstatus401 // this will return, validation and handler won't be called // set user id for next routes reqsessionuser_id = 'user_x' }
routes[0].validate
Value: ./schema/todo.findOne
Will resolve to:
-
File:
./schema/todo.js
-
Validate object
findOne
const Joi = // import Joi libmoduleexportsfindOne = params: // we want to validate only `params` id: Joi // here you can also validate `query`, `body` etc..
routes[0].handler
Value: ./handler/todo.findOne
Will resolve to:
-
File:
./handler/todo.js
-
Handler function
findOne
moduleexportsfindOne = async { // at this point user has passed the global middleware (middleware/auth.user) and has entered a valid :id (schema/todo.findOne) let todoFound = await reqdb if todoFound === null return resstatus404 return resstatus200}
routes[2].manager
Value: ./handler/todo.insertOne
Will resolve to:
-
File:
./handler/todo.js
-
Handler function
insertOne.handler
-
Validate object
insertOne.validate
const Joi = // import Joi lib// "manager" will automatically load "validate" and "handler" moduleexportsinsertOne = validate: body: // this is a POST request, validate body title: Joi description: Joi deadline: Joi { // at this point user has passed all middlewares and body is validated let body = reqbody let newTodo = Object let insertRes = await reqdb resstatus201 }