Skip to content

Latest commit

 

History

History
1478 lines (1200 loc) · 33.8 KB

README.md

File metadata and controls

1478 lines (1200 loc) · 33.8 KB

My Express.js Documentation

Total Chapters are following

  1. Express.js
    1. introduction to express.js
    2. express server
    3. http methods and postman
    4. Express Router
    5. HTTP Response
    6. HTTP Request part-1
    7. HTTP Request part-2
    8. HTTP Request part-3
    9. send and receive from data
    10. Area Calculator
    11. How to set .env variables
    12. Middlewares
    13. express static Middlewares
    14. MVC pattern

Chapter 2: Express.js

  • always check the documentation of express.js
  • Express.js is a node.js framework which makes life easier
  • no more hassle of setting Content-Type
  • easy to learn and time saving facilitites available because we have ready made stuff in express.js
  • MERN Stack, NERD stack, PERN stack
  • first initialize npm : npm init -y

  • install express: npm install express

  • example

    const express = require("express");
    
    const PORT = 3000;
    
    const app = express();
    
    app.get("/", (req, res) => {
      res.send("<h1> Welcome to express server </h1>");
    });
    
    app.listen(PORT, () => {
      console.log(`server is running at http://localhost:${PORT}`);
    });
  • HTTP methods - get, post, put, patch, delete ...

  • get methods helps to get a resource or data

  • post method helps to create new resource

  • put method helps to update a resource

  • patch method helps to update single item of a resource

  • delete method helps to delete a resource

  • example

    // index.js
    
    const express = require("express");
    
    const PORT = 3000;
    
    const app = express();
    
    // http://localhost:3000/user
    
    // this will work for all http methods: get, post so use app.get() or anything specific
    app.use("/user", (req, res) => {
      res.send("<h1> Welcome to get request of express server </h1>");
    });
    
    app.get("/user", (req, res) => {
      res.send("<h1> Welcome to get request of express server </h1>");
    });
    
    app.post("/user", (req, res) => {
      res.send("<h1> Welcome to post request of express server </h1>");
    });
    
    // put is for updating multiple property
    // patch is for updating one property
    
    app.put("/user", (req, res) => {
      res.send("<h1> Welcome to put request of express server </h1>");
    });
    
    app.patch("/user", (req, res) => {
      res.send("<h1> Welcome to patch request of express server </h1>");
    });
    
    app.delete("/user", (req, res) => {
      res.send("<h1> Welcome to delete request of express server </h1>");
    });
    
    app.listen(PORT, () => {
      console.log(`server is running at http://localhost:${PORT}`);
    });
    
    // error handling
    app.use((req, res) => {
      res.send("<h2>Page not found 404</h2>");
    });
    
    app.use((err, req, res, next) => {
      console.error(err.stack);
      res.status(500).send("Something broke!");
    });
  • use morgan package for getting more info about routing on console

       step1 : npm install morgan
       step2 : const morgan = require("morgan");
       step3 : app.use(morgan("dev"));
  • example

    // step1: creates a routes folder
    // setp2: create a file name as user.routes.js
    // step3: write the following code inside user.routes.js
    const express = require("express");
    
    const router = express.Router();
    
    // /users
    router.get("/", (req, res) => {
      res.send("I am get method of user route");
    });
    
    router.post("/", (req, res) => {
      res.send("I am post method of user route");
    });
    
    router.put("/", (req, res) => {
      res.send("I am put method of user route");
    });
    
    router.patch("/", (req, res) => {
      res.send("I am patch method of user route");
    });
    
    router.delete("/", (req, res) => {
      res.send("I am delete method of user route");
    });
    
    module.exports = router;
    
    //step4: write following code inside index.js
    const express = require("express");
    
    const userRoutes = require("./routes/user.routes");
    
    const PORT = 3000;
    
    const app = express();
    
    app.use("/users", userRoutes);
    
    app.listen(PORT, () => {
      console.log(`server is running at http://localhost:${PORT}`);
    });
  • example 2

    const express = require("express");
    const router = express.Router();
    
    // how to get the path
    const path = require("path");
    
    const getFileLocation = (fileName) => {
      return path.join(__dirname, `../views/${fileName}`);
    };
    
    router.get("/", (req, res) => {
      res.sendFile(getFileLocation("index.html"));
    });
    router.get("/register", (req, res) => {
      res.sendFile(getFileLocation("register.html"));
    });
    router.get("/login", (req, res) => {
      res.sendFile(getFileLocation("login.html"));
    });
    module.exports = router;
