Nodejs Rest Api Flutter App

Created At: 2022-04-03 23:19:36 Updated At: 2023-04-30 23:37:00

Replace GoLang api with Nodejs api

Here we are going to build app using nodejs rest api for flutter app.

We will do this locally. So we need to install nodejs, So go ahead and install it from here https://nodejs.org/en/

We will use nodejs express framework to build our api. Go ahead a make a directory name nodejs-rest-api-flutter

Go inside the directory and run the below commands

npm install express mysql cors --save

It will install the below three modules

Express, mysql and cors

  1. Express is the nodes framework
  2. Mysql for database
  3. And cors 

What is CORS? CORS stands for Cross-Origin Resource Sharing . It allows us to relax the security applied to an API. This is done by bypassing the Access-Control-Allow-Origin headers, which specify which origins can access the API.

Building Node Server

Inside this nodejs-rest-api-flutter directory make a file called server.js and make another directory called app

Put the code inside server.js

const express = require("express");
const cors = require("cors");
const app = express();

var corsOptions = {
  origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
// simple route
app.get("/", (req, res) => {
  res.json({ message: "Welcome to dbestech nodejs flutter application." });
});
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}.`);
});

Here we want our app to use 8081 port, but if it's not available then it will use 8080. Run the command

node server.js

You will see the below message

Welcome to dbestech nodejs flutter application

 

Create Mysql Database

First go ahead and create a database. Call it task_management

Run the below command to create the database

CREATE DATABASE task_management;

And then run again another command to create a table name tasks

CREATE TABLE IF NOT EXISTS `tasks` (
  id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
 task_name varchar(255) NOT NULL,
 task_detail varchar(255),
  published BOOLEAN DEFAULT false,
 date DATETIME,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

If you can not create using command line, try to create them using phpmyadmin or mysql work bench.

 

Database Config

After that create a new folder inside the app. Name it config and then cd to config folder and create a new file name db.config.js. In this folder put the below code 

module.exports = {

  HOST: "localhost",

  USER: "root",

  PASSWORD: "123456",

  DB: “task_management”

};

 

Creating Database Model

After that, we need to connect with the database. For this reason, inside app folder, we will create a new folder name models. Cd to the models folder and create a new file called db.js and inside this put the code below

const mysql = require("mysql");

const dbConfig = require("../config/db.config.js");

// Create a connection to the database

const connection = mysql.createConnection({

  host: dbConfig.HOST,

  user: dbConfig.USER,

  password: dbConfig.PASSWORD,

  database: dbConfig.DB

});

// open the MySQL connection

connection.connect(error => {

  if (error) throw error;

  console.log("Successfully connected to the database.");

});

module.exports = connection;

 

Creating A Task Model

We need to create a task model that will represent what’s inside the database and we can operate on the database table task.

Our model will do the below things

  1. create a new Task
  2. find a Task by id
  3. get all Tasks
  4. get all published Tasks
  5. update a Task by id
  6. remove a Task
  7. remove all Tasks
const sql = require("./db.js");
// constructor
const Task = function(task) {
  this.task_name = task.task_name;
  this.task_detail = task.task_detail;
  this.date = task.date;
  this.published=task.published;
};
Task.create = (newTask, result) => {
  sql.query("INSERT INTO tasks SET ?", newTask, (err, res) => {
    if (err) {
      console.log("error: ", err);
      result(err, null);
      return;
    }
    console.log("created task: ", { id: res.insertId, ...newTask });
    result(null, { id: res.insertId, ...newTask });
  });

};
Task.findById = (id, result) => {
  console.log("The id is",id);
  sql.query(`SELECT * FROM tasks WHERE id = ${id}`, (err, res) => {
    if (err) {
      console.log("error: ", err);
      result(err, null);
      return;
    }
    if (res.length) {
      console.log("found task: ", res[0]);
      result(null, res[0]);
      return;
    }
    // not found Task with the id
    result({ kind: "not_found" }, null);
  });

};
Task.getAll = (name, result) => {
  let query = "SELECT * FROM tasks";
  if (name) {
    query += ` WHERE task_name LIKE '%${name}%'`;
  }
  sql.query(query, (err, res) => {
    if (err) {
      console.log("error: ", err);
      result(null, err);
      return;
    }
    console.log("tasks: ", res);
    result(null, res);
  });
};
Task.getAllPublished = result => {
  sql.query("SELECT * FROM tasks WHERE published=1", (err, res) => {
    if (err) {
      console.log("error: ", err);
      result(null, err);
      return;
    }
    console.log("tasks: ", res);
    result(null, res);
  });
    
};
Task.updateById = (id, task, result) => {
  sql.query(
    "UPDATE tasks SET task_name = ?, task_detail = ?, published = ? WHERE id = ?",
    [task.task_name, task.task_detail, task.published, id],
    (err, res) => {
      if (err) {
        console.log("error: ", err);
        result(null, err);
        return;
      }
      if (res.affectedRows == 0) {
        // not found Task with the id
        result({ kind: "not_found" }, null);
        return;
      }
      console.log("updated task: ", { id: id, ...task });
      result(null, { id: id, ...task });
    }
  );

};
Task.remove = (id, result) => {
  sql.query("DELETE FROM tasks WHERE id = ?", id, (err, res) => {
    if (err) {
      console.log("error: ", err);
      result(null, err);
      return;
    }
    if (res.affectedRows == 0) {
      // not found Task with the id
      result({ kind: "not_found" }, null);
      return;
    }
    console.log("deleted task with id: ", id);
    result(null, res);
  });
};
Task.removeAll = result => {
  sql.query("DELETE FROM tasks", (err, res) => {
    if (err) {
      console.log("error: ", err);
      result(null, err);
      return;
    }
    console.log(`deleted ${res.affectedRows} tasks`);
    result(null, res);
  });
};
module.exports = Task;

Inside this model we used sql.query() to run all the database query. The queries are basic create, delete, updating and select. 

You will also see that, every function just returns a result function. result function contains null, err or res. 

We send null when there's nothign to send, and err when errors found and res when we have a good response.

Define Routes

Now let’s define routes. To do that, let’s create a new folder inside app folder and name it routes. And inside that app folder create a new file name task.routes.js

This routes file will help us to point to the end point from our app. 

These are routes we define. They also represent our endoints 

  1. /tasks: GET, POST, DELETE
  2. /tasks/one:  GET
  3. /tasks/update: PUT
  4. tasks/delete/:DELETE
module.exports = app => {
  const tasks = require("../controllers/task.controller.js");
  var router = require("express").Router();
  // Create a new Task
  router.post("/", tasks.create);
  // Retrieve all tasks
  router.get("/", tasks.findAll);
  // Retrieve all published tasks
  router.get("/published", tasks.findAllPublished);
  // Retrieve a single Task with id
  router.get("/one", tasks.findOne);
  // Update a Task with id
  router.put("/update", tasks.update);
  // Delete a Task with id
  router.delete("/delete", tasks.delete);
  // Delete all tasks
  router.delete("/", tasks.deleteAll);
  app.use('/api/tasks', router);
};

Define Controller

var qs = require('querystring');
const Task = require("../models/task.model.js");
// Create and Save a new Task

exports.create = (req, res) => {
  console.log(req.body);
  // Validate request
  if (!req.body) {
    res.status(400).send({
      message: "Content can not be empty!"
    });
  }
  // Create a Task
  const task = new Task({
    task_name: req.body.task_name,
    task_detail: req.body.task_detail,
    date: req.body.date,
    published:req.body.published || 0
  });
  // Save Task in the database
  Task.create(task, (err, data) => {
    if (err)
      res.status(500).send({
        message:
          err.message || "Some error occurred while creating the Task."
      });
    else res.send(data);
  });
};
// Retrieve all tasks from the database (with condition).
exports.findAll = (req, res) => {
  const title = req.query.name;
  Task.getAll(title, (err, data) => {
    if (err)
      res.status(500).send({
        message:
          err.message || "Some error occurred while retrieving tasks."
      });
    else res.send(data);
  });
};
exports.findAllPublished = (req, res) => {
  Task.getAllPublished((err, data) => {
    if (err)
      res.status(500).send({
        message:
          err.message || "Some error occurred while retrieving tasks."
      });
    else res.send(data);
  });


};
// Find a single Task with a id
exports.findOne = (req, res) => {
  console.log(req.query.id);
  Task.findById(req.query.id, (err, data) => {
    if (err) {
      if (err.kind === "not_found") {
        res.status(404).send({
          message: `Not found Task with id ${req.query.id}.`
        });
      } else {
        res.status(500).send({
          message: "Error retrieving Task with id " + req.params.id
        });
      }
    } else res.send(data);
  });
};

// Update a Task identified by the id in the request
exports.update = (req, res) => {
  // Validate Request
  if (!req.body) {
    res.status(400).send({
      message: "Content can not be empty!"
    });
  }


  console.log(req.body);
  Task.updateById(
    req.query.id,
    new Task(req.body),
    (err, data) => {
      if (err) {
        if (err.kind === "not_found") {
          res.status(404).send({
            message: `Not found Tutorial with id ${req.query.id}.`
          });
        } else {
          res.status(500).send({
            message: "Error updating Tutorial with id " + req.query.id
          });
        }
      } else res.send(data);
    }
  );

};
// Delete a Task with the specified id in the request
exports.delete = (req, res) => {
  Task.remove(req.query.id, (err, data) => {
    if (err) {
      if (err.kind === "not_found") {
        res.status(404).send({
          message: `Not found Task with id ${req.query.id}.`
        });
      } else {
        res.status(500).send({
          message: "Could not delete Task with id " + req.query.id
        });
      }
    } else res.send({ message: `Task was deleted successfully!` });
  });

};
// Delete all tasks from the database.
exports.deleteAll = (req, res) => {
  Task.removeAll((err, data)=>{
    if(err){
      res.status(500).send({
        message:err.message || "Could not finish the operation"
      });

    }else{
      res.send({
        message:"Removed all task successfully"
      });
    }
  })
};

Controller would sit between the routes and models. From our app or webapp, nodejs server will be hit, first time it will hit the end points and each end point will find specific method in the controller and inside this method, it will find a method that exist in the model.

Comment

  • r
    ra2886380@gmail.com

    2024-09-11 10:52:22

    Saved me. why and what for - the importation of this package var qs = require('querystring'); in task.controller.js

  • r
    ra2886380@gmail.com

    2024-09-11 10:52:21

    Saved me. why and what for - the importation of this package var qs = require('querystring'); in task.controller.js

Add Reviews