js-data-express

Generate Express.js-compatible RESTful endpoints based on your JSData models.

js-data logo

Slack Status npm version Circle CI npm downloads Coverage Status

Generate Express.js-compatible route middleware (RESTful endpoints) for js-data models. Works with JSData 3.x and newer.

Table of Contents

Quick Start

npm install --save js-data@beta js-data-express express

Here's a small sample:

import express from 'express';
import { mount, queryParser, Router } from 'js-data-express';
import { Container } from 'js-data';

const app = express();
const store = new Container();
const userService = store.defineMapper('user');
const commentService = store.defineMapper('comment');

// Other app setup code

// Variant 1
// Mount queryParser and store at "/"
mount(app, store);

// Variant 2
// Mount queryParser and store at "/api"
mount(app, store, '/api');

// Variant 3
// Mount queryParser at "/"
app.use(queryParser);
// Mount store at "/"
app.use(new Router(store).router);

// Variant 5
// Mount queryParser at "/api"
app.use('/api' queryParser);
// Mount store at "/api"
app.use('/api', new Router(store).router);

// Variant 6:
var api = express().Router();
// Mount queryParser
api.use(queryParser);
// Mount UserMapper at "/user"
api.use('/user', new Router(userService).router);
// Mount UserMapper at "/comment"
api.use('/comment', new Router(commentService).router);
// Mount api to an existing express app instance at "/api"
app.use('/api', api);

📘

Node.js CommonJs (non-es2015)

If you're not using es2015 module import syntax with some sort of transpiler, you'll need to reference js-data-express exports more specifically

const mount = require('js-data-express').mount
const queryParser = require('js-data-express').queryParser
const Router = require('js-data-express').Router

Configuring

Middleware

import express from 'express'
import { mount, queryParser, Router } from 'js-data-express'
import { Container } from 'js-data'

const app = express()
const store = new Container()
const userService = store.defineMapper('user')
const commentService = store.defineMapper('comment')

// Variant 1
// Add a middleware method for the entire store
const config = {
  request: (req, res, next) => {
    const userLoggedIn = req.session.loggedIn

    if (userLoggedIn) {
      next() 
    } else {
      res.sendStatus(403)
    }
  }
}

mount('/api', store, config)

// Variant 2
// Add middleware for specific methods
const config = {
  // find, findAll, create, createMany, etc.
  'destroy': {
    request: (req, res, next) => {
      const userIsAdmin = req.session.isAdmin

      if (userIsAdmin) {
        next() 
      } else {
        res.sendStatus(401)
      }
  }
}
  
mount('/api', store, config)
  
// Variant 3
// Add middleware for specific mapper/endpoint
const config = {
    request: (req, res, next) => {
      const userIsAdmin = req.session.isAdmin

      if (userIsAdmin) {
      next() 
      } else {
        res.sendStatus(401)
      }
  	}
}
// add the Router() express router instance
app.use('/user', new Router(userService, config).router)

Method Action & Response Handlers

You can apply custom logic to intercept a specific method/endpoint and response results

import express from 'express'
import { mount, queryParser, Router } from 'js-data-express'
import { Container } from 'js-data'

const app = express()
const store = new Container()
const userService = store.defineMapper('user')

// Intercept and use custom method on find (findAll, update, updateAll, etc.)
const config = {
	find: {
    request: (req, res, next) {
    	// some middleware logic for this endpoint method
    	next()
  	},
    action (userComponent, req) {
      // must return a Promise
      return component.find(req.params.id, req.jsdataOpts)
    },
  	toJSON: (userComponent, result, jsdataOpts) {
  		// some logic for toJSON, the response results
  		// ie: remove password field from users
  		delete result.password
  		return result
		},
    statusCode: 200
  },
}

// mount on /user endpoint
app.use('/user', new Router(userService, config).router)

Links

🚧

See an issue with this tutorial?

You can open an issue or better yet, suggest edits right on this page.

📘

Need support?

Have a technical question? Post on the JSData Stack Overflow channel or the Mailing list.

Want to chat with the community? Hop onto the JSData Slack channel.