//regular expression
// we can use 0-9 but maximum 4 digits combination
router.get("/search/:id([0-9]{4})", (req, res) => {
  res.status(200).send("serach user by id" + req.params.id);
});

// only letters allowed with maximum 5 characters
router.get("/search-username/:name([a-zA-Z]{5})", (req, res) => {
  res.status(200).send("serach user by name" + req.params.name);
});

// wild cart
router.get("*", (req, res) => {
  res.status(404).send({
    message: "url not found",
  });
});
  • package npx espress-generator
  • create a basic standard scalable folder structure with necessary codes
  • response can be text, html, json
  • res.send("some text here");
  • res.status(statuscode).json({...});
  • res.sendFile(fileName);
  • res.cookie(key, value);
  • res.clrarCookie(key);
  • res.writeHead()
  • res.write()
  • res.end()
  • res.append(key, value); this will set as response header
  • request with query parameter - req.query.parameterName

  • request with route parameters - req.params.parameterName

  • request with headers - req.header(key)

  • request with json data / form data inside body - req.body.parameterName

  • query parameter has question mark; search something on google.

    • example of query parameter - http://localhost:3000?id=101&name=anisul islam

      • we can get the value using req.query.id and req.query.name
      router.post("/", (req, res) => {
        console.log(req.query);
        console.log(req.query.id);
        console.log(req.query.name);
        res.send("I am get method of user route");
      });
  • example of routes parameter

    • http://localhost:3000/101

    • we can get the value using req.params.id

      router.post("/:id", (req, res) => {
        console.log(req.params.id);
        res.send("I am get method of user route");
      });
  • example of how to get data header requests

    router.post("/", (req, res) => {
      console.log(req.header("id"));
      res.send("I am get method of user route");
    });
  • example of request with json data

    • first add app.use(express.json()); for form data use app.use(express.urlencoded({extended: true}))
    • then access the data using req.body.parameterName
    // sending json or from data when making request
    {
      "name" : "anisul"
    }
    
    router.post("/", (req, res) => {
      res.status(201).json({
        message: "user is created",
        name: req.body.name,
      });
    });
  • create a index.html file inside views folder

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <title>home</title>
      </head>
      <body>
        <nav>
          <ul>
            <li><a href="/">Home</a></li>
          </ul>
        </nav>
        <main>
          <h1>welcome to home page</h1>
          <form action="/users" method="post">
            <label for="name">Name</label>
            <input type="text" id="name" name="name" />
            <button type="submit">Register</button>
          </form>
        </main>
      </body>
    </html>
  • load a html file

    // Inside user.routes.js file
    const express = require("express");
    const path = require("path");
    
    const router = express.Router();
    
    router.get("/", (req, res) => {
      res.sendFile(path.join(__dirname, "../views/index.html"));
    });
    
    router.post("/", (req, res) => {
      res.status(201).json({
        message: "user is created",
        name: req.body.name,
      });
    });
    
    module.exports = router;
    
    // inside index.js
    const express = require("express");
    
    const userRoutes = require("./routes/user.routes");
    
    const PORT = 3000;
    
    const app = express();
    
    app.use(express.json());
    app.use(express.urlencoded({ extended: true }));
    app.use("/users", userRoutes);
    
    app.listen(PORT, () => {
      console.log(`server is running at http://localhost:${PORT}`);
    });
  • Step 1: create an .env file in the root directory

  • Step 2: define environment variable(S) using uppercase letters and underscore if more than one word. Example - PORT DATABASE_URL

  • Step 3: Assign the values without double quotation and space PORT=3000 DATABASE_URL=mongodb+srv://medo:demo1234@cluster0.0tl3q.mongodb.net/test?retryWrites=true&w=majority

  • Step 4: you can make a comment using #

    # server port
    PORT=3000
  • Step 5: install dotenv package - npm install dotenv

  • Step 6: require dotenv - require('dotenv').config();

  • Step 7: Access the env variables from anywhere using process.env.VARIABLE_NAME. Example – process.env.PORT;

  • Optional: DotENV Extension - nice syntax highlighting in your .env files.

  • what is middleware?

    • middleware is a function; it contains request obejct, response object and next function
  • why middleware?

    • execute any code inside middleware
    • we can make changes to the request and response object
    • we can end the request and response cycle.
    • we can call the next middleware in the stack.
  • some common usage of middleware

    • user is authenticated or not
    • check user is active or not
    • data is correct / all data available
  • Types of middleware

    • Application Level middleware: app.use(), app.METHOD(); here METHOD can be get, put, post, delete, patch

    • router Level middleware: router.use(),router.METHOD()

    • built-in Level middleware: express.json(), express.urlencoded(), express.static()

    • third-party Level middleware: body-parser

    • error handling middleware

      // routes not found error
      app.use((req, res, next) => {
        res.status(404).json({
          message: "resource not found",
        });
      });
      
      // server error
      app.use((err, req, res, next) => {
        console.log(err);
        res.status(500).json({
          message: "something broke",
        });
      });
  • app.use(express.static()); helps us to use static resources such as css and image inside our server
  • MVC Architecture means Model View Controller Architecture

  • Model holds all the database related codes

  • View is what users see

  • Controller is the connection point between Model and View. basically It deals with all the logic.

  • example of mvc file structure: setup a project and install necessary packages ( npm init -y && npm install nodemon express body-parser cors)

    Screenshot 2022-04-26 at 05 13 08
  • controllers - user.controller.js

    const path = require("path");
    const users = require("../models/user.model");
    
    const getUser = (req, res) => {
      res.status(200).json({
        users,
      });
    };
    
    const createUser = (req, res) => {
      const user = {
        username: req.body.username,
        email: req.body.email,
      };
      users.push(user);
      res.status(201).json(users);
    };
    
    module.exports = { getUser, createUser };
  • models

    • user.model.js

      const users = [
        {
          username: "anisul islam",
          email: "lalalal@yahoo.com",
        },
        {
          username: "rakibul islam",
          email: "lalalal@yahoo.com",
        },
      ];
      module.exports = users;
  • routes

    • user.route.js

      const express = require("express");
      const { getUser, createUser } = require("../controllers/user.controller");
      const router = express.Router();
      
      router.get("/", getUser);
      router.post("/", createUser);
      
      module.exports = router;
  • views

    • index.html

      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <meta http-equiv="X-UA-Compatible" content="IE=edge" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <title>Document</title>
        </head>
        <body>
          <nav>
            <ul>
              <li><a href="/">Home</a></li>
              <li><a href="/api/users">Register</a></li>
            </ul>
          </nav>
          <h1>Home Page</h1>
        </body>
      </html>
      • user.html
      <!DOCTYPE html>
      <html lang="en">
        <head>
          <meta charset="UTF-8" />
          <meta http-equiv="X-UA-Compatible" content="IE=edge" />
          <meta name="viewport" content="width=], initial-scale=1.0" />
          <title>Document</title>
        </head>
        <body>
          <nav>
            <ul>
              <li><a href="/">Home</a></li>
              <li><a href="/api/users">Register</a></li>
            </ul>
          </nav>
          <h1>User Registration</h1>
          <form action="/api/user" method="post">
            <input type="text" name="username" placeholder="username" />
            <input type="email" name="email" placeholder="email" />
            <button type="submit">register</button>
          </form>
        </body>
      </html>
  • .env

    • PORT=4000
  • app.js

    const express = require("express");
    const cors = require("cors");
    const app = express();
    const bodyParser = require("body-parser");
    const userRouter = require("./routes/user.route");
    // CORS
    app.use(bodyParser.urlencoded({ extended: true }));
    app.use(bodyParser.json());
    app.use(cors());
    
    app.use("/api/users", userRouter);
    
    app.get("/", (req, res) => {
      res.sendFile(__dirname + "/views/index.html");
    });
    
    // routes not found error
    app.use((req, res, next) => {
      res.status(404).json({
        message: "resource not found",
      });
    });
    
    // server error
    app.use((err, req, res, next) => {
      console.log(err);
      res.status(500).json({
        message: "something broke",
      });
    });
    
    module.exports = app;
  • index.js

    require("dotenv").config();
    const app = require("./app");
    const PORT = process.env.PORT || 5000;
    app.listen(PORT, () => {
      console.log(`server is running at http://localhost:${PORT}`);
    });

