Design a solid MVC REST API with node.js express and ORM Part 2
If you followed my last part, you should have by now a web application using express js with a simple user route.
We implemented the following routes:
- GET /users — Get all users (collection resource)
- GET /users/{id} — Get one user (singleton resource)
In this article, I will cover Create, Update, and Deletion of a resource, But first, we will need to implement a database connection with an Object-Relational Mapping (ORM).
Let’s get started.
First, to get a better structure, let’s create a ‘controllers’ folder and create our ‘user-controller.js’ file.
Then we will create there the getUser, get and create functions we made before:
const usersData = {...}
exports.getUser = (req, res, next) => {
const id = req.params.userId;
if (id && usersData[id]) {
res.json(usersData[id]);
res.status(200).send();
} else {
// Not Found
res.status(404).send();
}
};
// to retrieve resource
exports.getAll = (req, res, next) => {
// Respond with some data and return status OK
res.json(usersData);
res.status(200).send();
};
// to create new resources
exports.createUser = (req, res, next) => {
// Return our request body and return status OK
res.json(req.body).status(200).send();
};
Now let’s use those in our ‘routes/users.js’ file:
// routes/users.js
const userController = require('../controllers/user-controller');
router.route('/users')
.get(userController.getAll);
router.route('/users/:userId')
.get(userController.getUser)
Database and ORM
In the following steps, we will create a DB connection, create a model for our User resource using Sequelize ORM framework and implement Delete, Create and update.
First, let’s install the needed packages:
npm install --save sequelize
Add the DB driver as well. I used SQLite just for the In-Memory option, but you can use any supported driver.
npm install --save sqlite3
Set up the DB connection.
Create a new folder called ‘db’ and create a ‘sequilize.js’ file there.
Inside the file, add the following lines to create a DB connection.
// db/sequilize.js// Example for sqlite
const sequelize = new Sequelize('sqlite::memory:')
To create our model, make a new folder called ‘models’ and create a ‘user.js’ file there.
A model should represent our DB table. It will define our columns type and restrictions.
I used the following model for this example.
// models/user.jsconst { DataTypes } = require('sequelize');module.exports = (sequelize) => {
sequelize.define('user', {
id: {
type: DataTypes.BIGINT(20),
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING(50),
allowNull: false,
validate: {
min: {
args: 2,
},
max: {
args: 50,
}
}
},
email: {
type: DataTypes.STRING(60),
validate: {
isEmail: true
}
}
});
};
Now to connect our model and DB, we should add the following line to ‘sequilize.js’.
const { Sequelize } = require('sequelize');// Example for sqlite
const sequelize = new Sequelize('sqlite::memory:')const models = [
// Add here all of your models
require('../models/user'),
].map(m=>m(sequelize));sequelize.sync().then(console.log('DB is synced'));module.exports = sequelize;
The sequeliz.esync() function will create the User table each time the app is running.
In a real DB this only should run for the first time.
We need to implement the model operations for the last part instead of using the hard-coded JSON file.
Let’s open the ‘controllers/user-controller.js’ file and go over one by one:
GET for all users
findAll() will retrieve all of the users in our db
exports.getAll = (req, res, next) => {
models.user.findAll().then(users => {
res.json(users)
}).catch(next);
};
GET for a single user
Since our route for this one is ‘/users/:userId’, we need to fetch the is from the params and use findByPk() with the id to get a single user. if there is no such user, return error 404 (Not found)
exports.get = async (req, res, next) => {
const id = req.params.userId;
const user = await models.user.findByPk(id)
.catch(next);
if(user) {
res.json(user);
} else {
res.status(404).send(`User with id ${id} not found!`);
}
};
POST for creation of a user
Here we need to pass the body of the request to the create() function
exports.create = (req, res, next) => {
models.user.create(req.body).then(u => res.json(u))
.catch(next);
};
PUT to update the user resource
first, we need to find the candidate we want to update, and then we use update() with the id and the user content that we want to replace
exports.update = (req, res, next) => {
const newUser = req.body;
const id = req.params.userId;
models.user.findByPk(id).then(async (user) => {
if (user) {
await models.user.update(newUser, {where: {id}})
res.status(200).send()
}else {
res.status(404).send();
}
}).catch(next);
};
Delete to delete a user resource
we will use destroy() with the id that we want to remove from our DB
exports.deleteUser = (req, res, next) => {
const id = req.params.userId;
models.user.destroy({where:{id}}).then(res.status(200).send()).catch(next);
};
Now let’s create the routes for delete and update in our ‘routes/users.js’ file.
It should look like this:
const router = require('express').Router();
const userController = require('../controllers/user-controller');router.route('/users')
.post(userController.create) // to create new subordinate resources
.get(userController.getAll); // to retrieve resource representation/information onlyrouter.route('/users/:userId')
.get(userController.get) // to retrieve resource representation/information only
.put(userController.update) // to update existing resource
.delete(userController.deleteUser) // to delete resourcesmodule.exports = router;
That’s all. By now, you should have a solid structure for a REST API service along with DB connection and ORM using Sequelize. You can test it via Postman or any other API client.
I hope you enjoyed reading.
Complete example repository on Github