NodeJS 8 from scratch — Part 6.2 — Api Development

Anuj Baranwal
6 min readJul 23, 2018

--

In previous parts, we discussed about —

  • basics of nodeJS
  • debugging
  • asynchronous programming
  • call stack and event loop
  • promises
  • express and deployment
  • testing with mocha and supertest

Part 1 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-1-a3c1431f1e15

Part 2 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-2-3035f8f46b09

Part 3 — https://medium.com/@anujbaranwal/nodejs-from-scratch-part-3-20956ec252a3

Part 4 — https://medium.com/@anujbaranwal/nodejs-from-scratch-part-4-d0aadf019c79

Part 5 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-5-3d3e3a84b64

Part 6.1 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-6-1-api-development-5dee11785d62

Repo — https://github.com/anuj070894/nodejs_medium_2

In the previous part of api development(6.1), we learned how to write basic crud operations with a npm module called “mongodb”. In this part and next part, we will learn how to use mongoose with nodeJS with make apis for production.

So, let’s get started

Mongoose ORM(Object Relational Mapping)

A nice way to structure your data from mongoDB in nodeJS

Setting up Mongoose

To set up mongoose, we need to install it —

Run npm install --save mongoose

in server/server.js

const mongoose = require('mongoose');mongoose.Promise = global.Promise; // We are telling the mongoose that we are using the global promisemongoose.connect('mongodb://localhost:27017/TodoApp').then(() => {console.log('Connected to database successfully...');}, (e) => {console.log('Error connecting to database...', e);});const Todo = mongoose.model('Todo', { // we will be creating a model for everything that we want to storetext: {type: String},completed: {type: Boolean},completedAt: {type: Number}}); // the object will describe the properties that we want to storeconst todo = new Todo({text: "Eat lunch",completed: false});
// the below statement will work though it not inside the then success callback of then inside connect because the mongoose buffers it and calls it only once all the setup is goodtodo.save() // responsible for actually saving the data to the database.then((result) => {if (!result) {return console.log('Unable to save the record');}console.log(result);}).catch((e) => {console.log('Some error occurred');});// another model - Userconst User = mongoose.model('User', new mongoose.Schema({name: {type: String}}));const user = new User({name: "Anuj"});user.save().then((result) => {if (!result) {return console.log('Unable to save the record');}console.log(result);}).catch((e) => {console.log('Some error occurred');});

Before we dive any further in creating the apis, we need to learn something about validators types and defaults in model

Validators are used to apply on records to prevent user from saving empty records, invalid emails, etc. http://mongoosejs.com/docs/validation.html has the list of validators in mongoose.

We can put validation on our Todo model.

var Todo = mongoose.model('Todo', { // collection name: todos
text: {
type: String,
required: true, // meaning that the attribute should be there. ValidationError
minlength: 1,
trim: true // removes any leading and trailing white spaces. trims it first, then validates it next
},
completed: {
type: Boolean,
default: false
},
completedAt: {
type: Number,
default: null
}
}); // this object will describe the various properties for our model

Type casting by mongoose —

const todo = new Todo({text: 5,completed: false});

If we save the record above, it will be saved successfully because mongoose do some type casting internally. Therefore, we should be careful about such data being inserted into the database.

Branch — 03_Init

Postman

Postman is an excellent tool for developers to build modern applications for the apis will be required

The tool can be downloaded from https://www.getpostman.com/ as chrome app (or) standalone application on mac

chrome://apps — once installed, it can be launched from here

Now, that we are aware of the basics of CRUD operations and postman tool to verify our apis, we will start building a real world todo express app in nodeJS

First, we will separate our code to make it more clear.

Branch — 04_Init

in server/db/mongoose.js

Logic to connect to mongoDB export the mongoose

in server/models/todo.js

Logic to create the todo model and export the todo

in server/models/user.js

Logic to create the user model and export the user

Install express, body-parser by running — npm install --save express

in server/server.js

Logic to import the models, mongoose, configuring the middlewares and starting the server

To know all the possible statuses, one can look at it from — https://httpstatuses.com/

Branch — 04_Init

We installed one module — body-parser — but din’t discuss it’s purpose. It provides a middleware — https://medium.com/@adamzerner/how-bodyparser-works-247897a93b90 — Beautifully explain here in this medium post

In short, what it is telling that — data from client is coming in the form of chunks to the server. Server listens to it all the time when it is coming. When it knows that it has received all the data, it listens to it as well and with bodyParser.json() as a middleware, it then parses the body and assigns it to req.body at the end

req.body = JSON.parse(data); // data - string .. at the end

Now, that we understand and have configured our express application start point, it’s time we start building our apis for real — Create, Read, Update and Delete

POST /todos — stores a todo in the database

in server/server.js

const express = require('express');const bodyParser = require('body-parser');const {mongoose} = require('./db/mongoose');const {User} = require('./models/user');const {Todo} = require('./models/todo');const app = express();app.use(bodyParser.json());app.post('/todos', (req, res) => {const todo = new Todo({text: req.body.text});todo.save().then((result) => {res.send({result}); // {result: record} .. that is being saved into the database}, (e) => {res.status(404).send();console.log('Error in saving the record - POST - TODOs ', e);});});app.listen(3000, () => {console.log('Listening on port 3000');});module.exports = {app};

So, this code allows us to make a post request at /todos with the data {"text": "Test"} and type raw/application-json from postman.

We will also write test case for this request using supertest module that we have seen in the tests chapter of our nodeJS series.

Testing Api

  • expect for assertions
  • mocha for writing tests
  • supertest for testing express applications
  • nodemon to watch for any changes

Run npm install --save-dev nodemon expect@1.20.2 mocha supertest to install the test related dependencies in our project as dev

Once installed, in server/tests/server.test.js

const expect = require('expect');const request = require('supertest');const {app} = require('../server');const {Todo} = require('../models/todo');beforeEach((done) => {Todo.remove({}).then(() => {done(); // it runs before each test. and it runs the tests only when the done is called}); // removing all the data to give a fresh start});describe('TodoApp Api Tests', () => {describe('POST /todos', () => {it('should create a new todo', (done) => {const text = 'This is a test todo';request(app).post('/todos').send({text}).expect(200).expect((res) => {expect(res.body.result.text).toBe(text);}).end((err, res) => {if (err) {return done(err);}Todo.find().then((results) => {if (!results) {return done('No result found');}expect(results.length).toBe(1);expect(results[0].text).toBe(text);done();});})});});});

in package.json

..."scripts": {"test": "mocha server/**/*.test.js","test-watch": "nodemon --exec \"npm test\""}
...

We can run the tests — npm run test-watch

Branch — 05_Init

One important thing in postman is that we can save our requests in a collection inside the postman to use it in future.

We will be proceeding with further routes in the next part, i.e., GET, DELETE and UPDATE, and their tests respectively.

So, that’s it for this part, stay tuned for the next part. In this part, we discussed about —

  • mongoose ORM
  • models, validators and defaults
  • postman
  • POST api with NodeJS
  • Testing api

Thanks. See ya :)

Part 6.3 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-6-3-api-development-9b046fed7364

Part 6.4 — https://medium.com/@anujbaranwal/nodejs-8-from-scratch-part-6-4-api-development-38d600a35ad9

--

--

Anuj Baranwal

Full Stack Web Developer @AdobeSystems Bangalore. Sometimes I code, I draw, I play, I edit and write