[2.17] Validation with express-validator

  • install express-validator

Version-2 Express server with a project

Express tutorial

1. Create an express server

  • initialize npm and install packages
  • nodemon montior the changes of our code and update the server
npm init -y && npm install express
npm install -D nodemon
// index.js
const express = require("express");

const app = express();

const port = 3001;

app.listen(port, () => {
  console.log(`server is running at http://localhost:${port}`);
});
//package.json
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node src/index.js",
    "start-dev": "nodemon src/index.js"
  },

2. setting environment variables

3. Handle GET Request -> GET all products

  • routing plan using HTTP methods for RESTful Services
  • HTTP Verbs -> GET, POST, PUT, PATCH, DELETE helps us to CRUD operations
GET /products - get all the products -> 200 (ok) / 404 (not found)
GET /products/:id - get a single product -> 200 / 404
POST /products/ - create a single product -> 201 (Created) / 404 (Not Found) / 409 (Conflict -> Already Exist)
PUT /products/:id - update/replace every resource in a single product -> 200 (Ok) / 404 (Not Found) / 405 (Method Not Allowed)
PATCH /products/:id - update/Modify product itself -> 200 (Ok) / 404 (Not Found)  / 405 (Method Not Allowed)
DELETE /products/:id - delete a single product -> 200 (Ok) / 404 (Not Found) / 405 (Method Not Allowed)
// app.use()
app.use("/", (req, res) => {
  res.send("home page");
});

