Todo list app backend using Node.js and Express.js

Todo list app backend using Node.js and Express.js

In this article, ill share how I build a Todo list RESTfull Web API with Complete CRUD functionality using Node.js and Express.

First let's understand what is REST, API, CRUD, NODE.js, and express are.

REST API

A REST stands for Representational State Transfer and API stands for an application programming interface. REST is an architectural style and approach to communications often used in web services development.

NODE.js

Node.js is a server-side platform built on Google Chrome's JavaScript Engine (V8 Engine) which is created for easily building fast and scalable network applications.

Express

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

CRUD

CRUD is simply an acronym used to refer to four basic operations that can be performed on database applications:

  • Create
  • Read
  • Update
  • Delete

Before start

Install Node.js and npm Package Manager To check whether Node.js is already installed on your computer, open your terminal and run the command.

node -v

If you see your Node.js version it's installed you are good to go otherwise you can follow this Official documentation

for Linux just use :

sudo apt-get install -y nodejs

CREATE A PROJECT:

Create a folder on your Desktop and call it whatever you like. Now, go ahead and open that folder in VS Code. Fire up your terminal in VS Code by clicking Ctrl + ~ and run the following command to initialize a project and create important files and folders:

npm init

touch app.js
touch .env
mkdir controllers
mkdir routes

npm install express cors
npm install --save-dev  nodemon prettier

Create server

Now let's start working on the app.js file this will be the entry point of our application now import express and cors packages and create an express app.

//Import all the necessary packages
const express = require("express");
const cors = require("cors");

//Creating and express app
const app = express();

Set host and Port for your server

//PORT and host
const host = "localhost";
const PORT = 8000;

And important middleware for our application like express.json and cors

//CORS middlware to allow cross origin resources sharing
app.use(cors());

//Middleware to convert our request data into JSON format
app.use(express.json());

To check whether API is working perfectly or not we can add a simple route handle

//Welcome to API response
app.get("/", (req, res) => {
  res.send("Hello There API is now Working");
});

You might be thinking what is this get thing will its a HTTP method in simple In a RESTful API, endpoints define the structure and usage with the GET, POST, PUT, and DELETE HTTP methods. You must organize these methods logically.

Now everything is in its place we can start the server to listen on our host and port and log something to see how it's working

//App listening on PORT 8000
app.listen(PORT, () => {
  console.log(`Server is now Started on http://${host}:${PORT}`);
});

let's add a script to develop and start our server to do that add script with the command you want to run in the package.json file, we are using nodemon to develop our application because it helps users to restart our server on the go when we add something new to the code and node for starting the server for the production

  "scripts": {
    "dev": "nodemon app.js",
    "start": "node app.js"
  }

start the server by entering a command on the terminal

➡️ npm run dev

> rest-api@1.0.0 dev
> nodemon app.js

[nodemon] 2.0.20
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node app.js`
Server is now Started on http://localhost:8000

To weather the API is working fine we can use Postman and make a GET request to the address http://localhost:8000

Screenshot from 2022-11-19 17-33-15.png Here you can see we successfully get our log message.

Create Routes

Now we know our server is working fine let's start working on the routes folder inside the routes folder create a new file name todo.routes.js and define all the routes inside the file

  1. Get all the Todos
  2. Get one Todo by Id
  3. Post new Todo
  4. Update any Todo by Id
  5. Delete any Todo by Id

and also export all these routes

// Define Router
const express = require("express");
const Router = express.Router();

//GET all the tods
Router.get("/");

//GET one Todo
Router.get("/:id");

//CREATE one todo
Router.post("/");

//UPDATE one todo
Router.put("/:id");

//DELETE one todo
Router.delete("/:id");

//Export Router
module.exports = Router;

Sending GET Request

Now we can start working on the main core logic of our application inside the controller folder and make a new file todo.controller.js. make an array of name Todo or anything you like and create a sample data inside it

//Sample Todo objects
const Todos = [
  {
    id: 1,
    title: "Study",
    completed: false,
    createdOn: new Date(),
  },
  {
    id: 2,
    title: "Coding",
    completed: true,
    createdOn: new Date(),
  },
];

To make GET endpoints work we will make two functions call getTodos and getTodo. getTodos will simply return all the JSON data we have in the Array Todos, getTodo will first find the item in the array using the req.params.id and if we successfully found it we can return it if now we can send status code 404 which mean not found

//Get all todos function
const getTodos = (req, res) => {
  res.status(201).json(Todos);
};

//Get one todo function
const getTodo = (req, res) => {
  let found = Todos.find(function (item) {
    return item.id === parseInt(req.params.id);
  });

  if (found) {
    res.status(200).json(found);
  } else {
    res.sendStatus(404);
  }
};

Screenshot from 2022-11-19 18-16-41.png

Sending POST Request

Now lets work on POST we will create a new function that will take data from req.body and push it to the Todos array with a new Id

//Create one todo function
const postTodo = (req, res) => {
  let itemIds = Todos.map((item) => item.id);

  let newId = itemIds.length > 0 ? Math.max(...itemIds) + 1 : 1;
  let newItem = {
    id: newId,
    title: req.body.title,
    completed: false,
    createdOn: new Date(),
  };

  Todos.push(newItem);
  res.status(201).json(newItem);
};

Sending PUT Request

Now let's work on updating the Task we will create a new function that will take data from req.body and we can find that element in Todos with the id we got from req.params. and simply replace it using a splice method . And you should choose PUT as HTTP verb instead of POST and send all of the required data in the request body unlike POST.

//Update one todo function
const putTodo = (req, res) => {
  let found = Todos.find((item) => {
    return item.id == parseInt(req.params.id);
  });
  if (found) {
    let updated = {
      id: found.id,
      title: req.body.title,
      completed: req.body.completed,
      createdOn: new Date(),
    };
    let targetIndex = Todos.indexOf(found);
    Todos.splice(targetIndex, 1, updated);
    res.sendStatus(204);
  } else {
    res.sendStatus(404);
  }
};

Sending DELETE Request

Now we are only left with the delete function and we can use the same logic we used before just here we will just remove the element when we found no replace.

//Delete One todo function
const deleteTodo = (req, res) => {
  let found = Todos.find((item) => {
    return item.id == parseInt(req.params.id);
  });

  if (found) {
    let targetIndex = Todos.indexOf(found);
    Todos.splice(targetIndex, 1);
  }
  res.sendStatus(204);
};

We are done with all the functions lets export all the functions now so we can use them in routes

//Export Functions
module.exports = {
  getTodos,
  getTodo,
  postTodo,
  putTodo,
  deleteTodo,
};

Set controller at each endpoint

now we can add these function to the router's endpoint so it work whenever we hit that endpoint.

// Define Router
const express = require("express");
const Router = express.Router();

//Imorting all the controllers
const TodoController = require("../controllers/Todo.controller");

//GET all the tods
Router.get("/", TodoController.getTodos);

//GET one Todo
Router.get("/:id", TodoController.getTodo);

//CREATE one todo
Router.post("/", TodoController.postTodo);

//UPDATE one todo
Router.put("/:id", TodoController.putTodo);

//DELETE one todo
Router.delete("/:id", TodoController.deleteTodo);

//Export Router
module.exports = Router;

Now we are done with the coding part let's test this project and all the functionality using Postman

Now you all must have noticed that our API works on static data and keeps it in memory. All of our GET, POST, PUT, and DELETE HTTP methods just manipulate a JSON array. So you can modify logic and data structures in these HTTP methods to use a database or whatever you want.

You can find the source code of this Web API at this github repository.

As you can see, it works just fine.

Thank you for your time and patience.