sleepify

1.1.1 • Public • Published

status version

sleepify

An unobtrusive, easy to use library to quickly prototype relational REST apis in Express.

Install

npm i -S sleepify

Changes (v1.1.0)

  • Plugin now accepts an express app or router as a first parameter. This was necessary to drop the express dependency.
//Previous behaviour
//let usersRouter = sleepify(userPlugin)
 
//Current behaviour
let usersRouter = express.Router()
sleepify(usersRouter, userPlugin)
 
//Equivalent
let usersRouter = sleepify(express.Router(), userPlugin)
//usersRouter points to the same router passed to it
Usage (TL;DR):
let express = require('express')
let bodyParser = require('body-parser')
let {sleepify, sleepymem} = require('sleepify')
 
let app = express()
 
app.use(bodyParser.json())
 
module.exports = app
 
//Dummy memorystore
let memDB = {}
memDB.cars = [
    {id: '0', name: 'Suzuki'},
    {id: '1', name: 'Honda'},
    {id: '2', name: 'BMW'},
    {id: '3', name: 'MX5'}
]
memDB.users = [
  {
    id: '0',
    name: 'Foo',
    cars: memDB.cars.slice(0, 2)
  },
  {
    id: '1',
    name: 'Bar',
    cars: memDB.cars.slice(2, 3)
  }
]
 
//sleepymem is a basic in-memory plugin
let userPlugin = sleepymem({
  name: 'user',
  model: memDB.users
})
    .pre((req, res, next) => {
      console.log(req.method + ' ' + req.originalUrl)
      next()
    })
    .pre([ACTIONS.CREATE, ACTIONS.UPDATE, ACTIONS.DELETE], (req, res, next) => {
      console.log(`Simulating authentication middleware`)
      next()
    })
    .rel(sleepymem({
      name: 'car',
      model: memDB.cars,
      expose: [ACTIONS.GET, ACTIONS.LIST, ACTIONS.REPLACE]
    }).pre((req, res, next) => {
      console.log('Cars middleware only!')
      next()
    }).pre(ACTIONS.CREATE, (req, res, next) => {
      console.log('Before car creation')
      next()
    })
    )
    .post((req, res, next) => {
      console.log(`Done ${req.method + ' ' + req.originalUrl}`)
      next()
    })
 
// This router will point to the following endpoints:
// GET /users
// GET /users/:userId
// POST /users
// PATCH /users/:userId
// DELETE /users/:userId
// GET /users/:userId/cars
// GET /users/:userId/cars/:carId
// PUT /users/:userId/cars/:carId
let usersRouter = express.Router()
sleepify(usersRouter, userPlugin)
 
let apiRouter = express.Router()
apiRouter.use(usersRouter)
app.use('/api/v1', apiRouter)

Plugin methods:

plugin.pre(action, middleware) / plugin.post(action, middleware):
  • action: The action the middleware should be applied to. One of the actions from ACTIONS.
  • middleware: function (req, res, next) / Array - An express middleware or an array of them.

action can be replaced by middleware. This is equivalent to plugin.pre(ACTIONS.ALL, middleware) or plugin.post(ACTIONS.ALL, middleware) respectively.

plugin.rel(plugin):
  • plugin: An instance of a plugin to be nested. Much like a nested router.

Plugins

Plugins are a way to define how an action should be performed. A plugin takes an options object:

options:
  • name: String (required) - The prefix for these routes (for example 'user').
  • plural: String (optional, default: name + 's') - The prefix for these routes (for example 'facilities').
  • model: AnyObject (optional, default: undefined) - An object representing the model to be interacted with. This is available later in req.slp.model
  • expose: Array (optional, default: ACTIONS.ALL) - The endpoints to expose.
  • methods: Object (required, default: noop object) - An object containing at least one of the actions defined in ACTIONS as a key with a value of function (req, done) describing the implementation of this specific method. Callback: done(statusCode / Error, responseObject).
Example:
{
    name: 'facility',
    plural: 'facilities',
    model: mongoose.model('Facility'),
    expose: [ACTIONS.GET, ACTIONS.LIST],
    methods: {
        get: (req, done) => {
            req.slp.model.findById(req.slp.id)
                .then(facility => {
                    if(!facility) return done(404)
                    done(200, facility)
                }).catch(done)
        },
        list: (req, done) => {
            req.slp.model.find({...})
                .then(facilities => done(200, facilities))
                .catch(done)
        }
    }
}

Extending plugins

An example implementation is available here.

MongoosePlugin will be available soon in a different repo.

TODO

  • Add support for collection delete.
  • Allow expose endpoint selection in Plugins.
  • Add support for other node-based frameworks (koa, restify...).

Development

Install dependencies: npm i

Run tests: npm test

Readme

Keywords

Package Sidebar

Install

npm i sleepify

Weekly Downloads

0

Version

1.1.1

License

ISC

Last publish

Collaborators

  • muliyul