// now use ThunderClient extension for testing the API; you will see app.use() accept all http methods

// app.get() - will only accept get method
app.get("/", (req, res) => {
  res.send("home page");
});
let products = [
  {
    id: 1,
    title: "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops",
    price: 109.95,
  },
  {
    id: 2,
    title: "Mens Casual Premium Slim Fit T-Shirts ",
    price: 22.3,
  },
];

app.get("/products", (req, res) => {
  res.send(products);
});

4. Middleware

5. Handling error

// client error
app.use((req, res) => {
  res.send("<h2>Page not found 404</h2>");
});

// server error
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.send("Something broke!");
});

6. Response Object

  • text, HTML, JSON
res.send("hello");
res.send({
  success: true,
  user: { id: 1, name: "anisul" },
});
res.sendFile("hello.html");
app.get("/", (req, res) => {
  res.status(200).send("home page");
});

app.get("/products", (req, res) => {
  res.status(200).send(products);
});

app.use((req, res) => {
  res.status(404).send("<h2>Page not found 404</h2>");
});

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send("Something broke!");
});

8. Request Object

  • request with query parameter - req.query.parameterName

  • request with route parameters - req.params.parameterName

  • request with headers - req.header(key)

  • request with json data / form data inside body - req.body.parameterName

  • query parameter has question mark; search something on google.

  • example of query parameter - http://localhost:3000?id=101&name=anisul islam

  • we can get the value using req.query.id and req.query.name

router.post("/", (req, res) => {
  console.log(req.query);
  console.log(req.query.id);
  console.log(req.query.name);
  res.send("I am get method of user route");
});

9. Handle GET Request -> get a single product

// route parameter
app.get("/products/:id", (req, res) => {
  const singleProduct = products.find(
    (product) => product.id === Number(req.params.id)
  );
  res.status(200).send(singleProduct);
});

// query parameter
const sortItems = (sortBy, items) => {
  if (sortBy === "ASC") {
    return items.sort((a, b) => a.price - b.price);
  } else if (sortBy === "DESC") {
    return items.sort((a, b) => b.price - a.price);
  }
};

const sortItems = (sortBy, items) => {
  if (sortBy === "ASC") {
    return items.sort((a, b) => a.price - b.price);
  } else if (sortBy === "DESC") {
    return items.sort((a, b) => b.price - a.price);
  }
};

app.get("/products", (req, res) => {
  const maxPrice = Number(req.query.maxPrice);
  const sortBy = req.query.sortBy;
  let result;
  if (maxPrice) {
    result = products.filter((product) => product.price <= maxPrice);
    result = sortBy ? sortItems(sortBy, result) : result;
    res.status(200).send(result);
  } else {
    res.status(200).send(products);
  }
});

10. Handle POST Request -> create a single product

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

app.post("/products", (req, res) => {
  const newProduct = {
    id: Number(req.body.id),
    title: req.body.title,
    price: req.body.price,
  };
  products.push(newProduct);
  res.status(200).send(newProduct);
});

11. Handle DELETE Request -> delete a single product

app.delete("/products/:id", (req, res) => {
  products = products.filter((product) => product.id !== Number(req.params.id));
  res.status(200).send(products);
});

12. Handle PUT Request -> update a single product

app.put("/products/:id", (req, res) => {
  products
    .filter((product) => product.id === Number(req.params.id))
    .map((product) => {
      product.title = req.body.title;
      product.price = req.body.price;
    });
  res.status(200).send(products);
});

13. MVC Structure - Routing with express Router

  • Separation of Concerns
  • Model, View, Controllers
  • create a router folder and then create a product file where we will move all our routes
//routes -> product.js
const express = require("express");
const router = express.Router();

let products = [
  {
    id: 1,
    title: "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops",
    price: 109.95,
  },
  {
    id: 2,
    title: "Mens Casual Premium Slim Fit T-Shirts ",
    price: 22.3,
  },
  {
    id: 3,
    title: "Mens Cotton Jacket",
    price: 55.99,
  },
  { id: 4, title: "Mens Casual Slim Fit", price: 15.99 },
];

const sortItems = (sortBy, items) => {
  if (sortBy === "ASC") {
    return items.sort((a, b) => a.price - b.price);
  } else if (sortBy === "DESC") {
    return items.sort((a, b) => b.price - a.price);
  }
};

router.get("/products", (req, res) => {
  const maxPrice = Number(req.query.maxPrice);
  const sortBy = req.query.sortBy;
  let result;
  if (maxPrice) {
    result = products.filter((product) => product.price <= maxPrice);
    result = sortBy ? sortItems(sortBy, result) : result;
    res.status(200).send(result);
  } else {
    res.status(200).send(products);
  }
});

router.get("/products/:id", (req, res) => {
  const singleProduct = products.find(
    (product) => product.id === Number(req.params.id)
  );
  res.status(200).send(singleProduct);
});

router.post("/products", (req, res) => {
  const newProduct = {
    id: Number(req.body.id),
    title: req.body.title,
    price: req.body.price,
  };
  products.push(newProduct);
  res.status(200).send(newProduct);
});

router.put("/products/:id", (req, res) => {
  products
    .filter((product) => product.id === Number(req.params.id))
    .map((product) => {
      product.title = req.body.title;
      product.price = req.body.price;
    });
  res.status(200).send(products);
});

router.delete("/products/:id", (req, res) => {
  products = products.filter((product) => product.id !== Number(req.params.id));
  res.status(200).send(products);
});

module.exports = router;

// inside index.js
const productRouters = require("./router/products");
app.use(productRouters);
  • remove all the products and in index.js use app.use("/products", productRouters);

14. MVC Structure - Controller part

// routes -> products.js
const express = require("express");
const {
  getAllProducts,
  getSingleProduct,
  createProduct,
  updateProduct,
  deleteProduct,
} = require("../controller/products");
const router = express.Router();

router.get("/", getAllProducts).get("/:id", getSingleProduct);

router.post("/", createProduct);

router.put("/:id", updateProduct);

router.delete("/:id", deleteProduct);

module.exports = router;

// controller -> products.js
let products = [
  {
    id: 1,
    title: "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops",
    price: 109.95,
  },
  {
    id: 2,
    title: "Mens Casual Premium Slim Fit T-Shirts ",
    price: 22.3,
  },
  {
    id: 3,
    title: "Mens Cotton Jacket",
    price: 55.99,
  },
  { id: 4, title: "Mens Casual Slim Fit", price: 15.99 },
];

const sortItems = (sortBy, items) => {
  if (sortBy === "ASC") {
    return items.sort((a, b) => a.price - b.price);
  } else if (sortBy === "DESC") {
    return items.sort((a, b) => b.price - a.price);
  }
};

const getAllProducts = (req, res) => {
  const maxPrice = Number(req.query.maxPrice);
  const sortBy = req.query.sortBy;
  let result;
  if (maxPrice) {
    result = products.filter((product) => product.price <= maxPrice);
    result = sortBy ? sortItems(sortBy, result) : result;
    res.status(200).send(result);
  } else {
    res.status(200).send(products);
  }
};

const getSingleProduct = (req, res) => {
  const singleProduct = products.find(
    (product) => product.id === Number(req.params.id)
  );
  res.status(200).send(singleProduct);
};

const createProduct = (req, res) => {
  const newProduct = {
    id: Number(req.body.id),
    title: req.body.title,
    price: req.body.price,
  };
  products.push(newProduct);
  res.status(200).send(newProduct);
};

const updateProduct = (req, res) => {
  products
    .filter((product) => product.id === Number(req.params.id))
    .map((product) => {
      product.title = req.body.title;
      product.price = req.body.price;
    });
  res.status(200).send(products);
};

const deleteProduct = (req, res) => {
  products = products.filter((product) => product.id !== Number(req.params.id));
  res.status(200).send(products);
};

module.exports = {
  getAllProducts,
  getSingleProduct,
  createProduct,
  updateProduct,
  deleteProduct,
};

15. MVC Structure - Model part

// model -> products.js
let products = [
  {
    id: 1,
    title: "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops",
    price: 109.95,
  },
  {
    id: 2,
    title: "Mens Casual Premium Slim Fit T-Shirts ",
    price: 22.3,
  },
  {
    id: 3,
    title: "Mens Cotton Jacket",
    price: 55.99,
  },
  { id: 4, title: "Mens Casual Slim Fit", price: 15.99 },
];

module.exports = products;

15. EJS

16. Deploy on Heroku

  • const port = process.env.PORT || 3001;
  • Procfile -> web: node index.js
  • add .gitignore file -> node_modules_

17. Database

  • save(), find(), findOne(), deleteOne(), updateOne()
const mongoose = require("mongoose");
mongoose
  .connect("mongodb://localhost:27017/testProduct")
  .then(() => console.log("DB is connected"))
  .catch((error) => {
    console.log(error.message);
    process.exit(1);
  });

// schema & model
const { model } = require("mongoose");
const mongoose = require("mongoose");

const productsSchema = new mongoose.Schema({
  id: Number,
  title: String,
  price: Number,
});

module.exports = model("Product", productsSchema);

// controller
const Products = require("../model/products");

// Create
const createProduct = async (req, res) => {
  try {
    const newProduct = new Products({
      id: Number(req.body.id),
      title: req.body.title,
      price: req.body.price,
    });
    await newProduct.save();
    res.status(200).send(newProduct);
  } catch (error) {
    res.status(500).send(error.message);
  }
};

// Read
const getAllProducts = async (req, res) => {
  try {
    const products = await Products.find();
    res.status(200).send(products);
  } catch (error) {
    res.status(500).send(error.message);
  }
};

// read all the products
const getAllProducts = async (req, res) => {
  try {
    const products = await Products.find();
    const maxPrice = Number(req.query.maxPrice);
    const sortBy = req.query.sortBy;
    let result;
    if (maxPrice) {
      result = await Products.find({ price: { $lt: maxPrice } });
      result = sortBy ? sortItems(sortBy, result) : result;
      res.status(200).send(result);
    } else {
      res.status(200).send(products);
    }
  } catch (error) {
    res.status(500).send(error.message);
  }
};

// read single product by id
const getSingleProduct = async (req, res) => {
  try {
    // const id = parseInt(req.params.id);
    const singleProduct = await Products.findOne({ req.params.id });
    res.status(200).send(singleProduct);
  } catch (error) {
    res.status(500).send(error.message);
  }
};

// delete one product by id
const deleteProduct = async (req, res) => {
  try {
    const id = parseInt(req.params.id);
    const singleProduct = await Products.deleteOne({ id });
    res.status(200).send({ success: true });
  } catch (error) {
    res.status(500).send(error.message);
  }
};

// update a product by id
const updateProduct = async (req, res) => {
  try {
    await Products.updateOne(
      { id: req.params.id },
      {
        $set: {
          title: req.body.title,
          price: req.body.price,
        },
      }
    );
    res.status(200).send({ success: true });
  } catch (error) {
    res.status(500).send(error.message);
  }
};

18. cors setup

  • cors setup
npm install cors
app.use(cors())

19. connection from front end

import "./App.css";
import React, { useEffect, useState } from "react";
import NewProduct from "./components/NewProduct";

const URL = "http://localhost:4000/products";
function App() {
  const [products, setProducts] = useState([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);

  // update
  const [selectedProduct, setSelectedProduct] = useState({
    title: "",
    price: "",
  });
  const [updateFlag, setUpdateFlag] = useState(false);
  const [selectedProductId, setSelectedProductId] = useState("");

  const getAllProducts = () => {
    fetch(URL)
      .then((res) => {
        if (!res.ok) {
          throw Error("could not fetch");
        }
        return res.json();
      })
      .then((result) => {
        setProducts(result);
      })
      .catch((err) => {
        setError(err.message);
      })
      .finally(() => {
        setIsLoading(false);
      });
  };
  useEffect(() => {
    getAllProducts();
  }, []);

  const handleDelete = (id) => {
    fetch(URL + `${id}`, {
      method: "DELETE",
    })
      .then((res) => {
        if (!res.ok) {
          throw Error("could not delete");
        }
        getAllProducts();
      })
      .catch((err) => {
        setError(err.message);
      });
  };

  const addProduct = (product) => {
    fetch(URL, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(product),
    })
      .then((res) => {
        if (res.status === 201) {
          getAllProducts();
        } else {
          throw new Error("could not create new product");
        }
      })
      .catch((err) => {
        setError(err.message);
      });
  };

  const handleEdit = (id) => {
    setSelectedProductId(id);
    setUpdateFlag(true);
    const filteredData = products.filter((product) => product.id === id);
    setSelectedProduct({
      title: filteredData[0].title,
      price: filteredData[0].price,
    });
  };

  const handleUpdate = (product) => {
    console.log(selectedProductId);
    fetch(URL + `/${selectedProductId}`, {
      method: "PUT",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(product),
    })
      .then((res) => {
        if (!res.ok) {
          throw new Error("failed to update");
        }
        getAllProducts();
        setUpdateFlag(false);
      })
      .catch((err) => {
        setError(err.message);
      });
  };

  return (
    <div className="App">
      <h1>Products</h1>
      {isLoading && <h2>Loading...</h2>}
      {error && <h2>{error}</h2>}

      {updateFlag ? (
        <NewProduct
          btnText="Update Product"
          selectedProduct={selectedProduct}
          handleSubmitData={handleUpdate}
        />
      ) : (
        <NewProduct btnText="Add Product" handleSubmitData={addProduct} />
      )}

      {products.length > 0 &&
        products.map((product) => (
          <article key={product.id}>
            <h3>{product.title}</h3>
            <p>{product.price}</p>
            <button
              onClick={() => {
                handleEdit(product.id);
              }}
            >
              Edit
            </button>
            <button
              onClick={() => {
                handleDelete(product.id);
              }}
            >
              Delete
            </button>
          </article>
        ))}
    </div>
  );
}

export default App;


// NewProduct.js
import React, { useState, useEffect } from "react";
import { v4 as uuidv4 } from "uuid";

const NewProduct = ({ handleSubmitData, selectedProduct, btnText }) => {
  const [product, setProduct] = useState({
    title: "",
    price: "",
  });

  const { title, price } = product;

  useEffect(() => {
    setProduct({
      title: selectedProduct.title,
      price: selectedProduct.price,
    });
  }, [selectedProduct]);

  const handleChange = (e) => {
    const selectedField = e.target.name;
    const selectedValue = e.target.value;
    setProduct((prevState) => {
      return { ...prevState, [selectedField]: selectedValue };
    });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    const newProduct = {
      id: Number(uuidv4()),
      title: product.title,
      price: product.price,
    };
    handleSubmitData(newProduct);
    setProduct({
      title: "",
      price: "",
    });
  };

  return (
    <form onSubmit={handleSubmit}>
      <div className="field-group">
        <label htmlFor="title">Title: </label>
        <input
          type="text"
          id="title"
          name="title"
          value={title}
          onChange={handleChange}
          required
        />
      </div>
      <div className="field-group">
        <label htmlFor="price">Price: </label>
        <input
          type="text"
          id="price"
          name="price"
          value={price}
          onChange={handleChange}
          required
        />
      </div>
      <button type="submit" className="btn">
        {btnText}
      </button>
    </form>
  );
};

NewProduct.defaultProps = {
  selectedProduct: {
    title: "",
    price: "",
  },
};

export default NewProduct;

CORS Setup

REST API

  • basically we are going to return some data
  • Reperesentational State Transfer
  • Response data -> text, html, xml, json
  • HTTP methods -> GET, POST, PUT (CREATE/OVERRIDE A RESOURCE) /PATCH, DELETE
  • Routing

Updating

Lecture 1 - Course plan

Lecture 2 - basic setup

  • Node.js installation and version checkup
  • typescript, ts-node
  • nodemon : rsestart server after file changing in server
  • postman / insomnia
  • mongodb