main d876ccc661b5 cached
91 files
175.0 KB
41.0k tokens
21 symbols
1 requests
Download .txt
Repository: hiteshchoudhary/pro-backend-developer
Branch: main
Commit: d876ccc661b5
Files: 91
Total size: 175.0 KB

Directory structure:
gitextract_2i27geyc/

├── formsandimages/
│   ├── index.js
│   ├── package.json
│   └── views/
│       ├── getform.ejs
│       └── postform.ejs
├── lcoauthsystem/
│   ├── app.js
│   ├── config/
│   │   └── database.js
│   ├── index.js
│   ├── middleware/
│   │   └── auth.js
│   ├── model/
│   │   └── user.js
│   └── package.json
├── lcopassportgoogle/
│   ├── index.js
│   ├── model/
│   │   └── user.js
│   ├── package.json
│   ├── passport/
│   │   └── passport.js
│   ├── routes/
│   │   └── auth.js
│   └── views/
│       ├── home.ejs
│       └── login.ejs
├── mydocslco/
│   ├── index.js
│   ├── nodemon.json
│   ├── package.json
│   └── swagger.yaml
├── razorpay/
│   ├── index.js
│   ├── package.json
│   └── public/
│       └── index.html
├── readme.md
├── socialapp/
│   ├── .gitignore
│   ├── index.js
│   ├── nodemon.json
│   ├── package.json
│   └── swagger.yaml
└── tshirtstore/
    ├── .gitignore
    ├── README.md
    ├── app.js
    ├── config/
    │   └── db.js
    ├── controllers/
    │   ├── homeController.js
    │   ├── orderController.js
    │   ├── paymentController.js
    │   ├── productController.js
    │   └── userController.js
    ├── index.js
    ├── lcotshirtstore/
    │   ├── .gitignore
    │   ├── app.js
    │   ├── config/
    │   │   └── db.js
    │   ├── controllers/
    │   │   ├── homeController.js
    │   │   ├── orderController.js
    │   │   ├── paymentController.js
    │   │   ├── productController.js
    │   │   └── userController.js
    │   ├── index.js
    │   ├── middlewares/
    │   │   ├── bigPromise.js
    │   │   └── user.js
    │   ├── models/
    │   │   ├── order.js
    │   │   ├── product.js
    │   │   └── user.js
    │   ├── nodemon.json
    │   ├── package.json
    │   ├── routes/
    │   │   ├── home.js
    │   │   ├── order.js
    │   │   ├── payment.js
    │   │   ├── product.js
    │   │   └── user.js
    │   ├── swagger.yaml
    │   ├── utils/
    │   │   ├── cookieToken.js
    │   │   ├── customError.js
    │   │   ├── demotest.js
    │   │   ├── emailHelper.js
    │   │   ├── testOrder.json
    │   │   └── whereClause.js
    │   └── views/
    │       └── signuptest.ejs
    ├── middlewares/
    │   ├── bigPromise.js
    │   ├── productionError.js
    │   └── user.js
    ├── models/
    │   ├── order.js
    │   ├── product.js
    │   └── user.js
    ├── nodemon.json
    ├── package.json
    ├── routes/
    │   ├── home.js
    │   ├── order.js
    │   ├── payment.js
    │   ├── product.js
    │   └── user.js
    ├── swagger.yaml
    ├── utils/
    │   ├── cookieToken.js
    │   ├── customError.js
    │   ├── demotest.js
    │   ├── emailHelper.js
    │   ├── testOrder.json
    │   └── whereClause.js
    └── views/
        ├── home.ejs
        └── signuptest.ejs

================================================
FILE CONTENTS
================================================

================================================
FILE: formsandimages/index.js
================================================
const express = require("express");
const fileUpload = require("express-fileupload");
const cloudinary = require("cloudinary").v2;
const app = express();

cloudinary.config({
  // cloud_name: processs.env.CLOUD_NAME
  cloud_name: "dk92l1yoc",
  api_key: "769888332458168",
  api_secret: "7Kh-q81hHRdyDNiBxISrouGEFCo",
});

app.set("view engine", "ejs");

//middleware
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
  fileUpload({
    useTempFiles: true,
    tempFileDir: "/tmp/",
  })
);

app.get("/myget", (req, res) => {
  console.log(req.body);

  res.send(req.body);
});

app.post("/mypost", async (req, res) => {
  console.log(req.body);
  console.log(req.files);

  let result;
  let imageArray = [];

  // case - multiple images

  if (req.files) {
    for (let index = 0; index < req.files.samplefile.length; index++) {
      let result = await cloudinary.uploader.upload(
        req.files.samplefile[index].tempFilePath,
        {
          folder: "users",
        }
      );

      imageArray.push({
        public_id: result.public_id,
        secure_url: result.secure_url,
      });
    }
  }

  // ### use case for single image
  // let file = req.files.samplefile;
  // result = await cloudinary.uploader.upload(file.tempFilePath, {
  //   folder: "users",
  // });

  console.log(result);

  details = {
    firstname: req.body.firstname,
    lastname: req.body.lastname,
    result,
    imageArray,
  };
  console.log(details);

  res.send(details);
});

// just to render the forms
app.get("/mygetform", (req, res) => {
  res.render("getform");
});
app.get("/mypostform", (req, res) => {
  res.render("postform");
});

app.listen(4000, () => console.log(`Server is runnning at port 4000`));


================================================
FILE: formsandimages/package.json
================================================
{
  "name": "formsandimages",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cloudinary": "^1.27.1",
    "ejs": "^3.1.6",
    "express": "^4.17.1",
    "express-fileupload": "^1.2.1"
  },
  "devDependencies": {
    "nodemon": "^2.0.13"
  }
}


================================================
FILE: formsandimages/views/getform.ejs
================================================
<!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">
    <!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <title>GET form</title>
</head>
<body class="bg-dark text-white">
    <div class="container mt-4 col-4 col-offset-6">
        <h1 class="display-3">GET form</h1>
        <form method="GET" action="/myget">
            <div class="mb-3">
              <label for="firstname" class="form-label">firstname</label>
              <input type="text" name="firstname" class="form-control" id="firstname" aria-describedby="emailHelp">
              <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
            </div>
            <div class="mb-3">
              <label for="lastname" class="form-label">lastname</label>
              <input type="text" name="lastname" class="form-control" id="lastname">
            </div>
            
            <button type="submit" class="btn btn-primary">Submit</button>
          </form>
    </div>
</body>
</html>

================================================
FILE: formsandimages/views/postform.ejs
================================================
<!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">
    <!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <title>GET form</title>
</head>
<body class="bg-dark text-white">
    <div class="container mt-4 col-4 col-offset-6">
        <h1 class="display-3">POST form</h1>
        <form method="POST" action="/mypost" enctype="multipart/form-data">
            <div class="mb-3">
              <label for="firstname" class="form-label">firstname</label>
              <input type="text" name="firstname" class="form-control" id="firstname" aria-describedby="emailHelp">
              <div id="emailHelp" class="form-text">We'll never share your email with anyone else.</div>
            </div>
            <div class="mb-3">
              <label for="lastname" class="form-label">lastname</label>
              <input type="text" name="lastname" class="form-control" id="lastname">
            </div>
            <div class="mb-3">
              <label for="samplefile" class="form-label">samplefile</label>
              <input type="file" name="samplefile" multiple class="form-control" id="lastname">
            </div>
            
            <button type="submit" class="btn btn-primary">Submit</button>
          </form>
    </div>
</body>
</html>

================================================
FILE: lcoauthsystem/app.js
================================================
require("dotenv").config();
require("./config/database").connect();
const express = require("express");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
var cookieParser = require("cookie-parser");
const User = require("./model/user");
const auth = require("./middleware/auth");

const app = express();
app.use(express.json());
app.use(cookieParser());

app.get("/", (req, res) => {
  res.send("<h1>Hello from auth system - LCO</h1>");
});

app.post("/register", async (req, res) => {
  try {
    const { firstname, lastname, email, password } = req.body;

    if (!(email && password && firstname && lastname)) {
      res.status(400).send("All fields are required");
    }

    const existingUser = await User.findOne({ email }); // PROMISE

    if (existingUser) {
      res.status(401).send("User already exists");
    }

    const myEncPassword = await bcrypt.hash(password, 10);

    const user = await User.create({
      firstname,
      lastname,
      email: email.toLowerCase(),
      password: myEncPassword,
    });

    //token
    const token = jwt.sign(
      { user_id: user._id, email },
      process.env.SECRET_KEY,
      {
        expiresIn: "2h",
      }
    );
    user.token = token;
    //update or not in DB

    // handle password situation
    user.password = undefined;

    // send token or send just success yes and redirect - choice
    res.status(201).json(user);
  } catch (error) {
    console.log(error);
  }
});

app.post("/login", async (req, res) => {
  try {
    const { email, password } = req.body;

    if (!(email && password)) {
      res.status(400).send("Field is missing");
    }

    const user = await User.findOne({ email });

    // if(!user){
    //   res.status(400).send("You are not registered in our app")
    // }

    if (user && (await bcrypt.compare(password, user.password))) {
      const token = jwt.sign(
        { user_id: user._id, email },
        process.env.SECRET_KEY,
        {
          expiresIn: "2h",
        }
      );
      user.token = token;
      user.password = undefined;
      // res.status(200).json(user);

      // if you want to use cookies
      const options = {
        expires: new Date(Date.now() + 3 * 24 * 60 * 60 * 1000),
        httpOnly: true,
      };

      res.status(200).cookie("token", token, options).json({
        success: true,
        token,
        user,
      });
    }

    res.sendStatus(400).send("email or password is incorrect");
  } catch (error) {
    console.log(error);
  }
});

app.get("/dashboard", auth, (req, res) => {
  res.send("Welcome to secret information");
});

module.exports = app;


================================================
FILE: lcoauthsystem/config/database.js
================================================
const mongoose = require("mongoose");

const { MONGODB_URL } = process.env;

exports.connect = () => {
  mongoose
    .connect(MONGODB_URL, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    })
    .then(console.log(`DB CONNECTED SUCCESSFULLY`))
    .catch((error) => {
      console.log(`DB CONNECTION FAILED`);
      console.log(error);
      process.exit(1);
    });
};


================================================
FILE: lcoauthsystem/index.js
================================================
const app = require("./app");
const { PORT } = process.env;

app.listen(PORT, () => console.log(`Server is running at port ${PORT}...`));


================================================
FILE: lcoauthsystem/middleware/auth.js
================================================
const jwt = require("jsonwebtoken");

//model is optional

const auth = (req, res, next) => {
  console.log(req.cookies);
  const token =
    req.cookies.token ||
    req.body.token ||
    req.header("Authorization").replace("Bearer ", "");

  if (!token) {
    return res.status(403).send("token is missing");
  }

  try {
    const decode = jwt.verify(token, process.env.SECRET_KEY);
    console.log(decode);
    req.user = decode;
    // bring in info from DB
  } catch (error) {
    return res.status(401).send("Invalid Token");
  }
  return next();
};

module.exports = auth;


================================================
FILE: lcoauthsystem/model/user.js
================================================
const mongoose = require("mongoose");

const userSchema = new mongoose.Schema({
  firstname: {
    type: String,
    default: null,
  },
  lastname: {
    type: String,
    default: null,
  },
  email: {
    type: String,
    unique: true,
  },
  password: {
    type: String,
  },
  token: {
    type: String,
  },
});

module.exports = mongoose.model("user", userSchema);


================================================
FILE: lcoauthsystem/package.json
================================================
{
  "name": "lcoauthsystem",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "bcryptjs": "^2.4.3",
    "cookie-parser": "^1.4.5",
    "dotenv": "^10.0.0",
    "express": "^4.17.1",
    "jsonwebtoken": "^8.5.1",
    "mongoose": "^6.0.11"
  },
  "devDependencies": {
    "nodemon": "^2.0.13"
  }
}


================================================
FILE: lcopassportgoogle/index.js
================================================
const express = require("express");
const mongoose = require("mongoose");
const auth = require("./routes/auth");
const passportConfig = require("./passport/passport");
const passport = require("passport");
const cookieSession = require("cookie-session");
const app = express();

//connect to the DB
mongoose.connect("mongodb://127.0.0.1:27017/passport", () =>
  console.log("DB CONNECTED")
);

app.use(
  cookieSession({
    maxAge: 3 * 24 * 60 * 60 * 1000,
    keys: ["thisislcotokenkey"], // dotenv
  })
);

app.use(passport.initialize());
app.use(passport.session());

const isLoggedIn = (req, res, next) => {
  if (!req.user) {
    res.redirect("/auth/login");
  }
  next();
};

app.set("view engine", "ejs");
app.use("/auth", auth);

app.get("/", isLoggedIn, (req, res) => {
  res.render("home");
});

app.listen(4000, () => console.log(`Server is running at port 4000...`));


================================================
FILE: lcopassportgoogle/model/user.js
================================================
const mongoose = require("mongoose");

const userSchema = new mongoose.Schema({
  name: String,
  googleId: String,
  email: String,
});

module.exports = mongoose.model("User", userSchema);


================================================
FILE: lcopassportgoogle/package.json
================================================
{
  "name": "lcopassportgoogle",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cookie-session": "^1.4.0",
    "ejs": "^3.1.6",
    "express": "^4.17.1",
    "mongoose": "^6.0.12",
    "passport": "^0.5.0",
    "passport-google-oauth20": "^2.0.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.14"
  }
}


================================================
FILE: lcopassportgoogle/passport/passport.js
================================================
const passport = require("passport");
const User = require("../model/user");

var GoogleStrategy = require("passport-google-oauth20").Strategy;

passport.serializeUser(function (user, done) {
  done(null, user.id);
});

passport.deserializeUser(function (id, done) {
  User.findById(id, function (err, user) {
    done(err, user);
  });
});

passport.use(
  new GoogleStrategy(
    {
      clientID: "learncodeonline",
      clientSecret: "aSecretGoesHere",
      callbackURL: "http://localhost:4000/auth/google/callback",
    },
    (accessToken, refreshToken, profile, next) => {
      console.log("MY PROFILE", profile._json.email);
      User.findOne({ email: profile._json.email }).then((user) => {
        if (user) {
          console.log("User already exits in DB", user);
          next(null, user);
          // cookietoken()
        } else {
          User.create({
            name: profile.displayName,
            googleId: profile.id,
            email: profile._json.email,
          })
            .then((user) => {
              console.log("New User", user);
              next(null, user);
              // cookietoken()
            })
            .catch((err) => console.log(err));
        }
      });

      //   next();
    }
  )
);


================================================
FILE: lcopassportgoogle/routes/auth.js
================================================
const router = require("express").Router();
const passport = require("passport");

router.get("/login", (req, res) => {
  res.render("login");
});

router.get("/logout", (req, res) => {
  req.logout();
  res.redirect("/auth/login");
});

router.get(
  "/google",
  passport.authenticate("google", {
    scope: ["profile", "email"],
  }),
  (req, res) => {
    res.send("login with google");
  }
);

router.get("/google/callback", passport.authenticate("google"), (req, res) => {
  res.send(req.user);
});

module.exports = router;


================================================
FILE: lcopassportgoogle/views/home.ejs
================================================
<!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">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>LCO</title>
</head>
<body class="bg-dark text-white">
    <div class="container">
        <h1>LCO Social login</h1>
    </div>
    <div class="container">
        <a href="/auth/logout" class="btn btn-outline-success">Logout</a>
        <a href="/auth/login" class="btn btn-outline-success">Login</a>
        <a href="/" class="btn btn-outline-success">Home</a>
    </div>
    <div class="container">
        <h1 class="display-1">You are at HOME page</h1>
    </div>
</body>
</html>

================================================
FILE: lcopassportgoogle/views/login.ejs
================================================
<!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">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>LCO</title>
</head>
<body class="bg-dark text-white">
    <div class="container">
        <h1>LCO Social login</h1>
    </div>
    <div class="container">
        <a href="/auth/logout" class="btn btn-outline-success">Logout</a>
        <a href="/auth/login" class="btn btn-outline-success">Login</a>
        <a href="/" class="btn btn-outline-success">Home</a>
    </div>
    <div class="container mt-4">
        <a href="/auth/google" class="btn btn-danger">google</a>
        
    </div>
</body>
</html>

================================================
FILE: mydocslco/index.js
================================================
const express = require("express");

const app = express();

const swaggerUi = require("swagger-ui-express");
const YAML = require("yamljs");
const swaggerDocument = YAML.load("./swagger.yaml");
const fileUpload = require("express-fileupload");

app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument));
app.use(express.json());
app.use(fileUpload());

let courses = [
  {
    id: "11",
    name: "Learn Reactjs",
    price: 299,
  },
  {
    id: "22",
    name: "Learn Angular",
    price: 399,
  },
  {
    id: "33",
    name: "Learn Django",
    price: 499,
  },
];

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

app.get("/api/v1/lco", (req, res) => {
  res.send("hello from lco docs");
});

app.get("/api/v1/lcoobject", (req, res) => {
  res.send({ id: "55", name: "Learn Backend", price: 999 });
});

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

app.get("/api/v1/mycourse/:courseId", (req, res) => {
  const myCourse = courses.find((course) => course.id === req.params.courseId);
  res.send(myCourse);
});

app.post("/api/v1/addCourse", (req, res) => {
  console.log(req.body);
  courses.push(req.body);
  res.send(true);
});

app.get("/api/v1/coursequery", (req, res) => {
  let location = req.query.location;
  let device = req.query.device;

  res.send({ location, device });
});

app.post("/api/v1/courseupload", (req, res) => {
  console.log(req.headers);
  const file = req.files.file;
  console.log(file);
  let path = __dirname + "/images/" + Date.now() + ".jpg";

  file.mv(path, (err) => {
    res.send(true);
  });
});

app.listen(4000, () => console.log(`Server is running at port 4000...`));


================================================
FILE: mydocslco/nodemon.json
================================================
{
  "ext": ".js, .jsx, .yaml"
}


================================================
FILE: mydocslco/package.json
================================================
{
  "name": "mydocslco",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "express-fileupload": "^1.2.1",
    "nodemon": "^2.0.13",
    "swagger-ui-express": "^4.1.6",
    "yamljs": "^0.3.0"
  }
}


================================================
FILE: mydocslco/swagger.yaml
================================================
openapi: "3.0.0"
info:
  title: learn express and swagger - LearnCodeOnline
  description: LCO - a course segment about writing docs
  version: 1.1.0
  contact:
    email: hitesh@google.com
    url: "https://lco.dev"

# servers:
#   - url: "https://localhost:4000/api/v1"
#     description: for local host - secure
#   - url: "http://localhost:4000/api/v1"
#     description: for local host - regular

servers:
  - url: "{protocol}://localhost:4000/api/{version}"
    description: for local host 
    variables:
      version:
        enum:
          - v1
          - v2
        default: v1
      protocol:
        enum:
          - http
          - https
        default: http

components:
  securitySchemes:
    cookieAuth:
      type: apiKey
      in: cookie
      name: token
    BearerAuth:
      type: http
      scheme: bearer

paths:
  /lco:
    get:
      tags:
        - String
      summary: returns a greet message from LCO
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: string
                example: "mystring"
        400:
          description: Bad request
        500:
          description: internal server error
  
  /lcoobject:
    get:
      tags:
        - Object
      summary: returns a unique course 
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  name:
                    type: string
                  price:
                    type: number
        400:
          description: Bad request
        500:
          description: internal server error

  /courses:
    get:
      tags:
        - Array
      summary: returns all courses
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: string
                    name:
                      type: string
                    price:
                      type: number
        400:
          description: Bad request
        500:
          description: internal server error
  /mycourse/{courseId}:
    get:
      tags:
        - String
      summary: returns course based on request id
      parameters:
        - name: courseId
          in: path
          required: true
          default: 22
          schema:
            type: string
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  name:
                    type: string
                  price:
                    type: number
        400:
          description: Bad request
        500:
          description: internal server error

  /addCourse:
    post:
      tags:
        - String
      summary: adds a new course to existing courses
      consumes:
        - application/json
      produces:
        - application/json
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
                name:
                  type: string
                price:
                  type: number
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: boolean
                
        400:
          description: Bad request
        500:
          description: internal server error

  /coursequery:
    get:
      tags:
        - String
      summary: trying to learn about query
      parameters:
        - name: location
          in: query
          required: true
          schema:
            type: string
            enum: [delhi, london, jaipur]
        - name: device
          in: query
          required: true
          schema:
            type: string
            enum: [web, mobile]
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  location:
                    type: string
                  device:
                    type: string
                
        400:
          description: Bad request
        500:
          description: internal server error

  /courseupload:
    post:
      tags:
        - String
      summary: uploading course image
      parameters:
        - in: header
          name: auth
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
      responses:
        200:
          description: All good success
              
        400:
          description: Bad request
        500:
          description: internal server error



================================================
FILE: razorpay/index.js
================================================
const express = require("express");
const Razorpay = require("razorpay");
const app = express();
app.use(express.static("./public"));
app.use(express.json());

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

app.post("/order", async (req, res) => {
  const amount = req.body.amount;

  var instance = new Razorpay({
    key_id: "rzp_test_DfhbmLCnKJDWxO",
    key_secret: "YFZxjAWfyFyJidZXbXLu2UN0",
    // this needs to go in .env
  });

  var options = {
    amount: amount * 100, // amount in the smallest currency unit
    currency: "INR",
    receipt: "order_rcptid_11",
  };
  //   instance.orders.create(options, function (err, order) {
  //     console.log(order);
  //   });

  const myOrder = await instance.orders.create(options);

  res.status(200).json({
    success: true,
    amount,
    order: myOrder,
  });
});

app.listen(4000, () => console.log(`Server is running at port 4000`));


================================================
FILE: razorpay/package.json
================================================
{
  "name": "razorpay",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1",
    "razorpay": "^2.0.7"
  }
}


================================================
FILE: razorpay/public/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>
    <style>
        body {
            background-color: rgb(25, 25, 25);
            color: aliceblue;
        }
    </style>
</head>
<body>
    <h1>Testing public folder</h1>

    <button id="rzp-button1">Pay</button>
<script src="https://checkout.razorpay.com/v1/checkout.js"></script>
<script>

const rpbutton = document.getElementById('rzp-button1')

rpbutton.addEventListener('click', async(event) => {
    const response = await fetch('/order', {
        method: "POST",
        headers: {
            'Content-Type': "application/json"
        },
        body: JSON.stringify({amount: 500})
    })

    const convertReponse = await response.json()

    const {order} = convertReponse;

    var options = {
    key: "rzp_test_DfhbmLCnKJDWxO", // Enter the Key ID generated from the Dashboard
    amount: 50000, // Amount is in currency subunits. Default currency is INR. Hence, 50000 refers to 50000 paise
    currency: "INR",
    
    order_id: order.id, //This is a sample Order ID. Pass the `id` obtained in the response of Step 1
    handler: function (response){
        alert(response.razorpay_payment_id);
        alert(response.razorpay_order_id);
        alert(response.razorpay_signature)
    },
   
};

var rzp1 = new Razorpay(options);

rzp1.open()
})




</script>
    
</body>
</html>

================================================
FILE: readme.md
================================================
# welcome to pro backend developer course code files

## If you like this course, please drop a thanks node at my social profiles.

[CoderCommunity](https://web.codercommunity.io)

[Website](https://hiteshchoudahry.com)

[Instagram](https://instagram.com/hiteshchoudharyofficial)

of course there are bugs in these code files. As you teach you focus more on concept and less on production level execution. If you find any bug, consider that as your challenge to fix them.

================================================
FILE: socialapp/.gitignore
================================================
node_modules/

================================================
FILE: socialapp/index.js
================================================
const express = require("express");
const format = require("date-format");
const app = express();

// swagger docs related
const swaggerUi = require("swagger-ui-express");
const YAML = require("yamljs");
const swaggerDocument = YAML.load("./swagger.yaml");

app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument));

const PORT = process.env.PORT || 4000;

app.get("/", (req, res) => {
  res.status(200).send("<h1>Hello from LCO</h1>");
});

app.get("/api/v1/instagram", (req, res) => {
  const instaSocial = {
    username: "hiteshchoudharyOfficial",
    folowers: 66,
    follows: 70,
    date: format.asString("dd[MM] - hh:mm:ss", new Date()),
  };

  res.status(200).json(instaSocial);
});

app.get("/api/v1/facebook", (req, res) => {
  const instaSocial = {
    username: "hiteshchoudharyPage",
    folowers: 88,
    follows: 10,
    date: format.asString("dd[MM] - hh:mm:ss", new Date()),
  };

  res.status(200).json(instaSocial);
});

app.get("/api/v1/linkedin", (req, res) => {
  const instaSocial = {
    username: "hiteshchoudhary",
    folowers: 800,
    follows: 80,
    date: new Date(),
  };

  res.status(200).json(instaSocial);
});

app.get("/api/v1/:token", (req, res) => {
  console.log(req.params.token);
  res.status(200).json({ param: req.params.token });
});

app.listen(PORT, () => {
  console.log(`Server is running at ${PORT}`);
});


================================================
FILE: socialapp/nodemon.json
================================================
{
  "ext": ".js, .json, .yaml, .jsx"
}


================================================
FILE: socialapp/package.json
================================================
{
  "name": "socialapp",
  "version": "1.0.0",
  "description": "a basic social media app",
  "main": "index.js",
  "scripts": {
    "start": "nodemon index.js"
  },
  "keywords": [
    "express",
    "api"
  ],
  "author": "Hitesh Choudhary",
  "license": "ISC",
  "dependencies": {
    "date-format": "^3.0.0",
    "express": "^4.17.1",
    "swagger-ui-express": "^4.1.6",
    "yamljs": "^0.3.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.13"
  }
}


================================================
FILE: socialapp/swagger.yaml
================================================
openapi: 3.0.0
info:
  title: Social App
  description: Our fist Social app at LCO - Hitesh
  version: 1.0.1

servers:
  - url: http://localhost:4000/api/v1
    description: localhost version of our app
  - url: https://localhost:4000/api/v1
    description: this is just a dummy api url, it doesn't work

components:
  securitySchemes:
    BasicAuth:
      type: http
      scheme: basic
    BearerAuth:
      type: http
      scheme: bearer

paths:
  /instagram:
    get:
      summary: returns username, followers and follows
      responses:
        '200': # status code
          description: returns an object
          content:
            application/json:
              schema:
                type: object
                properties:
                  username:
                    type: string
                  followers:
                    type: string
                  follows:
                    type: string
    post:
      summary: returns username, followers and follows
      responses:
        '200': # status code
          description: returns an object
          content:
            application/json:
              schema:
                type: object
                properties:
                  username:
                    type: string
                  followers:
                    type: string
                  follows:
                    type: string
  /{token}:
    get:
      summary: returns whatever is there in parameters
      parameters:
        - name: token
          default: 5
          in: path
          schema:
            type: string
      responses:
        '200': # status code
          description: returns an object
          content:
            application/json:
              schema:
                type: object
                properties:
                  params:
                    type: string
                  


================================================
FILE: tshirtstore/.gitignore
================================================
.env
node_modules/

================================================
FILE: tshirtstore/README.md
================================================
# Tshirt store for pro backend developer course

Please add env variables for the project

---

### PORT=4000

### DB_URL=

### JWT_SECRET=

### JWT_EXPIRY=

### COOKIE_TIME=

### CLOUDINARY_NAME=

### CLOUDINARY_API_KEY=

### CLOUDINARY_API_SECRET=

### SMTP_HOST=

### SMTP_PORT=

### SMTP_USER=

### SMTP_PASS=

### STRIPE_API_KEY=

### STRIPE_SECRET=

### RAZORPAY_API_KEY=

### RAZORPAY_SECRET=

---

[LearnCodeOnline](https://courses.learncodeonline.in/learn)
updat the variables before deploying


================================================
FILE: tshirtstore/app.js
================================================
const express = require("express");
require("dotenv").config();
const app = express();
const morgan = require("morgan");
const cookieParser = require("cookie-parser");
const fileUpload = require("express-fileupload");

//for swagger documentation
const swaggerUi = require("swagger-ui-express");
const YAML = require("yamljs");
const swaggerDocument = YAML.load("./swagger.yaml");
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument));

//custom error middleware for easy front end
const productionError = require("./middlewares/productionError");

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

//cookies and file middleware
app.use(cookieParser());
app.use(
  fileUpload({
    useTempFiles: true,
    tempFileDir: "/tmp/",
  })
);

//temp check
app.set("view engine", "ejs");

//morgan middleware
app.use(morgan("tiny"));

//import all routes here
const home = require("./routes/home");
const user = require("./routes/user");
const product = require("./routes/product");
const payment = require("./routes/payment");
const order = require("./routes/order");

//router middleware
app.use("/api/v1", home);
app.use("/api/v1", user);
app.use("/api/v1", product);
app.use("/api/v1", payment);
app.use("/api/v1", order);

app.get("/signuptest", (req, res) => {
  res.render("signuptest");
});

app.get("/", (req, res) => {
  res.render("home");
});

//to handle production error
app.use(productionError);

// export app js
module.exports = app;


================================================
FILE: tshirtstore/config/db.js
================================================
const mongoose = require("mongoose");

const connectWithDb = () => {
  mongoose
    .connect(process.env.DB_URL, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    })
    .then(console.log(`DB GOT CONNECTED`))
    .catch((error) => {
      console.log(`DB CONNECTION ISSUES`);
      console.log(error);
      process.exit(1);
    });
};

module.exports = connectWithDb;


================================================
FILE: tshirtstore/controllers/homeController.js
================================================
const BigPromise = require("../middlewares/bigPromise");

exports.home = BigPromise(async (req, res) => {
  // const db = await something()
  res.status(200).json({
    success: true,
    greeting: "Hello from API",
  });
});

exports.homeDummy = async (req, res) => {
  try {
    // const db = await something()

    res.status(200).json({
      success: true,
      greeting: "this is another dummy route",
    });
  } catch (error) {
    console.log(error);
  }
};


================================================
FILE: tshirtstore/controllers/orderController.js
================================================
const Order = require("../models/order");
const Product = require("../models/product");

const BigPromise = require("../middlewares/bigPromise");
const CustomError = require("../utils/customError");

exports.createOrder = BigPromise(async (req, res, next) => {
  const {
    shippingInfo,
    orderItems,
    paymentInfo,
    taxAmount,
    shippingAmount,
    totalAmount,
  } = req.body;

  const order = await Order.create({
    shippingInfo,
    orderItems,
    paymentInfo,
    taxAmount,
    shippingAmount,
    totalAmount,
    user: req.user._id,
  });

  res.status(200).json({
    success: true,
    order,
  });
});

exports.getOneOrder = BigPromise(async (req, res, next) => {
  const order = await Order.findById(req.params.id).populate(
    "user",
    "name email"
  );

  if (!order) {
    return next(new CustomError("please check order id", 401));
  }

  res.status(200).json({
    success: true,
    order,
  });
});

exports.getLoggedInOrders = BigPromise(async (req, res, next) => {
  const order = await Order.find({ user: req.user._id });

  if (!order) {
    return next(new CustomError("please check order id", 401));
  }

  res.status(200).json({
    success: true,
    order,
  });
});

exports.admingetAllOrders = BigPromise(async (req, res, next) => {
  const orders = await Order.find();

  res.status(200).json({
    success: true,
    orders,
  });
});

exports.adminUpdateOrder = BigPromise(async (req, res, next) => {
  const order = await Order.findById(req.params.id);

  if (order.orderStatus === "Delivered") {
    return next(new CustomError("Order is already marked for delivered", 401));
  }

  order.orderStatus = req.body.orderStatus;

  order.orderItems.forEach(async (prod) => {
    await updateProductStock(prod.product, prod.quantity);
  });

  await order.save();

  res.status(200).json({
    success: true,
    order,
  });
});

exports.adminDeleteOrder = BigPromise(async (req, res, next) => {
  const order = await Order.findById(req.params.id);

  await order.remove();

  res.status(200).json({
    success: true,
  });
});

async function updateProductStock(productId, quantity) {
  const product = await Product.findById(productId);

  product.stock = product.stock - quantity;

  await product.save({ validateBeforeSave: false });
}


================================================
FILE: tshirtstore/controllers/paymentController.js
================================================
const BigPromise = require("../middlewares/bigPromise");
const stripe = require("stripe")(process.env.STRIPE_SECRET);
const Razorpay = require("razorpay");

exports.sendStripeKey = BigPromise(async (req, res, next) => {
  res.status(200).json({
    stripekey: process.env.STRIPE_API_KEY,
  });
});

exports.captureStripePayment = BigPromise(async (req, res, next) => {
  const paymentIntent = await stripe.paymentIntents.create({
    amount: req.body.amount,
    currency: "inr",

    //optional
    metadata: { integration_check: "accept_a_payment" },
  });

  res.status(200).json({
    success: true,
    amount: req.body.amount,
    client_secret: paymentIntent.client_secret,
    //you can optionally send id as well
  });
});

exports.sendRazorpayKey = BigPromise(async (req, res, next) => {
  res.status(200).json({
    razorpaykey: process.env.RAZORPAY_API_KEY,
  });
});

exports.captureRazorpayPayment = BigPromise(async (req, res, next) => {
  var instance = new Razorpay({
    key_id: process.env.RAZORPAY_API_KEY,
    key_secret: process.env.RAZORPAY_SECRET,
  });

  var options = {
    amount: req.body.amount, // amount in the smallest currency unit
    currency: "INR",
  };
  console.log(req.body.amount);
  const myOrder = await instance.orders.create(options);

  res.status(200).json({
    success: true,
    amount: req.body.amount,
    order: myOrder,
  });
});


================================================
FILE: tshirtstore/controllers/productController.js
================================================
const Product = require("../models/product");
const BigPromise = require("../middlewares/bigPromise");
const CustomError = require("../utils/customError");
const cloudinary = require("cloudinary");
const WhereClause = require("../utils/whereClause");

exports.addProduct = BigPromise(async (req, res, next) => {
  // images

  let imageArray = [];

  if (!req.files) {
    return next(new CustomError("images are required", 401));
  }
  console.log("RESULT", req.files.photos[0]);

  if (req.files) {
    for (let index = 0; index < req.files.photos.length; index++) {
      console.log("UPLOAD START...");
      let result = await cloudinary.v2.uploader.upload(
        req.files.photos[index].tempFilePath,
        {
          folder: "products",
        }
      );

      // another way to upload and check error
      // let result
      // cloudinary.v2.uploader.upload(req.files.photos[index].tempFilePath, {
      //   folder: "products"
      // }, function(error, result){console.log(result, error)})

      console.log("RESULT", result);
      imageArray.push({
        id: result.public_id,
        secure_url: result.secure_url,
      });
    }
  }

  req.body.photos = imageArray;
  req.body.user = req.user.id;

  const product = await Product.create(req.body);

  res.status(200).json({
    success: true,
    product,
  });
});

exports.getAllProduct = BigPromise(async (req, res, next) => {
  const resultPerPage = 3;
  const totalcountProduct = await Product.countDocuments();

  const productsObj = new WhereClause(Product.find(), req.query)
    .search()
    .filter();

  let products = await productsObj.base;
  const filteredProductNumber = products.length;

  //products.limit().skip()

  productsObj.pager(resultPerPage);
  products = await productsObj.base.clone();

  res.status(200).json({
    success: true,
    products,
    filteredProductNumber,
    totalcountProduct,
    resultPerPage,
  });
});

exports.getOneProduct = BigPromise(async (req, res, next) => {
  const product = await Product.findById(req.params.id);

  if (!product) {
    return next(new CustomError("No product found with this id", 401));
  }
  res.status(200).json({
    success: true,
    product,
  });
});

exports.addReview = BigPromise(async (req, res, next) => {
  const { rating, comment, productId } = req.body;

  const review = {
    user: req.user._id,
    name: req.user.name,
    rating: Number(rating),
    comment,
  };

  const product = await Product.findById(productId);

  const AlreadyReview = product.reviews.find(
    (rev) => rev.user.toString() === req.user._id.toString()
  );

  if (AlreadyReview) {
    product.reviews.forEach((review) => {
      if (review.user.toString() === req.user._id.toString()) {
        review.comment = comment;
        review.rating = rating;
      }
    });
  } else {
    product.reviews.push(review);
    product.numberOfReviews = product.reviews.length;
  }

  // adjust ratings

  product.ratings =
    product.reviews.reduce((acc, item) => item.rating + acc, 0) /
    product.reviews.length;

  //save

  await product.save({ validateBeforeSave: false });

  res.status(200).json({
    success: true,
  });
});

exports.deleteReview = BigPromise(async (req, res, next) => {
  const { productId } = req.query;

  const product = await Product.findById(productId);

  const reviews = product.reviews.filter(
    (rev) => rev.user.toString() === req.user._id.toString()
  );

  const numberOfReviews = reviews.length;

  // adjust ratings

  product.ratings =
    product.reviews.reduce((acc, item) => item.rating + acc, 0) /
    product.reviews.length;

  //update the product

  await Product.findByIdAndUpdate(
    productId,
    {
      reviews,
      ratings,
      numberOfReviews,
    },
    {
      new: true,
      runValidators: true,
      useFindAndModify: false,
    }
  );

  res.status(200).json({
    success: true,
  });
});

exports.getOnlyReviewsForOneProduct = BigPromise(async (req, res, next) => {
  const product = await Product.findById(req.query.id);

  res.status(200).json({
    success: true,
    reviews: product.reviews,
  });
});

// admin only controllers
exports.adminGetAllProduct = BigPromise(async (req, res, next) => {
  const products = await Product.find();

  res.status(200).json({
    success: true,
    products,
  });
});

exports.adminUpdateOneProduct = BigPromise(async (req, res, next) => {
  let product = await Product.findById(req.params.id);

  if (!product) {
    return next(new CustomError("No product found with this id", 401));
  }
  let imagesArray = [];

  if (req.files) {
    //destroy the existing image
    for (let index = 0; index < product.photos.length; index++) {
      const res = await cloudinary.v2.uploader.destroy(
        product.photos[index].id
      );
    }

    for (let index = 0; index < req.files.photos.length; index++) {
      let result = await cloudinary.v2.uploader.upload(
        req.files.photos[index].tempFilePath,
        {
          folder: "products", //folder name -> .env
        }
      );

      imagesArray.push({
        id: result.public_id,
        secure_url: result.secure_url,
      });
    }
  }

  req.body.photos = imagesArray;

  product = await Product.findByIdAndUpdate(req.params.id, req.body, {
    new: true,
    runValidators: true,
    useFindAndModify: false,
  });

  res.status(200).json({
    success: true,
    product,
  });
});

exports.adminDeleteOneProduct = BigPromise(async (req, res, next) => {
  const product = await Product.findById(req.params.id);

  if (!product) {
    return next(new CustomError("No product found with this id", 401));
  }

  //destroy the existing image
  for (let index = 0; index < product.photos.length; index++) {
    const res = await cloudinary.v2.uploader.destroy(product.photos[index].id);
  }

  await product.remove();

  res.status(200).json({
    success: true,
    message: "Product was deleted !",
  });
});


================================================
FILE: tshirtstore/controllers/userController.js
================================================
const User = require("../models/user");
const BigPromise = require("../middlewares/bigPromise");
const CustomError = require("../utils/customError");
const cookieToken = require("../utils/cookieToken");
const cloudinary = require("cloudinary");
const mailHelper = require("../utils/emailHelper");
const crypto = require("crypto");

exports.signup = BigPromise(async (req, res, next) => {
  //let result;
  console.log(req.body);
  if (!req.files) {
    return next(new CustomError("photo is required for signup", 400));
  }

  const { name, email, password } = req.body;

  if (!email || !name || !password) {
    return next(new CustomError("Name, email and password are required", 400));
  }

  let file = req.files.photo;

  const result = await cloudinary.v2.uploader.upload(file.tempFilePath, {
    folder: "users",
    width: 150,
    crop: "scale",
  });

  const user = await User.create({
    name,
    email,
    password,
    photo: {
      id: result.public_id,
      secure_url: result.secure_url,
    },
  });

  cookieToken(user, res);
});

exports.login = BigPromise(async (req, res, next) => {
  const { email, password } = req.body;

  // check for presence of email and password
  if (!email || !password) {
    return next(new CustomError("please provide email and password", 400));
  }

  // get user from DB
  const user = await User.findOne({ email }).select("+password");

  // if user not found in DB
  if (!user) {
    return next(
      new CustomError("Email or password does not match or exist", 400)
    );
  }

  // match the password
  const isPasswordCorrect = await user.isValidatedPassword(password);

  //if password do not match
  if (!isPasswordCorrect) {
    return next(
      new CustomError("Email or password does not match or exist", 400)
    );
  }

  // if all goes good and we send the token
  cookieToken(user, res);
});

exports.logout = BigPromise(async (req, res, next) => {
  //clear the cookie
  res.cookie("token", null, {
    expires: new Date(Date.now()),
    httpOnly: true,
  });
  //send JSON response for success
  res.status(200).json({
    succes: true,
    message: "Logout success",
  });
});

exports.forgotPassword = BigPromise(async (req, res, next) => {
  // collect email
  const { email } = req.body;
  console.log(email);
  // find user in database
  const user = await User.findOne({ email });

  // if user not found in database
  if (!user) {
    return next(new CustomError("Email not found as registered", 400));
  }

  //get token from user model methods
  const forgotToken = user.getForgotPasswordToken();

  // save user fields in DB
  await user.save({ validateBeforeSave: false });

  // create a URL
  // const myUrl = `${req.protocol}://${req.get(
  //   "host"
  // )}/api/v1/password/reset/${forgotToken}`;

  //URL for deployment as front end might be running at different URL
  const myUrl = `${process.env.FRONT_END}/password/reset/${forgotToken}`;

  // craft a message
  const message = `Copy paste this link in your URL and hit enter \n\n ${myUrl}`;

  // attempt to send email
  try {
    await mailHelper({
      email: user.email,
      subject: "LCO TStore - Password reset email",
      message,
    });

    // json reponse if email is success
    res.status(200).json({
      succes: true,
      message: "Email sent successfully",
    });
  } catch (error) {
    // reset user fields if things goes wrong
    user.forgotPasswordToken = undefined;
    user.forgotPasswordExpiry = undefined;
    await user.save({ validateBeforeSave: false });

    // send error response
    return next(new CustomError(error.message, 500));
  }
});

exports.passwordReset = BigPromise(async (req, res, next) => {
  //get token from params
  const token = req.params.token;

  // hash the token as db also stores the hashed version
  const encryToken = crypto.createHash("sha256").update(token).digest("hex");

  // find user based on hased on token and time in future
  const user = await User.findOne({
    encryToken,
    forgotPasswordExpiry: { $gt: Date.now() },
  });

  if (!user) {
    return next(new CustomError("Token is invalid or expired", 400));
  }

  // check if password and conf password matched
  if (req.body.password !== req.body.confirmPassword) {
    return next(
      new CustomError("password and confirm password do not match", 400)
    );
  }

  // update password field in DB
  user.password = req.body.password;

  // reset token fields
  user.forgotPasswordToken = undefined;
  user.forgotPasswordExpiry = undefined;

  // save the user
  await user.save();

  // send a JSON response OR send token

  cookieToken(user, res);
});

exports.getLoggedInUserDetails = BigPromise(async (req, res, next) => {
  //req.user will be added by middleware
  // find user by id
  const user = await User.findById(req.user.id);

  //send response and user data
  res.status(200).json({
    success: true,
    user,
  });
});

exports.changePassword = BigPromise(async (req, res, next) => {
  // get user from middleware
  const userId = req.user.id;

  // get user from database
  const user = await User.findById(userId).select("+password");

  //check if old password is correct
  const isCorrectOldPassword = await user.isValidatedPassword(
    req.body.oldPassword
  );

  if (!isCorrectOldPassword) {
    return next(new CustomError("old password is incorrect", 400));
  }

  // allow to set new password
  user.password = req.body.password;

  // save user and send fresh token
  await user.save();
  cookieToken(user, res);
});

exports.updateUserDetails = BigPromise(async (req, res, next) => {
  // add a check for email and name in body

  // collect data from body
  const newData = {
    name: req.body.name,
    email: req.body.email,
  };

  // if photo comes to us
  if (req.files) {
    const user = await User.findById(req.user.id);

    const imageId = user.photo.id;

    // delete photo on cloudinary
    const resp = await cloudinary.v2.uploader.destroy(imageId);

    // upload the new photo
    const result = await cloudinary.v2.uploader.upload(
      req.files.photo.tempFilePath,
      {
        folder: "users",
        width: 150,
        crop: "scale",
      }
    );

    // add photo data in newData object
    newData.photo = {
      id: result.public_id,
      secure_url: result.secure_url,
    };
  }

  // update the data in user
  const user = await User.findByIdAndUpdate(req.user.id, newData, {
    new: true,
    runValidators: true,
    useFindAndModify: false,
  });

  res.status(200).json({
    success: true,
  });
});

exports.adminAllUser = BigPromise(async (req, res, next) => {
  // select all users
  const users = await User.find();

  // send all users
  res.status(200).json({
    success: true,
    users,
  });
});

exports.admingetOneUser = BigPromise(async (req, res, next) => {
  // get id from url and get user from database
  const user = await User.findById(req.params.id);

  if (!user) {
    next(new CustomError("No user found", 400));
  }

  // send user
  res.status(200).json({
    success: true,
    user,
  });
});

exports.adminUpdateOneUserDetails = BigPromise(async (req, res, next) => {
  // add a check for email and name in body

  // get data from request body
  const newData = {
    name: req.body.name,
    email: req.body.email,
    role: req.body.role,
  };

  // update the user in database
  const user = await User.findByIdAndUpdate(req.params.id, newData, {
    new: true,
    runValidators: true,
    useFindAndModify: false,
  });

  res.status(200).json({
    success: true,
  });
});

exports.adminDeleteOneUser = BigPromise(async (req, res, next) => {
  // get user from url
  const user = await User.findById(req.params.id);

  if (!user) {
    return next(new CustomError("No Such user found", 401));
  }

  // get image id from user in database
  const imageId = user.photo.id;

  // delete image from cloudinary
  await cloudinary.v2.uploader.destroy(imageId);

  // remove user from databse
  await user.remove();

  res.status(200).json({
    success: true,
  });
});

exports.managerAllUser = BigPromise(async (req, res, next) => {
  // select the user with role of user
  const users = await User.find({ role: "user" });

  res.status(200).json({
    success: true,
    users,
  });
});


================================================
FILE: tshirtstore/index.js
================================================
const app = require("./app");
const connectWithDb = require("./config/db");
require("dotenv").config();
const cloudinary = require("cloudinary");

// connect with databases
connectWithDb();

//cloudinary config goes here
cloudinary.config({
  cloud_name: process.env.CLOUDINARY_NAME,
  api_key: process.env.CLOUDINARY_API_KEY,
  api_secret: process.env.CLOUDINARY_API_SECRET,
});

app.listen(process.env.PORT, () => {
  console.log(`Server is running at port: ${process.env.PORT}`);
});


================================================
FILE: tshirtstore/lcotshirtstore/.gitignore
================================================
.env
node_modules/

================================================
FILE: tshirtstore/lcotshirtstore/app.js
================================================
const express = require("express");
require("dotenv").config();
const app = express();
const morgan = require("morgan");
const cookieParser = require("cookie-parser");
const fileUpload = require("express-fileupload");

//for swagger documentation
const swaggerUi = require("swagger-ui-express");
const YAML = require("yamljs");
const swaggerDocument = YAML.load("./swagger.yaml");
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument));

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

//cookies and file middleware
app.use(cookieParser());
app.use(
  fileUpload({
    useTempFiles: true,
    tempFileDir: "/tmp/",
  })
);

//temp check
app.set("view engine", "ejs");

//morgan middleware
app.use(morgan("tiny"));

//import all routes here
const home = require("./routes/home");
const user = require("./routes/user");
const product = require("./routes/product");
const payment = require("./routes/payment");
const order = require("./routes/order");

//router middleware
app.use("/api/v1", home);
app.use("/api/v1", user);
app.use("/api/v1", product);
app.use("/api/v1", payment);
app.use("/api/v1", order);

app.get("/signuptest", (req, res) => {
  res.render("signuptest");
});

// export app js
module.exports = app;


================================================
FILE: tshirtstore/lcotshirtstore/config/db.js
================================================
const mongoose = require("mongoose");

const connectWithDb = () => {
  mongoose
    .connect(process.env.DB_URL, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    })
    .then(console.log(`DB GOT CONNECTED`))
    .catch((error) => {
      console.log(`DB CONNECTION ISSUES`);
      console.log(error);
      process.exit(1);
    });
};

module.exports = connectWithDb;


================================================
FILE: tshirtstore/lcotshirtstore/controllers/homeController.js
================================================
const BigPromise = require("../middlewares/bigPromise");

exports.home = BigPromise(async (req, res) => {
  // const db = await something()
  res.status(200).json({
    success: true,
    greeting: "Hello from API",
  });
});

exports.homeDummy = async (req, res) => {
  try {
    // const db = await something()

    res.status(200).json({
      success: true,
      greeting: "this is another dummy route",
    });
  } catch (error) {
    console.log(error);
  }
};


================================================
FILE: tshirtstore/lcotshirtstore/controllers/orderController.js
================================================
const Order = require("../models/order");
const Product = require("../models/product");

const BigPromise = require("../middlewares/bigPromise");
const CustomError = require("../utils/customError");

exports.createOrder = BigPromise(async (req, res, next) => {
  const {
    shippingInfo,
    orderItems,
    paymentInfo,
    taxAmount,
    shippingAmount,
    totalAmount,
  } = req.body;

  const order = await Order.create({
    shippingInfo,
    orderItems,
    paymentInfo,
    taxAmount,
    shippingAmount,
    totalAmount,
    user: req.user._id,
  });

  res.status(200).json({
    success: true,
    order,
  });
});

exports.getOneOrder = BigPromise(async (req, res, next) => {
  const order = await Order.findById(req.params.id).populate(
    "user",
    "name email"
  );

  if (!order) {
    return next(new CustomError("please check order id", 401));
  }

  res.status(200).json({
    success: true,
    order,
  });
});

exports.getLoggedInOrders = BigPromise(async (req, res, next) => {
  const order = await Order.find({ user: req.user._id });

  if (!order) {
    return next(new CustomError("please check order id", 401));
  }

  res.status(200).json({
    success: true,
    order,
  });
});

exports.admingetAllOrders = BigPromise(async (req, res, next) => {
  const orders = await Order.find();

  res.status(200).json({
    success: true,
    orders,
  });
});

exports.adminUpdateOrder = BigPromise(async (req, res, next) => {
  const order = await Order.findById(req.params.id);

  if (order.orderStatus === "Delivered") {
    return next(new CustomError("Order is already marked for delivered", 401));
  }

  order.orderStatus = req.body.orderStatus;

  order.orderItems.forEach(async (prod) => {
    await updateProductStock(prod.product, prod.quantity);
  });

  await order.save();

  res.status(200).json({
    success: true,
    orders,
  });
});

exports.adminDeleteOrder = BigPromise(async (req, res, next) => {
  const order = await Order.findById(req.params.id);

  await order.remove();

  res.status(200).json({
    success: true,
  });
});

async function updateProductStock(productId, quantity) {
  const product = await Product.findById(productId);

  product.stock = product.stock - quantity;

  await product.save({ validateBeforeSave: false });
}


================================================
FILE: tshirtstore/lcotshirtstore/controllers/paymentController.js
================================================
const BigPromise = require("../middlewares/bigPromise");
const stripe = require("stripe")(process.env.STRIPE_SECRET);

exports.sendStripeKey = BigPromise(async (req, res, next) => {
  res.status(200).json({
    stripekey: process.env.STRIPE_API_KEY,
  });
});

exports.captureStripePayment = BigPromise(async (req, res, next) => {
  const paymentIntent = await stripe.paymentIntents.create({
    amount: req.body.amount,
    currency: "inr",

    //optional
    metadata: { integration_check: "accept_a_payment" },
  });

  res.status(200).json({
    success: true,
    amount: req.body.amount,
    client_secret: paymentIntent.client_secret,
    //you can optionally send id as well
  });
});

exports.sendRazorpayKey = BigPromise(async (req, res, next) => {
  res.status(200).json({
    stripekey: process.env.RAZORPAY_API_KEY,
  });
});

exports.captureRazorpayPayment = BigPromise(async (req, res, next) => {
  var instance = new Razorpay({
    key_id: process.env.RAZORPAY_API_KEY,
    key_secret: process.env.RAZORPAY_SECRET,
  });

  var options = {
    amount: req.body.amount, // amount in the smallest currency unit
    currency: "INR",
  };
  const myOrder = await instance.orders.create(options);

  res.staus(200).json({
    success: true,
    amount: req.body.amount,
    order: myOrder,
  });
});


================================================
FILE: tshirtstore/lcotshirtstore/controllers/productController.js
================================================
const Product = require("../models/product");
const BigPromise = require("../middlewares/bigPromise");
const CustomError = require("../utils/customError");
const cloudinary = require("cloudinary");
const WhereClause = require("../utils/whereClause");

exports.addProduct = BigPromise(async (req, res, next) => {
  // images

  let imageArray = [];

  if (!req.files) {
    return next(new CustomError("images are required", 401));
  }

  if (req.files) {
    for (let index = 0; index < req.files.photos.length; index++) {
      let result = await cloudinary.v2.uploader.upload(
        req.files.photos[index].tempFilePath,
        {
          folder: "products",
        }
      );

      imageArray.push({
        id: result.public_id,
        secure_url: result.secure_url,
      });
    }
  }

  req.body.photos = imageArray;
  req.body.user = req.user.id;

  const product = await Product.create(req.body);

  res.status(200).json({
    success: true,
    product,
  });
});

exports.getAllProduct = BigPromise(async (req, res, next) => {
  const resultPerPage = 6;
  const totalcountProduct = await Product.countDocuments();

  const productsObj = new WhereClause(Product.find(), req.query)
    .search()
    .filter();

  let products = await productsObj.base;
  const filteredProductNumber = products.length;

  //products.limit().skip()

  productsObj.pager(resultPerPage);
  products = await productsObj.base.clone();

  res.status(200).json({
    success: true,
    products,
    filteredProductNumber,
    totalcountProduct,
  });
});

exports.getOneProduct = BigPromise(async (req, res, next) => {
  const product = await Product.findById(req.params.id);

  if (!product) {
    return next(new CustomError("No product found with this id", 401));
  }
  res.status(200).json({
    success: true,
    product,
  });
});

exports.addReview = BigPromise(async (req, res, next) => {
  const { rating, comment, productId } = req.body;

  const review = {
    user: req.user._id,
    name: req.user.name,
    rating: Number(rating),
    comment,
  };

  const product = await Product.findById(productId);

  const AlreadyReview = product.reviews.find(
    (rev) => rev.user.toString() === req.user._id.toString()
  );

  if (AlreadyReview) {
    product.reviews.forEach((review) => {
      if (review.user.toString() === req.user._id.toString()) {
        review.comment = comment;
        review.rating = rating;
      }
    });
  } else {
    product.reviews.push(review);
    product.numberOfReviews = product.reviews.length;
  }

  // adjust ratings

  product.ratings =
    product.reviews.reduce((acc, item) => item.rating + acc, 0) /
    product.reviews.length;

  //save

  await product.save({ validateBeforeSave: false });

  res.status(200).json({
    success: true,
  });
});

exports.deleteReview = BigPromise(async (req, res, next) => {
  const { productId } = req.query;

  const product = await Product.findById(productId);

  const reviews = product.reviews.filter(
    (rev) => rev.user.toString() === req.user._id.toString()
  );

  const numberOfReviews = reviews.length;

  // adjust ratings

  product.ratings =
    product.reviews.reduce((acc, item) => item.rating + acc, 0) /
    product.reviews.length;

  //update the product

  await Product.findByIdAndUpdate(
    productId,
    {
      reviews,
      ratings,
      numberOfReviews,
    },
    {
      new: true,
      runValidators: true,
      useFindAndModify: false,
    }
  );

  res.status(200).json({
    success: true,
  });
});

exports.getOnlyReviewsForOneProduct = BigPromise(async (req, res, next) => {
  const product = await Product.findById(req.query.id);

  res.status(200).json({
    success: true,
    reviews: product.reviews,
  });
});

// admin only controllers
exports.adminGetAllProduct = BigPromise(async (req, res, next) => {
  const products = await Product.find();

  res.status(200).json({
    success: true,
    products,
  });
});

exports.adminUpdateOneProduct = BigPromise(async (req, res, next) => {
  let product = await Product.findById(req.params.id);

  if (!product) {
    return next(new CustomError("No product found with this id", 401));
  }
  let imagesArray = [];

  if (req.files) {
    //destroy the existing image
    for (let index = 0; index < product.photos.length; index++) {
      const res = await cloudinary.v2.uploader.destroy(
        product.photos[index].id
      );
    }

    for (let index = 0; index < req.files.photos.length; index++) {
      let result = await cloudinary.v2.uploader.upload(
        req.files.photos[index].tempFilePath,
        {
          folder: "products", //folder name -> .env
        }
      );

      imagesArray.push({
        id: result.public_id,
        secure_url: result.secure_url,
      });
    }
  }

  req.body.photos = imagesArray;

  product = await Product.findByIdAndUpdate(req.params.id, req.body, {
    new: true,
    runValidators: true,
    useFindAndModify: false,
  });

  res.status(200).json({
    success: true,
    product,
  });
});

exports.adminDeleteOneProduct = BigPromise(async (req, res, next) => {
  const product = await Product.findById(req.params.id);

  if (!product) {
    return next(new CustomError("No product found with this id", 401));
  }

  //destroy the existing image
  for (let index = 0; index < product.photos.length; index++) {
    const res = await cloudinary.v2.uploader.destroy(product.photos[index].id);
  }

  await product.remove();

  res.status(200).json({
    success: true,
    message: "Product was deleted !",
  });
});


================================================
FILE: tshirtstore/lcotshirtstore/controllers/userController.js
================================================
const User = require("../models/user");
const BigPromise = require("../middlewares/bigPromise");
const CustomError = require("../utils/customError");
const cookieToken = require("../utils/cookieToken");
const cloudinary = require("cloudinary");
const mailHelper = require("../utils/emailHelper");
const crypto = require("crypto");

exports.signup = BigPromise(async (req, res, next) => {
  //let result;

  if (!req.files) {
    return next(new CustomError("photo is required for signup", 400));
  }

  const { name, email, password } = req.body;

  if (!email || !name || !password) {
    return next(new CustomError("Name, email and password are required", 400));
  }

  let file = req.files.photo;

  const result = await cloudinary.v2.uploader.upload(file.tempFilePath, {
    folder: "users",
    width: 150,
    crop: "scale",
  });

  const user = await User.create({
    name,
    email,
    password,
    photo: {
      id: result.public_id,
      secure_url: result.secure_url,
    },
  });

  cookieToken(user, res);
});

exports.login = BigPromise(async (req, res, next) => {
  const { email, password } = req.body;

  // check for presence of email and password
  if (!email || !password) {
    return next(new CustomError("please provide email and password", 400));
  }

  // get user from DB
  const user = await User.findOne({ email }).select("+password");

  // if user not found in DB
  if (!user) {
    return next(
      new CustomError("Email or password does not match or exist", 400)
    );
  }

  // match the password
  const isPasswordCorrect = await user.isValidatedPassword(password);

  //if password do not match
  if (!isPasswordCorrect) {
    return next(
      new CustomError("Email or password does not match or exist", 400)
    );
  }

  // if all goes good and we send the token
  cookieToken(user, res);
});

exports.logout = BigPromise(async (req, res, next) => {
  //clear the cookie
  res.cookie("token", null, {
    expires: new Date(Date.now()),
    httpOnly: true,
  });
  //send JSON response for success
  res.status(200).json({
    succes: true,
    message: "Logout success",
  });
});

exports.forgotPassword = BigPromise(async (req, res, next) => {
  // collect email
  const { email } = req.body;

  // find user in database
  const user = await User.findOne({ email });

  // if user not found in database
  if (!user) {
    return next(new CustomError("Email not found as registered", 400));
  }

  //get token from user model methods
  const forgotToken = user.getForgotPasswordToken();

  // save user fields in DB
  await user.save({ validateBeforeSave: false });

  // create a URL
  const myUrl = `${req.protocol}://${req.get(
    "host"
  )}/api/v1/password/reset/${forgotToken}`;

  // craft a message
  const message = `Copy paste this link in your URL and hit enter \n\n ${myUrl}`;

  // attempt to send email
  try {
    await mailHelper({
      email: user.email,
      subject: "LCO TStore - Password reset email",
      message,
    });

    // json reponse if email is success
    res.status(200).json({
      succes: true,
      message: "Email sent successfully",
    });
  } catch (error) {
    // reset user fields if things goes wrong
    user.forgotPasswordToken = undefined;
    user.forgotPasswordExpiry = undefined;
    await user.save({ validateBeforeSave: false });

    // send error response
    return next(new CustomError(error.message, 500));
  }
});

exports.passwordReset = BigPromise(async (req, res, next) => {
  //get token from params
  const token = req.params.token;

  // hash the token as db also stores the hashed version
  const encryToken = crypto.createHash("sha256").update(token).digest("hex");

  // find user based on hased on token and time in future
  const user = await User.findOne({
    encryToken,
    forgotPasswordExpiry: { $gt: Date.now() },
  });

  if (!user) {
    return next(new CustomError("Token is invalid or expired", 400));
  }

  // check if password and conf password matched
  if (req.body.password !== req.body.confirmPassword) {
    return next(
      new CustomError("password and confirm password do not match", 400)
    );
  }

  // update password field in DB
  user.password = req.body.password;

  // reset token fields
  user.forgotPasswordToken = undefined;
  user.forgotPasswordExpiry = undefined;

  // save the user
  await user.save();

  // send a JSON response OR send token

  cookieToken(user, res);
});

exports.getLoggedInUserDetails = BigPromise(async (req, res, next) => {
  //req.user will be added by middleware
  // find user by id
  const user = await User.findById(req.user.id);

  //send response and user data
  res.status(200).json({
    success: true,
    user,
  });
});

exports.changePassword = BigPromise(async (req, res, next) => {
  // get user from middleware
  const userId = req.user.id;

  // get user from database
  const user = await User.findById(userId).select("+password");

  //check if old password is correct
  const isCorrectOldPassword = await user.isValidatedPassword(
    req.body.oldPassword
  );

  if (!isCorrectOldPassword) {
    return next(new CustomError("old password is incorrect", 400));
  }

  // allow to set new password
  user.password = req.body.password;

  // save user and send fresh token
  await user.save();
  cookieToken(user, res);
});

exports.updateUserDetails = BigPromise(async (req, res, next) => {
  // add a check for email and name in body

  // collect data from body
  const newData = {
    name: req.body.name,
    email: req.body.email,
  };

  // if photo comes to us
  if (req.files) {
    const user = await User.findById(req.user.id);

    const imageId = user.photo.id;

    // delete photo on cloudinary
    const resp = await cloudinary.v2.uploader.destroy(imageId);

    // upload the new photo
    const result = await cloudinary.v2.uploader.upload(
      req.files.photo.tempFilePath,
      {
        folder: "users",
        width: 150,
        crop: "scale",
      }
    );

    // add photo data in newData object
    newData.photo = {
      id: result.public_id,
      secure_url: result.secure_url,
    };
  }

  // update the data in user
  const user = await User.findByIdAndUpdate(req.user.id, newData, {
    new: true,
    runValidators: true,
    useFindAndModify: false,
  });

  res.status(200).json({
    success: true,
  });
});

exports.adminAllUser = BigPromise(async (req, res, next) => {
  // select all users
  const users = await User.find();

  // send all users
  res.status(200).json({
    success: true,
    users,
  });
});

exports.admingetOneUser = BigPromise(async (req, res, next) => {
  // get id from url and get user from database
  const user = await User.findById(req.params.id);

  if (!user) {
    next(new CustomError("No user found", 400));
  }

  // send user
  res.status(200).json({
    success: true,
    user,
  });
});

exports.adminUpdateOneUserDetails = BigPromise(async (req, res, next) => {
  // add a check for email and name in body

  // get data from request body
  const newData = {
    name: req.body.name,
    email: req.body.email,
    role: req.body.role,
  };

  // update the user in database
  const user = await User.findByIdAndUpdate(req.params.id, newData, {
    new: true,
    runValidators: true,
    useFindAndModify: false,
  });

  res.status(200).json({
    success: true,
  });
});

exports.adminDeleteOneUser = BigPromise(async (req, res, next) => {
  // get user from url
  const user = await User.findById(req.params.id);

  if (!user) {
    return next(new CustomError("No Such user found", 401));
  }

  // get image id from user in database
  const imageId = user.photo.id;

  // delete image from cloudinary
  await cloudinary.v2.uploader.destroy(imageId);

  // remove user from databse
  await user.remove();

  res.status(200).json({
    success: true,
  });
});

exports.managerAllUser = BigPromise(async (req, res, next) => {
  // select the user with role of user
  const users = await User.find({ role: "user" });

  res.status(200).json({
    success: true,
    users,
  });
});


================================================
FILE: tshirtstore/lcotshirtstore/index.js
================================================
const app = require("./app");
const connectWithDb = require("./config/db");
require("dotenv").config();
const cloudinary = require("cloudinary");

// connect with databases
connectWithDb();

//cloudinary config goes here
cloudinary.config({
  cloud_name: process.env.CLOUDINARY_NAME,
  api_key: process.env.CLOUDINARY_API_KEY,
  api_secret: process.env.CLOUDINARY_API_SECRET,
});

app.listen(process.env.PORT, () => {
  console.log(`Server is running at port: ${process.env.PORT}`);
});


================================================
FILE: tshirtstore/lcotshirtstore/middlewares/bigPromise.js
================================================
// try catch and async - await || use promise

module.exports = (func) => (req, res, next) =>
  Promise.resolve(func(req, res, next)).catch(next);


================================================
FILE: tshirtstore/lcotshirtstore/middlewares/user.js
================================================
const User = require("../models/user");
const BigPromise = require("../middlewares/bigPromise");
const CustomError = require("../utils/customError");
const jwt = require("jsonwebtoken");

exports.isLoggedIn = BigPromise(async (req, res, next) => {
  const token =
    req.cookies.token || req.header("Authorization").replace("Bearer ", "");

  if (!token) {
    return next(new CustomError("Login first to access this page", 401));
  }

  const decoded = jwt.verify(token, process.env.JWT_SECRET);

  req.user = await User.findById(decoded.id);

  next();
});

exports.customRole = (...roles) => {
  return (req, res, next) => {
    if (!roles.includes(req.user.role)) {
      return next(new CustomError("You are not allowed for this resouce", 403));
    }
    next();
  };
};


================================================
FILE: tshirtstore/lcotshirtstore/models/order.js
================================================
const mongoose = require("mongoose");

// shippingInfo{}
// user,
// paymentInfo{}
// taxAmount
// ShippingAmount
// totalAmount
// orderStatus
// deliveredAt
// createdAt
// -------------
// orderItems: [ {} ]
// - name
// - quantity
// - image[0]
// - price
// - product

const orderSchema = new mongoose.Schema({
  shippingInfo: {
    address: {
      type: String,
      required: true,
    },
    city: {
      type: String,
      required: true,
    },
    phoneNo: {
      type: String,
      required: true,
    },
    postalCode: {
      type: String,
      required: true,
    },
    state: {
      type: String,
      required: true,
    },
    country: {
      type: String,
      required: true,
    },
  },
  user: {
    type: mongoose.Schema.ObjectId, //mongoose.Schema.Types.ObjectId
    ref: "User",
    required: true,
  },
  orderItems: [
    {
      name: {
        type: String,
        required: true,
      },
      quantity: {
        type: Number,
        required: true,
      },
      image: {
        type: String,
        required: true,
      },
      price: {
        type: Number,
        required: true,
      },
      product: {
        type: mongoose.Schema.ObjectId, //mongoose.Schema.Types.ObjectId
        ref: "Product",
        required: true,
      },
    },
  ],
  paymentInfo: {
    id: {
      type: String,
    },
  },
  taxAmount: {
    type: Number,
    required: true,
  },
  shippingAmount: {
    type: Number,
    required: true,
  },
  totalAmount: {
    type: Number,
    required: true,
  },
  orderStatus: {
    type: String,
    required: true,
    default: "processing",
  },
  deliveredAt: {
    type: Date,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

module.exports = mongoose.model("Order", orderSchema);

// ref link
// https://stackoverflow.com/questions/28997636/should-i-use-schema-types-objectid-or-schema-objectid-when-defining-a-mongoose-s


================================================
FILE: tshirtstore/lcotshirtstore/models/product.js
================================================
const mongoose = require("mongoose");

const productSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, "please provide product name"],
    trim: true,
    maxlength: [120, "Product name should not be more than 120 characters"],
  },
  price: {
    type: Number,
    required: [true, "please provide product price"],
    maxlength: [6, "Product price should not be more than 6 digits"],
  },
  description: {
    type: String,
    required: [true, "please provide product description"],
  },
  photos: [
    {
      id: {
        type: String,
        required: true,
      },
      secure_url: {
        type: String,
        required: true,
      },
    },
  ],
  category: {
    type: String,
    required: [
      true,
      "please select category from- short-sleeves, long-sleeves, sweat-shirts, hoodies",
    ],
    enum: {
      values: ["shortsleeves", "longsleeves", "sweatshirt", "hoodies"],
      message:
        "please select category ONLY from - short-sleeves, long-sleeves, sweat-shirts and hoodies ",
    },
  },
  //this field was updated in order videos later
  stock: {
    type: Number,
    required: [true, "please add a number in stock"],
  },
  brand: {
    type: String,
    required: [true, "please add a brand for clothing"],
  },
  ratings: {
    type: Number,
    default: 0,
  },
  numberOfReviews: {
    type: Number,
    default: 0,
  },
  reviews: [
    {
      user: {
        type: mongoose.Schema.ObjectId,
        ref: "User",
        required: true,
      },
      name: {
        type: String,
        required: true,
      },
      rating: {
        type: Number,
        required: true,
      },
      comment: {
        type: String,
        required: true,
      },
    },
  ],
  user: {
    type: mongoose.Schema.ObjectId,
    ref: "User",
    required: true,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

module.exports = mongoose.model("Product", productSchema);


================================================
FILE: tshirtstore/lcotshirtstore/models/user.js
================================================
const mongoose = require("mongoose");
const validator = require("validator");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const crypto = require("crypto");

const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, "Please provide a name"],
    maxlength: [40, "Name should be under 40 characters"],
  },
  email: {
    type: String,
    required: [true, "Please provide an email"],
    validate: [validator.isEmail, "Please enter email in correct format"],
    unique: true,
  },
  password: {
    type: String,
    required: [true, "Please provide a password"],
    minlength: [6, "password should be atleast 6 char"],
    select: false,
  },
  role: {
    type: String,
    default: "user",
  },
  photo: {
    id: {
      type: String,
      required: true,
    },
    secure_url: {
      type: String,
      required: true,
    },
  },
  forgotPasswordToken: String,
  forgotPasswordExpiry: Date,
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

//encrypt password before save - HOOKS
userSchema.pre("save", async function (next) {
  if (!this.isModified("password")) {
    return next();
  }
  this.password = await bcrypt.hash(this.password, 10);
});

// validate the password with passed on user password
userSchema.methods.isValidatedPassword = async function (usersendPassword) {
  return await bcrypt.compare(usersendPassword, this.password);
};

//create and return jwt token
userSchema.methods.getJwtToken = function () {
  return jwt.sign({ id: this._id }, process.env.JWT_SECRET, {
    expiresIn: process.env.JWT_EXPIRY,
  });
};

//generate forgot password token (string)
userSchema.methods.getForgotPasswordToken = function () {
  // generate a long and randomg string
  const forgotToken = crypto.randomBytes(20).toString("hex");

  // getting a hash - make sure to get a hash on backend
  this.forgotPasswordToken = crypto
    .createHash("sha256")
    .update(forgotToken)
    .digest("hex");

  //time of token
  this.forgotPasswordExpiry = Date.now() + 20 * 60 * 1000;

  return forgotToken;
};

module.exports = mongoose.model("User", userSchema);


================================================
FILE: tshirtstore/lcotshirtstore/nodemon.json
================================================
{
  "ext": ".js, .jsx, .yaml"
}


================================================
FILE: tshirtstore/lcotshirtstore/package.json
================================================
{
  "name": "tshirtstore",
  "version": "1.0.0",
  "description": "a backend api for tshirt store",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
  "keywords": [
    "api",
    "backend"
  ],
  "author": "hitesh choudhary",
  "license": "ISC",
  "dependencies": {
    "bcryptjs": "^2.4.3",
    "cloudinary": "^1.27.1",
    "cookie-parser": "^1.4.5",
    "dotenv": "^10.0.0",
    "ejs": "^3.1.6",
    "express": "^4.17.1",
    "express-fileupload": "^1.2.1",
    "jsonwebtoken": "^8.5.1",
    "mongoose": "^6.0.12",
    "morgan": "^1.10.0",
    "nodemailer": "^6.7.0",
    "razorpay": "^2.0.7",
    "stripe": "^8.184.0",
    "swagger-ui-express": "^4.1.6",
    "validator": "^13.6.0",
    "yamljs": "^0.3.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.14"
  }
}


================================================
FILE: tshirtstore/lcotshirtstore/routes/home.js
================================================
const express = require("express");
const router = express.Router();

const { home, homeDummy } = require("../controllers/homeController");

router.route("/").get(home);
router.route("/dummy").get(homeDummy);

module.exports = router;


================================================
FILE: tshirtstore/lcotshirtstore/routes/order.js
================================================
const express = require("express");
const {
  createOrder,
  getOneOrder,
  getLoggedInOrders,
  admingetAllOrders,
  adminUpdateOrder,
  adminDeleteOrder,
} = require("../controllers/orderController");
const router = express.Router();
const { isLoggedIn, customRole } = require("../middlewares/user");

router.route("/order/create").post(isLoggedIn, createOrder);
router.route("/order/:id").get(isLoggedIn, getOneOrder);
router.route("/myorder").get(isLoggedIn, getLoggedInOrders);

//admin routes
router
  .route("/admin/orders")
  .get(isLoggedIn, customRole("admin"), admingetAllOrders);
router
  .route("/admin/order/:id")
  .put(isLoggedIn, customRole("admin"), adminUpdateOrder)
  .delete(isLoggedIn, customRole("admin"), adminDeleteOrder);

module.exports = router;


================================================
FILE: tshirtstore/lcotshirtstore/routes/payment.js
================================================
const express = require("express");
const router = express.Router();
const {
  sendRazorpayKey,
  sendStripeKey,
  captureStripePayment,
  captureRazorpayPayment,
} = require("../controllers/paymentController");
const { isLoggedIn } = require("../middlewares/user");

router.route("/stripekey").get(isLoggedIn, sendStripeKey);
router.route("/razorpaykey").get(isLoggedIn, sendRazorpayKey);

router.route("/capturestripe").post(isLoggedIn, captureStripePayment);
router.route("/capturerazorpay").post(isLoggedIn, captureRazorpayPayment);

module.exports = router;


================================================
FILE: tshirtstore/lcotshirtstore/routes/product.js
================================================
const express = require("express");
const {
  addProduct,
  getAllProduct,
  adminGetAllProduct,
  getOneProduct,
  adminUpdateOneProduct,
  adminDeleteOneProduct,
  addReview,
  deleteReview,
  getOnlyReviewsForOneProduct,
} = require("../controllers/productController");
const router = express.Router();
const { isLoggedIn, customRole } = require("../middlewares/user");

//user routes
router.route("/products").get(getAllProduct);
router.route("/product/:id").get(getOneProduct);
router.route("/review").put(isLoggedIn, addReview);
router.route("/review").delete(isLoggedIn, deleteReview);
router.route("/reviews").get(isLoggedIn, getOnlyReviewsForOneProduct);

//admin routes
router
  .route("/admin/product/add")
  .post(isLoggedIn, customRole("admin"), addProduct);

router
  .route("/admin/products")
  .get(isLoggedIn, customRole("admin"), adminGetAllProduct);

router
  .route("/admin/product/:id")
  .put(isLoggedIn, customRole("admin"), adminUpdateOneProduct)
  .delete(isLoggedIn, customRole("admin"), adminDeleteOneProduct);

module.exports = router;


================================================
FILE: tshirtstore/lcotshirtstore/routes/user.js
================================================
const express = require("express");
const router = express.Router();

const {
  signup,
  login,
  logout,
  forgotPassword,
  passwordReset,
  getLoggedInUserDetails,
  changePassword,
  updateUserDetails,
  adminAllUser,
  managerAllUser,
  admingetOneUser,
  adminUpdateOneUserDetails,
  adminDeleteOneUser,
} = require("../controllers/userController");
const { isLoggedIn, customRole } = require("../middlewares/user");

router.route("/signup").post(signup);
router.route("/login").post(login);
router.route("/logout").get(logout);
router.route("/forgotPassword").post(forgotPassword);
router.route("/password/reset/:token").post(passwordReset);
router.route("/userdashboard").get(isLoggedIn, getLoggedInUserDetails);
router.route("/password/update").post(isLoggedIn, changePassword);
router.route("/userdashboard/update").post(isLoggedIn, updateUserDetails);

//admin only routes
router.route("/admin/users").get(isLoggedIn, customRole("admin"), adminAllUser);
router
  .route("/admin/user/:id")
  .get(isLoggedIn, customRole("admin"), admingetOneUser)
  .put(isLoggedIn, customRole("admin"), adminUpdateOneUserDetails)
  .delete(isLoggedIn, customRole("admin"), adminDeleteOneUser);

// manager only route
router
  .route("/manager/users")
  .get(isLoggedIn, customRole("manager"), managerAllUser);
module.exports = router;


================================================
FILE: tshirtstore/lcotshirtstore/swagger.yaml
================================================
openapi: "3.0.0"
info:
  title: Tshirt store API
  description: LCO - a course to create API for ecomm store
  version: 1.1.0
  contact:
    email: hitesh@lco.dev
    url: "https://lco.dev"

# servers:
#   - url: "https://localhost:4000/api/v1"
#     description: for local host - secure
#   - url: "http://localhost:4000/api/v1"
#     description: for local host - regular

servers:
  - url: "{protocol}://localhost:4000/api/{version}"
    description: for local host 
    variables:
      version:
        enum:
          - v1
          - v2
        default: v1
      protocol:
        enum:
          - http
          - https
        default: http

components:
  securitySchemes:
    cookieAuth:
      type: apiKey
      in: cookie
      name: token
    BearerAuth:
      type: http
      scheme: bearer


paths:
  /dummy:
    get:
      tags:
        - Home
      summary: returns a greet message from LCO
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: string
                example: "mystring"
        400:
          description: Bad request
        500:
          description: internal server error
  /signup:
    post:
      tags:
        - User
      summary: signup a new user. required files are - name, email, password and photo
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - name
                - email
                - password
                - photo
              properties:
                name:
                  type: string
                  required: true
                email:
                  type: string
                password:
                  type: string
                photo:
                  in: formData
                  description: The uploaded file data
                  type: file
                  format: binary
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  token:
                    type: string
                  user:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
                      role:
                        type: string
                      photo:
                        type: object
                        properties:
                          id:
                            type: string
                          secure_url:
                            type: string
                      _id:
                        type: string
                      createdAt:
                        type: string
        400:
          description: Bad request
        500:
          description: internal server error
  /login:
    post:
      tags:
        - User
      summary: login a new user. required files are -  email and password. Also add httpOnly cookie
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - password
              properties:
                email:
                  type: string
                password:
                  type: string
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  token:
                    type: string
                  user:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
                      role:
                        type: string
                      photo:
                        type: object
                        properties:
                          id:
                            type: string
                          secure_url:
                            type: string
                      _id:
                        type: string
                      createdAt:
                        type: string
        400:
          description: Bad request
        500:
          description: internal server error
  /logout:
    get:
      tags:
        - User
      summary: get request to logout the user. Also removes httpOnly cookies 
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  
        400:
          description: Bad request
        500:
          description: internal server error

  /forgotPassword:
    post:
      tags:
        - User
      summary: sends an email with link to forgot password. Contains the token for user validation
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - email
              properties:
                email:
                  type: string
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
        400:
          description: Bad request
        500:
          description: internal server error

  /password/reset/{token}:
    post:
      tags:
        - User
      summary: Allows user to reset password, validated based on token. send password and confirm password fields
      parameters:
        - name: token
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - password
                - confirmPassword
              properties:
                password:
                  type: string
                confirmPassword:
                  type: string
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  token:
                    type: string
                  user:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
                      role:
                        type: string
                      photo:
                        type: object
                        properties:
                          id:
                            type: string
                          secure_url:
                            type: string
                      _id:
                        type: string
                      createdAt:
                        type: string
        400:
          description: Bad request
        500:
          description: internal server error

  /userdashboard:
    get:
      tags:
        - User
      summary: Gets all details about logged in user. Send token in cookies as named token or send Bearer Auth
      requestBody:
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  user:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
                      role:
                        type: string
                      photo:
                        type: object
                        properties:
                          id:
                            type: string
                          secure_url:
                            type: string
                      _id:
                        type: string
                      createdAt:
                        type: string
        400:
          description: Bad request
        500:
          description: internal server error

  /password/update:
    post:
      tags:
        - User
      summary: User can update the password if he is logged in. Send oldPassword and password
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - oldPassword
                - password
              properties:
                oldPassword:
                  type: string
                password:
                  type: string
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string
                  user:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
                      role:
                        type: string
                      photo:
                        type: object
                        properties:
                          id:
                            type: string
                          secure_url:
                            type: string
                      _id:
                        type: string
                      createdAt:
                        type: string
        400:
          description: Bad request
        500:
          description: internal server error

  /userdashboard/update:
    post:
      tags:
        - User
      summary: User can update the name, emails and photo. Photo is optional
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - name
                - email
              properties:
                name:
                  type: string
                email:
                  type: string
                photo:
                  in: formData
                  description: The uploaded file data
                  type: file
                  format: binary
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  
        400:
          description: Bad request
        500:
          description: internal server error

  /admin/users:
    get:
      tags:
        - Admin
      summary: If user is admin, response will get array of all users
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    user:
                      type: object
                      properties:
                        name:
                          type: string
                        email:
                          type: string
                        role:
                          type: string
                        photo:
                          type: object
                          properties:
                            id:
                              type: string
                            secure_url:
                              type: string
                        _id:
                          type: string
                        createdAt:
                          type: string
                  
        400:
          description: Bad request
        500:
          description: internal server error

  /admin/user/{id}:
    get:
      tags:
        - Admin
      summary: If user is admin, response will get details of 1 user
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                  type: object
                  properties:
                    user:
                      type: object
                      properties:
                        name:
                          type: string
                        email:
                          type: string
                        role:
                          type: string
                        photo:
                          type: object
                          properties:
                            id:
                              type: string
                            secure_url:
                              type: string
                        _id:
                          type: string
                        createdAt:
                          type: string
                  
        400:
          description: Bad request
        500:
          description: internal server error
    put:
      tags:
        - Admin
      summary: If user is admin, response will get details of 1 user
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: name
          in: formData
          required: true
          schema:
            type: string
        - name: email
          in: formData
          required: true
          schema:
            type: string
        - name: role
          in: formData
          required: true
          schema:
            type: string
            enum: [user, admin, manager]
      requestBody: 
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                  type: object
                  properties:
                    success:
                      type: boolean
                  
        400:
          description: Bad request
        500:
          description: internal server error
    delete:
      tags:
        - Admin
      summary: If user is admin, delete the user with given id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody: 
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                  type: object
                  properties:
                    success:
                      type: boolean
                  
        400:
          description: Bad request
        500:
          description: internal server error

  /manager/users:
    get:
      tags:
        - Manager
      summary: If manager, response will get array of all users whose role is user
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    user:
                      type: object
                      properties:
                        name:
                          type: string
                        email:
                          type: string
                        role:
                          type: string
                        photo:
                          type: object
                          properties:
                            id:
                              type: string
                            secure_url:
                              type: string
                        _id:
                          type: string
                        createdAt:
                          type: string
                  
        400:
          description: Bad request
        500:
          description: internal server error




================================================
FILE: tshirtstore/lcotshirtstore/utils/cookieToken.js
================================================
const cookieToken = (user, res) => {
  const token = user.getJwtToken();

  const options = {
    expires: new Date(
      Date.now() + process.env.COOKIE_TIME * 24 * 60 * 60 * 1000
    ),
    httpOnly: true,
  };

  user.password = undefined;
  res.status(200).cookie("token", token, options).json({
    success: true,
    token,
    user,
  });
};

module.exports = cookieToken;


================================================
FILE: tshirtstore/lcotshirtstore/utils/customError.js
================================================
class CustomError extends Error {
  constructor(message, code) {
    super(message);
    this.code = code;
  }
}

module.exports = CustomError;


================================================
FILE: tshirtstore/lcotshirtstore/utils/demotest.js
================================================
// User.find({ qty: { $lte: 20 } })
// /api/v1/product?search=coder&page=2&category=shortsleeves&rating[gte]=4
// &price[lte]=999&price[gte]=199

// rating: { $gte: '4' }

// URL - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace

// const p = 'gte gte lte mygte';

// const regex = /\b(gte|lte)\b/g;
// console.log(p.replace(regex, m => `$${m}`));


================================================
FILE: tshirtstore/lcotshirtstore/utils/emailHelper.js
================================================
const nodemailer = require("nodemailer");

const mailHelper = async (option) => {
  const transporter = nodemailer.createTransport({
    host: process.env.SMTP_HOST,
    port: process.env.SMTP_PORT,
    auth: {
      user: process.env.SMTP_USER, // generated ethereal user
      pass: process.env.SMTP_PASS, // generated ethereal password
    },
  });

  const message = {
    from: "hitesh@lco.dev", // sender address
    to: option.email, // list of receivers
    subject: option.subject, // Subject line
    text: option.message, // plain text body
  };

  // send mail with defined transport object
  await transporter.sendMail(message);
};

module.exports = mailHelper;


================================================
FILE: tshirtstore/lcotshirtstore/utils/testOrder.json
================================================
{
  "shippingInfo": {
    "address": "1 Jaipur",
    "city": "Jaipur",
    "phoneNo": "9898989898",
    "postalCode": "302020",
    "state": "Rajasthan",
    "country": "India"
  },
  "orderItems": [
    {
      "name": "Pro Coder tshirts",
      "quantity": 1,
      "image": "https://res.cloudinary.com/dk92l1yoc/image/upload/v1635757229/products/b4laryk4dbp6vdrvq3wv.png",
      "price": 999,
      "product": "617facb5333fd4c0fdfdee65"
    }
  ],
  "paymentInfo": {
    "id": "testString"
  },
  "taxAmount": 40,
  "shippingAmount": 10,
  "totalAmount": 100
}


================================================
FILE: tshirtstore/lcotshirtstore/utils/whereClause.js
================================================
// base - Product.find()
// base - Product.find(email: {"hitesh@lco.dev"})

//bigQ - //search=coder&page=2&category=shortsleeves&rating[gte]=4
// &price[lte]=999&price[gte]=199&limit=5

class WhereClause {
  constructor(base, bigQ) {
    this.base = base;
    this.bigQ = bigQ;
  }

  search() {
    const searchword = this.bigQ.search
      ? {
          name: {
            $regex: this.bigQ.search,
            $options: "i",
          },
        }
      : {};

    this.base = this.base.find({ ...searchword });
    return this;
  }

  filter() {
    const copyQ = { ...this.bigQ };

    delete copyQ["search"];
    delete copyQ["limit"];
    delete copyQ["page"];

    //convert bigQ into a string => copyQ
    let stringOfCopyQ = JSON.stringify(copyQ);

    stringOfCopyQ = stringOfCopyQ.replace(
      /\b(gte|lte|gt|lt)\b/g,
      (m) => `$${m}`
    );

    const jsonOfCopyQ = JSON.parse(stringOfCopyQ);

    this.base = this.base.find(jsonOfCopyQ);
    return this;
  }

  pager(resultperPage) {
    let currentPage = 1;
    if (this.bigQ.page) {
      currentPage = this.bigQ.page;
    }

    const skipVal = resultperPage * (currentPage - 1);

    this.base = this.base.limit(resultperPage).skip(skipVal);
    return this;
  }
}

module.exports = WhereClause;


================================================
FILE: tshirtstore/lcotshirtstore/views/signuptest.ejs
================================================
<!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">
    <!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <title>GET form</title>
</head>
<body class="bg-dark text-white">
    <div class="container mt-4 col-4 col-offset-6">
        <h1 class="display-3">POST form</h1>
        <form method="POST" action="/api/v1/signup" enctype="multipart/form-data">
            <div class="mb-3">
              <label for="name" class="form-label">firstname</label>
              <input type="text" name="name" class="form-control" id="name" aria-describedby="emailHelp">
            </div>
            <div class="mb-3">
              <label for="email" class="form-label">email</label>
              <input type="text" name="email" class="form-control" id="email" aria-describedby="emailHelp">
            </div>
            <div class="mb-3">
              <label for="password" class="form-label">email</label>
              <input type="password" name="password" class="form-control" id="password" aria-describedby="emailHelp">
            </div>
            
            <div class="mb-3">
              <label for="photo" class="form-label">samplefile</label>
              <input type="file" name="photo" multiple class="form-control" id="lastname">
            </div>
            
            <button type="submit" class="btn btn-primary">Submit</button>
          </form>
    </div>
</body>
</html>

================================================
FILE: tshirtstore/middlewares/bigPromise.js
================================================
// try catch and async - await || use promise

module.exports = (func) => (req, res, next) =>
  Promise.resolve(func(req, res, next)).catch(next);


================================================
FILE: tshirtstore/middlewares/productionError.js
================================================
const CustomError = require("../utils/customError");

module.exports = (err, req, res, next) => {
  let error = { ...err };
  error.message = err.message;

  res.status(error.statusCode || 500).json({
    success: false,
    message: error.message || "Internal Server Error",
  });
};


================================================
FILE: tshirtstore/middlewares/user.js
================================================
const User = require("../models/user");
const BigPromise = require("../middlewares/bigPromise");
const CustomError = require("../utils/customError");
const jwt = require("jsonwebtoken");

exports.isLoggedIn = BigPromise(async (req, res, next) => {
  // const token = req.cookies.token || req.header("Authorization").replace("Bearer ", "");

  // check token first in cookies
  let token = req.cookies.token;

  // if token not found in cookies, check if header contains Auth field
  if (!token && req.header("Authorization")) {
    token = req.header("Authorization").replace("Bearer ", "");
  }

  if (!token) {
    return next(new CustomError("Login first to access this page", 401));
  }

  const decoded = jwt.verify(token, process.env.JWT_SECRET);

  req.user = await User.findById(decoded.id);

  next();
});

exports.customRole = (...roles) => {
  return (req, res, next) => {
    if (!roles.includes(req.user.role)) {
      return next(new CustomError("You are not allowed for this resouce", 403));
    }
    console.log(req.user.role);
    next();
  };
};


================================================
FILE: tshirtstore/models/order.js
================================================
const mongoose = require("mongoose");

// shippingInfo{}
// user,
// paymentInfo{}
// taxAmount
// ShippingAmount
// totalAmount
// orderStatus
// deliveredAt
// createdAt
// -------------
// orderItems: [ {} ]
// - name
// - quantity
// - image[0]
// - price
// - product

const orderSchema = new mongoose.Schema({
  shippingInfo: {
    address: {
      type: String,
      required: true,
    },
    city: {
      type: String,
      required: true,
    },
    phoneNo: {
      type: String,
      required: true,
    },
    postalCode: {
      type: String,
      required: true,
    },
    state: {
      type: String,
      // required: true,
    },
    country: {
      type: String,
      required: true,
    },
  },
  user: {
    type: mongoose.Schema.ObjectId, //mongoose.Schema.Types.ObjectId
    ref: "User",
    required: true,
  },
  orderItems: [
    {
      name: {
        type: String,
        required: true,
      },
      quantity: {
        type: Number,
        required: true,
      },
      image: {
        type: String,
        required: true,
      },
      price: {
        type: Number,
        required: true,
      },
      product: {
        type: mongoose.Schema.ObjectId, //mongoose.Schema.Types.ObjectId
        ref: "Product",
        required: true,
      },
    },
  ],
  paymentInfo: {
    id: {
      type: String,
    },
  },
  taxAmount: {
    type: Number,
    required: true,
  },
  shippingAmount: {
    type: Number,
    required: true,
  },
  totalAmount: {
    type: Number,
    required: true,
  },
  orderStatus: {
    type: String,
    required: true,
    default: "processing",
  },
  deliveredAt: {
    type: Date,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

module.exports = mongoose.model("Order", orderSchema);

// ref link
// https://stackoverflow.com/questions/28997636/should-i-use-schema-types-objectid-or-schema-objectid-when-defining-a-mongoose-s


================================================
FILE: tshirtstore/models/product.js
================================================
const mongoose = require("mongoose");

const productSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, "please provide product name"],
    trim: true,
    maxlength: [120, "Product name should not be more than 120 characters"],
  },
  price: {
    type: Number,
    required: [true, "please provide product price"],
    maxlength: [6, "Product price should not be more than 6 digits"],
  },
  description: {
    type: String,
    required: [true, "please provide product description"],
  },
  photos: [
    {
      id: {
        type: String,
        required: true,
      },
      secure_url: {
        type: String,
        required: true,
      },
    },
  ],
  category: {
    type: String,
    required: [
      true,
      "please select category from- short-sleeves, long-sleeves, sweat-shirts, hoodies",
    ],
    enum: {
      values: ["shortsleeves", "longsleeves", "sweatshirt", "hoodies"],
      message:
        "please select category ONLY from - short-sleeves, long-sleeves, sweat-shirts and hoodies ",
    },
  },
  //this field was updated in order videos later
  stock: {
    type: Number,
    required: [true, "please add a number in stock"],
  },
  brand: {
    type: String,
    required: [true, "please add a brand for clothing"],
  },
  ratings: {
    type: Number,
    default: 0,
  },
  numberOfReviews: {
    type: Number,
    default: 0,
  },
  reviews: [
    {
      user: {
        type: mongoose.Schema.ObjectId,
        ref: "User",
        required: true,
      },
      name: {
        type: String,
        required: true,
      },
      rating: {
        type: Number,
        required: true,
      },
      comment: {
        type: String,
        required: true,
      },
    },
  ],
  user: {
    type: mongoose.Schema.ObjectId,
    ref: "User",
    required: true,
  },
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

module.exports = mongoose.model("Product", productSchema);


================================================
FILE: tshirtstore/models/user.js
================================================
const mongoose = require("mongoose");
const validator = require("validator");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const crypto = require("crypto");

const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: [true, "Please provide a name"],
    maxlength: [40, "Name should be under 40 characters"],
  },
  email: {
    type: String,
    required: [true, "Please provide an email"],
    validate: [validator.isEmail, "Please enter email in correct format"],
    unique: true,
  },
  password: {
    type: String,
    required: [true, "Please provide a password"],
    minlength: [6, "password should be atleast 6 char"],
    select: false,
  },
  role: {
    type: String,
    default: "user",
  },
  photo: {
    id: {
      type: String,
      required: true,
    },
    secure_url: {
      type: String,
      required: true,
    },
  },
  forgotPasswordToken: String,
  forgotPasswordExpiry: Date,
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

//encrypt password before save - HOOKS
userSchema.pre("save", async function (next) {
  if (!this.isModified("password")) {
    return next();
  }
  this.password = await bcrypt.hash(this.password, 10);
});

// validate the password with passed on user password
userSchema.methods.isValidatedPassword = async function (usersendPassword) {
  return await bcrypt.compare(usersendPassword, this.password);
};

//create and return jwt token
userSchema.methods.getJwtToken = function () {
  return jwt.sign({ id: this._id }, process.env.JWT_SECRET, {
    expiresIn: process.env.JWT_EXPIRY,
  });
};

//generate forgot password token (string)
userSchema.methods.getForgotPasswordToken = function () {
  // generate a long and randomg string
  const forgotToken = crypto.randomBytes(20).toString("hex");

  // getting a hash - make sure to get a hash on backend
  this.forgotPasswordToken = crypto
    .createHash("sha256")
    .update(forgotToken)
    .digest("hex");

  //time of token
  this.forgotPasswordExpiry = Date.now() + 20 * 60 * 1000;

  return forgotToken;
};

module.exports = mongoose.model("User", userSchema);


================================================
FILE: tshirtstore/nodemon.json
================================================
{
  "ext": ".js, .jsx, .yaml"
}


================================================
FILE: tshirtstore/package.json
================================================
{
  "name": "tshirtstore",
  "version": "1.0.0",
  "description": "a backend api for tshirt store",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js"
  },
  "keywords": [
    "api",
    "backend"
  ],
  "author": "hitesh choudhary",
  "license": "ISC",
  "dependencies": {
    "bcryptjs": "^2.4.3",
    "cloudinary": "^1.27.1",
    "cookie-parser": "^1.4.5",
    "dotenv": "^10.0.0",
    "ejs": "^3.1.6",
    "express": "^4.17.1",
    "express-fileupload": "^1.2.1",
    "jsonwebtoken": "^8.5.1",
    "mongoose": "^6.0.12",
    "morgan": "^1.10.0",
    "nodemailer": "^6.7.0",
    "razorpay": "^2.0.7",
    "stripe": "^8.184.0",
    "swagger-ui-express": "^4.1.6",
    "validator": "^13.6.0",
    "yamljs": "^0.3.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.14"
  }
}


================================================
FILE: tshirtstore/routes/home.js
================================================
const express = require("express");
const router = express.Router();

const { home, homeDummy } = require("../controllers/homeController");

router.route("/").get(home);
router.route("/dummy").get(homeDummy);

module.exports = router;


================================================
FILE: tshirtstore/routes/order.js
================================================
const express = require("express");
const {
  createOrder,
  getOneOrder,
  getLoggedInOrders,
  admingetAllOrders,
  adminUpdateOrder,
  adminDeleteOrder,
} = require("../controllers/orderController");
const router = express.Router();
const { isLoggedIn, customRole } = require("../middlewares/user");

router.route("/order/create").post(isLoggedIn, createOrder);
router.route("/order/:id").get(isLoggedIn, getOneOrder);
router.route("/myorder").get(isLoggedIn, getLoggedInOrders);

//admin routes
router
  .route("/admin/orders")
  .get(isLoggedIn, customRole("admin"), admingetAllOrders);
router
  .route("/admin/order/:id")
  .put(isLoggedIn, customRole("admin"), adminUpdateOrder)
  .delete(isLoggedIn, customRole("admin"), adminDeleteOrder);

module.exports = router;


================================================
FILE: tshirtstore/routes/payment.js
================================================
const express = require("express");
const router = express.Router();
const {
  sendRazorpayKey,
  sendStripeKey,
  captureStripePayment,
  captureRazorpayPayment,
} = require("../controllers/paymentController");
const { isLoggedIn } = require("../middlewares/user");

router.route("/stripekey").get(isLoggedIn, sendStripeKey);
router.route("/razorpaykey").get(isLoggedIn, sendRazorpayKey);

router.route("/capturestripe").post(isLoggedIn, captureStripePayment);
router.route("/capturerazorpay").post(isLoggedIn, captureRazorpayPayment);

module.exports = router;


================================================
FILE: tshirtstore/routes/product.js
================================================
const express = require("express");
const {
  addProduct,
  getAllProduct,
  adminGetAllProduct,
  getOneProduct,
  adminUpdateOneProduct,
  adminDeleteOneProduct,
  addReview,
  deleteReview,
  getOnlyReviewsForOneProduct,
} = require("../controllers/productController");
const router = express.Router();
const { isLoggedIn, customRole } = require("../middlewares/user");

//user routes
router.route("/products").get(getAllProduct);
router.route("/product/:id").get(getOneProduct);
router.route("/review").put(isLoggedIn, addReview);
router.route("/review").delete(isLoggedIn, deleteReview);
router.route("/reviews").get(isLoggedIn, getOnlyReviewsForOneProduct);

//admin routes
router
  .route("/admin/product/add")
  .post(isLoggedIn, customRole("admin"), addProduct);

router
  .route("/admin/products")
  .get(isLoggedIn, customRole("admin"), adminGetAllProduct);

router
  .route("/admin/product/:id")
  .put(isLoggedIn, customRole("admin"), adminUpdateOneProduct)
  .delete(isLoggedIn, customRole("admin"), adminDeleteOneProduct);

module.exports = router;


================================================
FILE: tshirtstore/routes/user.js
================================================
const express = require("express");
const router = express.Router();

const {
  signup,
  login,
  logout,
  forgotPassword,
  passwordReset,
  getLoggedInUserDetails,
  changePassword,
  updateUserDetails,
  adminAllUser,
  managerAllUser,
  admingetOneUser,
  adminUpdateOneUserDetails,
  adminDeleteOneUser,
} = require("../controllers/userController");
const { isLoggedIn, customRole } = require("../middlewares/user");

router.route("/signup").post(signup);
router.route("/login").post(login);
router.route("/logout").get(logout);
router.route("/forgotPassword").post(forgotPassword);
router.route("/password/reset/:token").put(passwordReset);
router.route("/userdashboard").get(isLoggedIn, getLoggedInUserDetails);
router.route("/password/update").put(isLoggedIn, changePassword);
router.route("/userdashboard/update").put(isLoggedIn, updateUserDetails);

//admin only routes
router.route("/admin/users").get(isLoggedIn, customRole("admin"), adminAllUser);
router
  .route("/admin/user/:id")
  .get(isLoggedIn, customRole("admin"), admingetOneUser)
  .put(isLoggedIn, customRole("admin"), adminUpdateOneUserDetails)
  .delete(isLoggedIn, customRole("admin"), adminDeleteOneUser);

// manager only route
router
  .route("/manager/users")
  .get(isLoggedIn, customRole("manager"), managerAllUser);
module.exports = router;


================================================
FILE: tshirtstore/swagger.yaml
================================================
openapi: "3.0.0"
info:
  title: Tshirt store API
  description: LCO - a course to create API for ecomm store
  version: 1.1.0
  contact:
    email: hitesh@lco.dev
    url: "https://lco.dev"

# servers:
#   - url: "https://localhost:4000/api/v1"
#     description: for local host - secure
#   - url: "http://localhost:4000/api/v1"
#     description: for local host - regular

servers:
  - url: "{protocol}://{url}/api/{version}"
    description: for local host 
    variables:
      version:
        enum:
          - v1
          - v2
        default: v1
      url:
        enum:
          - localhost:4000
          - lcotshirtstore.herokuapp.com
        default: lcotshirtstore.herokuapp.com
      protocol:
        enum:
          - http
          - https
        default: https

components:
  securitySchemes:
    cookieAuth:
      type: apiKey
      in: cookie
      name: token
    BearerAuth:
      type: http
      scheme: bearer


paths:
  /dummy:
    get:
      tags:
        - Home
      summary: returns a greet message from LCO
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: string
                example: "mystring"
        400:
          description: Bad request
        500:
          description: internal server error
  
  /signup:
    post:
      tags:
        - User
      summary: signup a new user. required files are - name, email, password and photo
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - name
                - email
                - password
                - photo
              properties:
                name:
                  type: string
                  required: true
                email:
                  type: string
                password:
                  type: string
                photo:
                  in: formData
                  description: The uploaded file data
                  type: file
                  format: binary
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  token:
                    type: string
                  user:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
                      role:
                        type: string
                      photo:
                        type: object
                        properties:
                          id:
                            type: string
                          secure_url:
                            type: string
                      _id:
                        type: string
                      createdAt:
                        type: string
        400:
          description: Bad request
        500:
          description: internal server error

  /login:
    post:
      tags:
        - User
      summary: login a new user. required files are -  email and password. Also adds httpOnly cookie in browser. It sends token in response too.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - password
              properties:
                email:
                  type: string
                password:
                  type: string
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  token:
                    type: string
                  user:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
                      role:
                        type: string
                      photo:
                        type: object
                        properties:
                          id:
                            type: string
                          secure_url:
                            type: string
                      _id:
                        type: string
                      createdAt:
                        type: string
        400:
          description: Bad request
        500:
          description: internal server error

  /logout:
    get:
      tags:
        - User
      summary: get request to logout the user. Also removes httpOnly cookies 
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  
        400:
          description: Bad request
        500:
          description: internal server error

  /forgotPassword:
    post:
      tags:
        - User
      summary: sends an email with link to forgot password. Contains the token for user validation. Public hosted version will not send email to your account. Use your own SMTP details to access this feature on local project
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - email
              properties:
                email:
                  type: string
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
        400:
          description: Bad request
        500:
          description: internal server error

  /password/reset/{token}:
    post:
      tags:
        - User
      summary: Allows user to reset password, validated based on token. send password and confirm password fields
      parameters:
        - name: token
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - password
                - confirmPassword
              properties:
                password:
                  type: string
                confirmPassword:
                  type: string
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  token:
                    type: string
                  user:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
                      role:
                        type: string
                      photo:
                        type: object
                        properties:
                          id:
                            type: string
                          secure_url:
                            type: string
                      _id:
                        type: string
                      createdAt:
                        type: string
        400:
          description: Bad request
        500:
          description: internal server error

  /userdashboard:
    get:
      tags:
        - User
      summary: Gets all details about logged in user. Send token in cookies as named token or send Bearer Auth
      requestBody:
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  user:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
                      role:
                        type: string
                      photo:
                        type: object
                        properties:
                          id:
                            type: string
                          secure_url:
                            type: string
                      _id:
                        type: string
                      createdAt:
                        type: string
        400:
          description: Bad request
        500:
          description: internal server error

  /password/update:
    post:
      tags:
        - User
      summary: User can update the password if he is logged in. Send oldPassword and password
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - oldPassword
                - password
              properties:
                oldPassword:
                  type: string
                password:
                  type: string
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string
                  user:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
                      role:
                        type: string
                      photo:
                        type: object
                        properties:
                          id:
                            type: string
                          secure_url:
                            type: string
                      _id:
                        type: string
                      createdAt:
                        type: string
        400:
          description: Bad request
        500:
          description: internal server error

  /userdashboard/update:
    post:
      tags:
        - User
      summary: User can update the name, emails and photo. Photo is optional
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - name
                - email
              properties:
                name:
                  type: string
                email:
                  type: string
                photo:
                  in: formData
                  description: The uploaded file data
                  type: file
                  format: binary
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  
        400:
          description: Bad request
        500:
          description: internal server error

  /admin/users:
    get:
      tags:
        - Admin
      summary: If user is admin, response will get array of all users
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    user:
                      type: object
                      properties:
                        name:
                          type: string
                        email:
                          type: string
                        role:
                          type: string
                        photo:
                          type: object
                          properties:
                            id:
                              type: string
                            secure_url:
                              type: string
                        _id:
                          type: string
                        createdAt:
                          type: string
                  
        400:
          description: Bad request
        500:
          description: internal server error

  /admin/user/{id}:
    get:
      tags:
        - Admin
      summary: If user is admin, response will get details of 1 user
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                  type: object
                  properties:
                    user:
                      type: object
                      properties:
                        name:
                          type: string
                        email:
                          type: string
                        role:
                          type: string
                        photo:
                          type: object
                          properties:
                            id:
                              type: string
                            secure_url:
                              type: string
                        _id:
                          type: string
                        createdAt:
                          type: string
                  
        400:
          description: Bad request
        500:
          description: internal server error
    put:
      tags:
        - Admin
      summary: If user is admin, he can update mentioned fields in user
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        - name: name
          in: formData
          required: true
          schema:
            type: string
        - name: email
          in: formData
          required: true
          schema:
            type: string
        - name: role
          in: formData
          required: true
          schema:
            type: string
            enum: [user, admin, manager]
      requestBody: 
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                  type: object
                  properties:
                    success:
                      type: boolean
                  
        400:
          description: Bad request
        500:
          description: internal server error
    delete:
      tags:
        - Admin
      summary: If user is admin, delete the user with given id
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody: 
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                  type: object
                  properties:
                    success:
                      type: boolean
                  
        400:
          description: Bad request
        500:
          description: internal server error

  /manager/users:
    get:
      tags:
        - Manager
      summary: If manager, response will get array of all users whose role is user
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    user:
                      type: object
                      properties:
                        name:
                          type: string
                        email:
                          type: string
                        role:
                          type: string
                        photo:
                          type: object
                          properties:
                            id:
                              type: string
                            secure_url:
                              type: string
                        _id:
                          type: string
                        createdAt:
                          type: string
                  
        400:
          description: Bad request
        500:
          description: internal server error

  /products:
    get:
      tags:
        - Product
      summary: A simple get request will give you all available products
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  filteredProductNumber:
                    type: number
                  totalcountProduct:
                    type: number
                  products:
                    type: array
                    items:
                      type: object
                      properties:
                        _id:
                          type: string
                        name:
                          type: string
                        price: 
                          type: number
                        description: 
                          type: string
                        category: 
                          type: string
                        brand: 
                          type: string
                        ratings: 
                          type: number
                        numberOfReviews: 
                          type: number
                        user: 
                          type: string
                        photos: 
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: string
                              secure_url:
                                type: string
                        reviews: 
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: string
                              comment:
                                type: string
                              user:
                                type: string
                              name:
                                type: string
                              rating:
                                type: number
        400:
          description: Bad request
        500:
          description: internal server error

  /product/{id}:
    get:
      tags:
        - Product
      summary: Get a single product
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  product:
                    type: object
                    properties:
                      _id:
                        type: string
                      name:
                        type: string
                      price: 
                        type: number
                      description: 
                        type: string
                      category: 
                        type: string
                      brand: 
                        type: string
                      ratings: 
                        type: number
                      numberOfReviews: 
                        type: number
                      user: 
                        type: string
                      photos: 
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            secure_url:
                              type: string
                      reviews: 
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            comment:
                              type: string
                            user:
                              type: string
                            name:
                              type: string
                            rating:
                              type: number
        400:
          description: Bad request
        500:
          description: internal server error

  /admin/products:
    get:
      tags:
        - Admin
      summary: If user is admin, he get all products
      
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  products:
                    type: array
                    items:
                      type: object
                      properties:
                        _id:
                          type: string
                        name:
                          type: string
                        price: 
                          type: number
                        description: 
                          type: string
                        category: 
                          type: string
                        brand: 
                          type: string
                        ratings: 
                          type: number
                        numberOfReviews: 
                          type: number
                        user: 
                          type: string
                        photos: 
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: string
                              secure_url:
                                type: string
                        reviews: 
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: string
                              comment:
                                type: string
                              user:
                                type: string
                              name:
                                type: string
                              rating:
                                type: number
        400:
          description: Bad request
        500:
          description: internal server error

  /admin/product/add:
    post:
      tags:
        - Admin
      summary: If admin, Add a product

        
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - name
                - price
                - description
                - category
                - stock
                - brand
                - photos
              properties:
                name:
                  type: string
                  required: true
                price:
                  type: number
                  required: true
                description:
                  type: string
                  required: true
                category:
                  type: string
                  required: true
                  enum: [shortsleeves, longsleeves, sweatshirt, hoodies]
                stock:
                  type: number
                  required: true
                brand:
                  type: string
                  required: true
                photos:
                  in: formData
                  description: The uploaded photos
                  type: array
                  items:
                    type: file
                    format: binary
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  product:
                    type: object
                    properties:
                      _id:
                        type: string
                      name:
                        type: string
                      price: 
                        type: number
                      description: 
                        type: string
                      category: 
                        type: string
                      brand: 
                        type: string
                      ratings: 
                        type: number
                      numberOfReviews: 
                        type: number
                      user: 
                        type: string
                      photos: 
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            secure_url:
                              type: string
                      reviews: 
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            comment:
                              type: string
                            user:
                              type: string
                            name:
                              type: string
                            rating:
                              type: number
        400:
          description: Bad request
        500:
          description: internal server error
  
  /admin/product/{id}:
    put:
      tags:
        - Admin
      summary: If admin, update the product. photos are optional to pass. Rest all body is set to be updated to what you pass here.
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - name
                - price
                - description
                - category
                - stock
                - brand
              properties:
                name:
                  type: string
                  required: true
                price:
                  type: number
                  required: true
                description:
                  type: number
                  required: true
                category:
                  type: string
                  required: true
                  enum: [shortsleeves, longsleeves, sweatshirt, hoodies]
                stock:
                  type: number
                  required: true
                brand:
                  type: string
                  required: true
                photos:
                  in: formData
                  description: The uploaded photos
                  type: file
                  format: binary
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  product:
                    type: object
                    properties:
                      _id:
                        type: string
                      name:
                        type: string
                      price: 
                        type: number
                      description: 
                        type: string
                      category: 
                        type: string
                      brand: 
                        type: string
                      ratings: 
                        type: number
                      numberOfReviews: 
                        type: number
                      user: 
                        type: string
                      photos: 
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            secure_url:
                              type: string
                      reviews: 
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            comment:
                              type: string
                            user:
                              type: string
                            name:
                              type: string
                            rating:
                              type: number
        400:
          description: Bad request
        500:
          description: internal server error
    delete:
      tags:
        - Admin
      summary: If admin, pass the id of product and product will be removed
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
        
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  
        400:
          description: Bad request
        500:
          description: internal server error

  /reviews:
      get:
        tags:
          - Product
        summary: A simple get request will give you all reviews for given products
        parameters:
        - name: id
          in: query
          description: id of the product
          required: true
          schema:
            type: string
        requestBody:
          
        responses:
          200:
            description: All good success
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    success:
                      type: boolean
                    reviews:
                      type: array
                      items:
                        type: object
                        properties:
                          user:
                            type: string
                          name:
                            type: string
                          rating: 
                            type: number
                          comment: 
                            type: string
                          _id: 
                            type: string
                          
          400:
            description: Bad request
          500:
            description: internal server error
  
  /review:
      put:
        tags:
          - Product
        summary: A logged in user can post a review on any product. If review is already posted, it will just update the existing review
        parameters:
        
        requestBody:
          content:
            application/json:
              schema:
                type: object
                required:
                  - rating
                  - comment
                  - productId
                properties:
                  rating:
                    type: number
                    required: true
                  comment:
                    type: string
                    required: true
                  productId:
                    type: string
                    required: true
        responses:
          200:
            description: All good success
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    success:
                      type: boolean
                    reviews:
                      type: array
                      items:
                        type: object
                        properties:
                          user:
                            type: string
                          name:
                            type: string
                          rating: 
                            type: number
                          comment: 
                            type: string
                          _id: 
                            type: string
                          
          400:
            description: Bad request
          500:
            description: internal server error
      delete:
        tags:
          - Product
        summary: Delete the review of logged in user on given product id.
        parameters:
        - name: productId
          in: query
          required: true
          schema:
            type: string
        
        requestBody:
          content:
            application/json:
              schema:
                type: object
                required:
                  - rating
                  - comment
                  - productId
                properties:
                  rating:
                    type: number
                    required: true
                  comment:
                    type: string
                    required: true
                  productId:
                    type: string
                    required: true
        responses:
          200:
            description: All good success
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    success:
                      type: boolean
                    reviews:
                      type: array
                      items:
                        type: object
                        properties:
                          user:
                            type: string
                          name:
                            type: string
                          rating: 
                            type: number
                          comment: 
                            type: string
                          _id: 
                            type: string
                          
          400:
            description: Bad request
          500:
            description: internal server error

  /order/create:
    post:
      tags:
        - Order
      summary: create a new order with given details
      parameters:
      
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - shippingInfo
                - paymentInfo
                - taxAmount
                - shippingAmount
                - totalAmount
                - orderItems
              properties:
                shippingInfo:
                  type: object
                  properties:
                    address:
                      type: string
                    city: 
                      type: string
                    phoneNo: 
                      type: string
                    postalCode: 
                      type: string
                    state: 
                      type: string
                    country: 
                      type: string
                paymentInfo:
                  type: object
                  properties:
                    id:
                      type: string
                taxAmount:
                  type: number
                shippingAmount:
                  type: number
                totalAmount:
                  type: number
                orderItems:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                      quantity:
                        type: string
                      image:
                        type: string
                      price:
                        type: number
                      product:
                        type: string
                        description: id of product
                  
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  order:
                    type: object
                    properties:
                      _id:
                        type: string
                      user:
                        type: string
                      orderStatus:
                        type: string
                      createdAt:
                        type: string
                      shippingInfo:
                        type: object
                        properties:
                          address:
                            type: string
                          city: 
                            type: string
                          phoneNo: 
                            type: string
                          postalCode: 
                            type: string
                          state: 
                            type: string
                          country: 
                            type: string
                      paymentInfo:
                        type: object
                        properties:
                          id:
                            type: string
                      taxAmount:
                        type: number
                      shippingAmount:
                        type: number
                      totalAmount:
                        type: number
                      orderItems:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            quantity:
                              type: string
                            image:
                              type: string
                            price:
                              type: number
                            product:
                              type: string
                              description: id of product
                        
        400:
          description: Bad request
        500:
          description: internal server error

  /order/{id}:
    get:
      tags:
        - Order
      summary: get details about a order with order id
      parameters:
        - name: id
          in: path
          required: true
          description: id of the order
          schema:
            type: string
      
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  order:
                    type: object
                    properties:
                      _id:
                        type: string
                      user:
                        type: object
                        properties:
                          name:
                            type: string
                          email:
                            type: string
                          id:
                            type: string
                      orderStatus:
                        type: string
                      createdAt:
                        type: string
                      shippingInfo:
                        type: object
                        properties:
                          address:
                            type: string
                          city: 
                            type: string
                          phoneNo: 
                            type: string
                          postalCode: 
                            type: string
                          state: 
                            type: string
                          country: 
                            type: string
                      paymentInfo:
                        type: object
                        properties:
                          id:
                            type: string
                      taxAmount:
                        type: number
                      shippingAmount:
                        type: number
                      totalAmount:
                        type: number
                      orderItems:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            quantity:
                              type: string
                            image:
                              type: string
                            price:
                              type: number
                            product:
                              type: string
                              description: id of product
                        
        400:
          description: Bad request
        500:
          description: internal server error

  /myorder:
    get:
      tags:
        - Order
      summary: get order of logged in user
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  order:
                    type: object
                    properties:
                      _id:
                        type: string
                      user:
                        type: object
                        properties:
                          name:
                            type: string
                          email:
                            type: string
                          id:
                            type: string
                      orderStatus:
                        type: string
                      createdAt:
                        type: string
                      shippingInfo:
                        type: object
                        properties:
                          address:
                            type: string
                          city: 
                            type: string
                          phoneNo: 
                            type: string
                          postalCode: 
                            type: string
                          state: 
                            type: string
                          country: 
                            type: string
                      paymentInfo:
                        type: object
                        properties:
                          id:
                            type: string
                      taxAmount:
                        type: number
                      shippingAmount:
                        type: number
                      totalAmount:
                        type: number
                      orderItems:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            quantity:
                              type: string
                            image:
                              type: string
                            price:
                              type: number
                            product:
                              type: string
                              description: id of product
                        
        400:
          description: Bad request
        500:
          description: internal server error

  /admin/orders:
    get:
      tags:
        - Admin
      summary: if admin, get list of all orders
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  orders:
                    type: array
                    items:
                      properties:
                        _id:
                          type: string
                        user:
                          type: string
                        orderStatus:
                          type: string
                        createdAt:
                          type: string
                        shippingInfo:
                          type: object
                          properties:
                            address:
                              type: string
                            city: 
                              type: string
                            phoneNo: 
                              type: string
                            postalCode: 
                              type: string
                            state: 
                              type: string
                            country: 
                              type: string
                        paymentInfo:
                          type: object
                          properties:
                            id:
                              type: string
                        taxAmount:
                          type: number
                        shippingAmount:
                          type: number
                        totalAmount:
                          type: number
                        orderItems:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                              quantity:
                                type: string
                              image:
                                type: string
                              price:
                                type: number
                              product:
                                type: string
                                description: id of product
                        
        400:
          description: Bad request
        500:
          description: internal server error

  /admin/order/{id}:
    put:
      tags:
        - Admin
      summary: if admin, update the status of the order
      parameters:
        - name: id
          in: path
          required: true
          description: id of the order
          schema:
            type: string
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - orderStatus
              properties:
                orderStatus:
                  type: string
                  enum: [Processing, Delivered]
                  required: true
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  order:
                    type: object
                    properties:
                      _id:
                        type: string
                      user:
                        type: string
                      orderStatus:
                        type: string
                      createdAt:
                        type: string
                      shippingInfo:
                        type: object
                        properties:
                          address:
                            type: string
                          city: 
                            type: string
                          phoneNo: 
                            type: string
                          postalCode: 
                            type: string
                          state: 
                            type: string
                          country: 
                            type: string
                      paymentInfo:
                        type: object
                        properties:
                          id:
                            type: string
                      taxAmount:
                        type: number
                      shippingAmount:
                        type: number
                      totalAmount:
                        type: number
                      orderItems:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            quantity:
                              type: string
                            image:
                              type: string
                            price:
                              type: number
                            product:
                              type: string
                              description: id of product
                        
        400:
          description: Bad request
        500:
          description: internal server error
    delete:
      tags:
        - Admin
      summary: if admin, delete an order with given id
      parameters:
        - name: id
          in: path
          required: true
          description: id of the order
          schema:
            type: string
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
        400:
          description: Bad request
        500:
          description: internal server error

  /stripekey:
    get:
      tags:
        - Payment
      summary: gets you the public stripe key
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  stripekey:
                    type: string
                                 
        400:
          description: Bad request
        500:
          description: internal server error

  /razorpaykey:
    get:
      tags:
        - Payment
      summary: gets you the public razorpay key
      requestBody:
        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  razorpaykey:
                    type: string
                                 
        400:
          description: Bad request
        500:
          description: internal server error

  /capturestripe:
    post:
      tags:
        - Payment
      summary: send amount in number. Send amount after multiplying by 100. Also request from swagger UI are not proper as to capture payment we need to send dummy card details
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - amount
              properties:
                amount:
                  type: number

        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  amount:
                    type: number
                  client_secret:
                    type: string
                                 
        400:
          description: Bad request
        500:
          description: internal server error

  /capturerazorpay:
    post:
      tags:
        - Payment
      summary: send amount in number. Send amount after multiplying by 100. Check orders tab, not payments. Also request from swagger UI are not proper as to capture payment we need to send dummy card details.
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - amount
              properties:
                amount:
                  type: number

        
      responses:
        200:
          description: All good success
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  amount:
                    type: number
                  order:
                    type: object
                    properties:
                      id:
                        type: string
                      amount:
                        type: number
                      currency:
                        type: string
                                 
        400:
          description: Bad request
        500:
          description: internal server error



================================================
FILE: tshirtstore/utils/cookieToken.js
================================================
const cookieToken = (user, res) => {
  const token = user.getJwtToken();

  const options = {
    expires: new Date(
      Date.now() + process.env.COOKIE_TIME * 24 * 60 * 60 * 1000
    ),
    httpOnly: true,
  };

  user.password = undefined;
  res.status(200).cookie("token", token, options).json({
    success: true,
    token,
    user,
  });
};

module.exports = cookieToken;


================================================
FILE: tshirtstore/utils/customError.js
================================================
class CustomError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
    Error.captureStackTrace(this, this.constructor)
  }
}

module.exports = CustomError;


================================================
FILE: tshirtstore/utils/demotest.js
================================================
// User.find({ qty: { $lte: 20 } })
// /api/v1/product?search=coder&page=2&category=shortsleeves&rating[gte]=4
// &price[lte]=999&price[gte]=199

// rating: { $gte: '4' }

// URL - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace

// const p = 'gte gte lte mygte';

// const regex = /\b(gte|lte)\b/g;
// console.log(p.replace(regex, m => `$${m}`));


================================================
FILE: tshirtstore/utils/emailHelper.js
================================================
const nodemailer = require("nodemailer");

const mailHelper = async (option) => {
  const transporter = nodemailer.createTransport({
    host: process.env.SMTP_HOST,
    port: process.env.SMTP_PORT,
    auth: {
      user: process.env.SMTP_USER, // generated ethereal user
      pass: process.env.SMTP_PASS, // generated ethereal password
    },
  });

  const message = {
    from: "hitesh@lco.dev", // sender address
    to: option.email, // list of receivers
    subject: option.subject, // Subject line
    text: option.message, // plain text body
  };

  // send mail with defined transport object
  await transporter.sendMail(message);
};

module.exports = mailHelper;


================================================
FILE: tshirtstore/utils/testOrder.json
================================================
{
  "shippingInfo": {
    "address": "1 Jaipur",
    "city": "Jaipur",
    "phoneNo": "9898989898",
    "postalCode": "302020",
    "state": "Rajasthan",
    "country": "India"
  },
  "orderItems": [
    {
      "name": "Pro Coder tshirts",
      "quantity": 1,
      "image": "https://res.cloudinary.com/dk92l1yoc/image/upload/v1635757229/products/b4laryk4dbp6vdrvq3wv.png",
      "price": 999,
      "product": "617facb5333fd4c0fdfdee65"
    }
  ],
  "paymentInfo": {
    "id": "testString"
  },
  "taxAmount": 40,
  "shippingAmount": 10,
  "totalAmount": 100
}


================================================
FILE: tshirtstore/utils/whereClause.js
================================================
// base - Product.find()
// base - Product.find(email: {"hitesh@lco.dev"})

//bigQ - //search=coder&page=2&category=shortsleeves&rating[gte]=4
// &price[lte]=999&price[gte]=199&limit=5

class WhereClause {
  constructor(base, bigQ) {
    this.base = base;
    this.bigQ = bigQ;
  }

  search() {
    const searchword = this.bigQ.search
      ? {
          name: {
            $regex: this.bigQ.search,
            $options: "i",
          },
        }
      : {};

    this.base = this.base.find({ ...searchword });
    return this;
  }

  filter() {
    const copyQ = { ...this.bigQ };

    delete copyQ["search"];
    delete copyQ["limit"];
    delete copyQ["page"];

    //convert bigQ into a string => copyQ
    let stringOfCopyQ = JSON.stringify(copyQ);

    stringOfCopyQ = stringOfCopyQ.replace(
      /\b(gte|lte|gt|lt)\b/g,
      (m) => `$${m}`
    );

    const jsonOfCopyQ = JSON.parse(stringOfCopyQ);

    this.base = this.base.find(jsonOfCopyQ);
    return this;
  }

  pager(resultperPage) {
    let currentPage = 1;
    if (this.bigQ.page) {
      currentPage = this.bigQ.page;
    }

    const skipVal = resultperPage * (currentPage - 1);

    this.base = this.base.limit(resultperPage).skip(skipVal);
    return this;
  }
}

module.exports = WhereClause;


================================================
FILE: tshirtstore/views/home.ejs
================================================
<!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">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" >
    <title>LCO Tshirt store</title>
</head>
<body class="bg-dark ">
    <div class="container mt-5">
        <div class="row">
            <div class="col-sm-6 mt-2">
              <div class="card">
                <div class="card-body">
                  <h5 class="card-title">Read API docs here</h5>
                  <p class="card-text">All API docs are available here. You have access to everything except admin credentials. If you are a team member of LCO, get it from me (Hitesh)</p>
                  <a href="/api-docs" class="btn btn-primary">Store DOCS</a>
                </div>
              </div>
            </div>
            <div class="col-sm-6 mt-2">
              <div class="card">
                <div class="card-body">
                  <h5 class="card-title">LCO course</h5>
                  <p class="card-text">You can visit our courses at LearnCodeonline. There is something amazing for everyone there.</p>
                  <a href="https://courses.learncodeonline.in/learn" target="_blank" class="btn btn-primary">Visit LCO</a>
                </div>
              </div>
            </div>
          </div>
    </div>
</body>
</html>

================================================
FILE: tshirtstore/views/signuptest.ejs
================================================
<!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">
    <!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <title>GET form</title>
</head>
<body class="bg-dark text-white">
    <div class="container mt-4 col-4 col-offset-6">
        <h1 class="display-3">POST form</h1>
        <form method="POST" action="/api/v1/signup" enctype="multipart/form-data">
            <div class="mb-3">
              <label for="name" class="form-label">firstname</label>
              <input type="text" name="name" class="form-control" id="name" aria-describedby="emailHelp">
            </div>
            <div class="mb-3">
              <label for="email" class="form-label">email</label>
              <input type="text" name="email" class="form-control" id="email" aria-describedby="emailHelp">
            </div>
            <div class="mb-3">
              <label for="password" class="form-label">email</label>
              <input type="password" name="password" class="form-control" id="password" aria-describedby="emailHelp">
            </div>
            
            <div class="mb-3">
              <label for="photo" class="form-label">samplefile</label>
              <input type="file" name="photo" multiple class="form-control" id="lastname">
            </div>
            
            <button type="submit" class="btn btn-primary">Submit</button>
          </form>
    </div>
</body>
</html>
Download .txt
gitextract_2i27geyc/

├── formsandimages/
│   ├── index.js
│   ├── package.json
│   └── views/
│       ├── getform.ejs
│       └── postform.ejs
├── lcoauthsystem/
│   ├── app.js
│   ├── config/
│   │   └── database.js
│   ├── index.js
│   ├── middleware/
│   │   └── auth.js
│   ├── model/
│   │   └── user.js
│   └── package.json
├── lcopassportgoogle/
│   ├── index.js
│   ├── model/
│   │   └── user.js
│   ├── package.json
│   ├── passport/
│   │   └── passport.js
│   ├── routes/
│   │   └── auth.js
│   └── views/
│       ├── home.ejs
│       └── login.ejs
├── mydocslco/
│   ├── index.js
│   ├── nodemon.json
│   ├── package.json
│   └── swagger.yaml
├── razorpay/
│   ├── index.js
│   ├── package.json
│   └── public/
│       └── index.html
├── readme.md
├── socialapp/
│   ├── .gitignore
│   ├── index.js
│   ├── nodemon.json
│   ├── package.json
│   └── swagger.yaml
└── tshirtstore/
    ├── .gitignore
    ├── README.md
    ├── app.js
    ├── config/
    │   └── db.js
    ├── controllers/
    │   ├── homeController.js
    │   ├── orderController.js
    │   ├── paymentController.js
    │   ├── productController.js
    │   └── userController.js
    ├── index.js
    ├── lcotshirtstore/
    │   ├── .gitignore
    │   ├── app.js
    │   ├── config/
    │   │   └── db.js
    │   ├── controllers/
    │   │   ├── homeController.js
    │   │   ├── orderController.js
    │   │   ├── paymentController.js
    │   │   ├── productController.js
    │   │   └── userController.js
    │   ├── index.js
    │   ├── middlewares/
    │   │   ├── bigPromise.js
    │   │   └── user.js
    │   ├── models/
    │   │   ├── order.js
    │   │   ├── product.js
    │   │   └── user.js
    │   ├── nodemon.json
    │   ├── package.json
    │   ├── routes/
    │   │   ├── home.js
    │   │   ├── order.js
    │   │   ├── payment.js
    │   │   ├── product.js
    │   │   └── user.js
    │   ├── swagger.yaml
    │   ├── utils/
    │   │   ├── cookieToken.js
    │   │   ├── customError.js
    │   │   ├── demotest.js
    │   │   ├── emailHelper.js
    │   │   ├── testOrder.json
    │   │   └── whereClause.js
    │   └── views/
    │       └── signuptest.ejs
    ├── middlewares/
    │   ├── bigPromise.js
    │   ├── productionError.js
    │   └── user.js
    ├── models/
    │   ├── order.js
    │   ├── product.js
    │   └── user.js
    ├── nodemon.json
    ├── package.json
    ├── routes/
    │   ├── home.js
    │   ├── order.js
    │   ├── payment.js
    │   ├── product.js
    │   └── user.js
    ├── swagger.yaml
    ├── utils/
    │   ├── cookieToken.js
    │   ├── customError.js
    │   ├── demotest.js
    │   ├── emailHelper.js
    │   ├── testOrder.json
    │   └── whereClause.js
    └── views/
        ├── home.ejs
        └── signuptest.ejs
Download .txt
SYMBOL INDEX (21 symbols across 10 files)

FILE: mydocslco/index.js
  constant YAML (line 6) | const YAML = require("yamljs");

FILE: socialapp/index.js
  constant YAML (line 7) | const YAML = require("yamljs");
  constant PORT (line 12) | const PORT = process.env.PORT || 4000;

FILE: tshirtstore/app.js
  constant YAML (line 10) | const YAML = require("yamljs");

FILE: tshirtstore/controllers/orderController.js
  function updateProductStock (line 102) | async function updateProductStock(productId, quantity) {

FILE: tshirtstore/lcotshirtstore/app.js
  constant YAML (line 10) | const YAML = require("yamljs");

FILE: tshirtstore/lcotshirtstore/controllers/orderController.js
  function updateProductStock (line 102) | async function updateProductStock(productId, quantity) {

FILE: tshirtstore/lcotshirtstore/utils/customError.js
  class CustomError (line 1) | class CustomError extends Error {
    method constructor (line 2) | constructor(message, code) {

FILE: tshirtstore/lcotshirtstore/utils/whereClause.js
  class WhereClause (line 7) | class WhereClause {
    method constructor (line 8) | constructor(base, bigQ) {
    method search (line 13) | search() {
    method filter (line 27) | filter() {
    method pager (line 48) | pager(resultperPage) {

FILE: tshirtstore/utils/customError.js
  class CustomError (line 1) | class CustomError extends Error {
    method constructor (line 2) | constructor(message, statusCode) {

FILE: tshirtstore/utils/whereClause.js
  class WhereClause (line 7) | class WhereClause {
    method constructor (line 8) | constructor(base, bigQ) {
    method search (line 13) | search() {
    method filter (line 27) | filter() {
    method pager (line 48) | pager(resultperPage) {
Condensed preview — 91 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (194K chars).
[
  {
    "path": "formsandimages/index.js",
    "chars": 1747,
    "preview": "const express = require(\"express\");\nconst fileUpload = require(\"express-fileupload\");\nconst cloudinary = require(\"cloudi"
  },
  {
    "path": "formsandimages/package.json",
    "chars": 391,
    "preview": "{\n  \"name\": \"formsandimages\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start"
  },
  {
    "path": "formsandimages/views/getform.ejs",
    "chars": 1326,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
  },
  {
    "path": "formsandimages/views/postform.ejs",
    "chars": 1581,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
  },
  {
    "path": "lcoauthsystem/app.js",
    "chars": 2639,
    "preview": "require(\"dotenv\").config();\nrequire(\"./config/database\").connect();\nconst express = require(\"express\");\nconst bcrypt = r"
  },
  {
    "path": "lcoauthsystem/config/database.js",
    "chars": 389,
    "preview": "const mongoose = require(\"mongoose\");\n\nconst { MONGODB_URL } = process.env;\n\nexports.connect = () => {\n  mongoose\n    .c"
  },
  {
    "path": "lcoauthsystem/index.js",
    "chars": 138,
    "preview": "const app = require(\"./app\");\nconst { PORT } = process.env;\n\napp.listen(PORT, () => console.log(`Server is running at po"
  },
  {
    "path": "lcoauthsystem/middleware/auth.js",
    "chars": 581,
    "preview": "const jwt = require(\"jsonwebtoken\");\n\n//model is optional\n\nconst auth = (req, res, next) => {\n  console.log(req.cookies)"
  },
  {
    "path": "lcoauthsystem/model/user.js",
    "chars": 374,
    "preview": "const mongoose = require(\"mongoose\");\n\nconst userSchema = new mongoose.Schema({\n  firstname: {\n    type: String,\n    def"
  },
  {
    "path": "lcoauthsystem/package.json",
    "chars": 471,
    "preview": "{\n  \"name\": \"lcoauthsystem\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start\""
  },
  {
    "path": "lcopassportgoogle/index.js",
    "chars": 881,
    "preview": "const express = require(\"express\");\nconst mongoose = require(\"mongoose\");\nconst auth = require(\"./routes/auth\");\nconst p"
  },
  {
    "path": "lcopassportgoogle/model/user.js",
    "chars": 191,
    "preview": "const mongoose = require(\"mongoose\");\n\nconst userSchema = new mongoose.Schema({\n  name: String,\n  googleId: String,\n  em"
  },
  {
    "path": "lcopassportgoogle/package.json",
    "chars": 483,
    "preview": "{\n  \"name\": \"lcopassportgoogle\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"st"
  },
  {
    "path": "lcopassportgoogle/passport/passport.js",
    "chars": 1256,
    "preview": "const passport = require(\"passport\");\nconst User = require(\"../model/user\");\n\nvar GoogleStrategy = require(\"passport-goo"
  },
  {
    "path": "lcopassportgoogle/routes/auth.js",
    "chars": 531,
    "preview": "const router = require(\"express\").Router();\nconst passport = require(\"passport\");\n\nrouter.get(\"/login\", (req, res) => {\n"
  },
  {
    "path": "lcopassportgoogle/views/home.ejs",
    "chars": 909,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
  },
  {
    "path": "lcopassportgoogle/views/login.ejs",
    "chars": 932,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
  },
  {
    "path": "mydocslco/index.js",
    "chars": 1667,
    "preview": "const express = require(\"express\");\n\nconst app = express();\n\nconst swaggerUi = require(\"swagger-ui-express\");\nconst YAML"
  },
  {
    "path": "mydocslco/nodemon.json",
    "chars": 32,
    "preview": "{\n  \"ext\": \".js, .jsx, .yaml\"\n}\n"
  },
  {
    "path": "mydocslco/package.json",
    "chars": 369,
    "preview": "{\n  \"name\": \"mydocslco\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start\": \"n"
  },
  {
    "path": "mydocslco/swagger.yaml",
    "chars": 5414,
    "preview": "openapi: \"3.0.0\"\ninfo:\n  title: learn express and swagger - LearnCodeOnline\n  description: LCO - a course segment about "
  },
  {
    "path": "razorpay/index.js",
    "chars": 913,
    "preview": "const express = require(\"express\");\nconst Razorpay = require(\"razorpay\");\nconst app = express();\napp.use(express.static("
  },
  {
    "path": "razorpay/package.json",
    "chars": 269,
    "preview": "{\n  \"name\": \"razorpay\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start\": \"no"
  },
  {
    "path": "razorpay/public/index.html",
    "chars": 1533,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
  },
  {
    "path": "readme.md",
    "chars": 471,
    "preview": "# welcome to pro backend developer course code files\n\n## If you like this course, please drop a thanks node at my social"
  },
  {
    "path": "socialapp/.gitignore",
    "chars": 13,
    "preview": "node_modules/"
  },
  {
    "path": "socialapp/index.js",
    "chars": 1374,
    "preview": "const express = require(\"express\");\nconst format = require(\"date-format\");\nconst app = express();\n\n// swagger docs relat"
  },
  {
    "path": "socialapp/nodemon.json",
    "chars": 39,
    "preview": "{\n  \"ext\": \".js, .json, .yaml, .jsx\"\n}\n"
  },
  {
    "path": "socialapp/package.json",
    "chars": 457,
    "preview": "{\n  \"name\": \"socialapp\",\n  \"version\": \"1.0.0\",\n  \"description\": \"a basic social media app\",\n  \"main\": \"index.js\",\n  \"scr"
  },
  {
    "path": "socialapp/swagger.yaml",
    "chars": 1882,
    "preview": "openapi: 3.0.0\ninfo:\n  title: Social App\n  description: Our fist Social app at LCO - Hitesh\n  version: 1.0.1\n\nservers:\n "
  },
  {
    "path": "tshirtstore/.gitignore",
    "chars": 18,
    "preview": ".env\nnode_modules/"
  },
  {
    "path": "tshirtstore/README.md",
    "chars": 503,
    "preview": "# Tshirt store for pro backend developer course\n\nPlease add env variables for the project\n\n---\n\n### PORT=4000\n\n### DB_UR"
  },
  {
    "path": "tshirtstore/app.js",
    "chars": 1508,
    "preview": "const express = require(\"express\");\nrequire(\"dotenv\").config();\nconst app = express();\nconst morgan = require(\"morgan\");"
  },
  {
    "path": "tshirtstore/config/db.js",
    "chars": 386,
    "preview": "const mongoose = require(\"mongoose\");\n\nconst connectWithDb = () => {\n  mongoose\n    .connect(process.env.DB_URL, {\n     "
  },
  {
    "path": "tshirtstore/controllers/homeController.js",
    "chars": 468,
    "preview": "const BigPromise = require(\"../middlewares/bigPromise\");\n\nexports.home = BigPromise(async (req, res) => {\n  // const db "
  },
  {
    "path": "tshirtstore/controllers/orderController.js",
    "chars": 2290,
    "preview": "const Order = require(\"../models/order\");\nconst Product = require(\"../models/product\");\n\nconst BigPromise = require(\"../"
  },
  {
    "path": "tshirtstore/controllers/paymentController.js",
    "chars": 1385,
    "preview": "const BigPromise = require(\"../middlewares/bigPromise\");\nconst stripe = require(\"stripe\")(process.env.STRIPE_SECRET);\nco"
  },
  {
    "path": "tshirtstore/controllers/productController.js",
    "chars": 5937,
    "preview": "const Product = require(\"../models/product\");\nconst BigPromise = require(\"../middlewares/bigPromise\");\nconst CustomError"
  },
  {
    "path": "tshirtstore/controllers/userController.js",
    "chars": 8284,
    "preview": "const User = require(\"../models/user\");\nconst BigPromise = require(\"../middlewares/bigPromise\");\nconst CustomError = req"
  },
  {
    "path": "tshirtstore/index.js",
    "chars": 487,
    "preview": "const app = require(\"./app\");\nconst connectWithDb = require(\"./config/db\");\nrequire(\"dotenv\").config();\nconst cloudinary"
  },
  {
    "path": "tshirtstore/lcotshirtstore/.gitignore",
    "chars": 18,
    "preview": ".env\nnode_modules/"
  },
  {
    "path": "tshirtstore/lcotshirtstore/app.js",
    "chars": 1284,
    "preview": "const express = require(\"express\");\nrequire(\"dotenv\").config();\nconst app = express();\nconst morgan = require(\"morgan\");"
  },
  {
    "path": "tshirtstore/lcotshirtstore/config/db.js",
    "chars": 386,
    "preview": "const mongoose = require(\"mongoose\");\n\nconst connectWithDb = () => {\n  mongoose\n    .connect(process.env.DB_URL, {\n     "
  },
  {
    "path": "tshirtstore/lcotshirtstore/controllers/homeController.js",
    "chars": 468,
    "preview": "const BigPromise = require(\"../middlewares/bigPromise\");\n\nexports.home = BigPromise(async (req, res) => {\n  // const db "
  },
  {
    "path": "tshirtstore/lcotshirtstore/controllers/orderController.js",
    "chars": 2291,
    "preview": "const Order = require(\"../models/order\");\nconst Product = require(\"../models/product\");\n\nconst BigPromise = require(\"../"
  },
  {
    "path": "tshirtstore/lcotshirtstore/controllers/paymentController.js",
    "chars": 1312,
    "preview": "const BigPromise = require(\"../middlewares/bigPromise\");\nconst stripe = require(\"stripe\")(process.env.STRIPE_SECRET);\n\ne"
  },
  {
    "path": "tshirtstore/lcotshirtstore/controllers/productController.js",
    "chars": 5555,
    "preview": "const Product = require(\"../models/product\");\nconst BigPromise = require(\"../middlewares/bigPromise\");\nconst CustomError"
  },
  {
    "path": "tshirtstore/lcotshirtstore/controllers/userController.js",
    "chars": 8085,
    "preview": "const User = require(\"../models/user\");\nconst BigPromise = require(\"../middlewares/bigPromise\");\nconst CustomError = req"
  },
  {
    "path": "tshirtstore/lcotshirtstore/index.js",
    "chars": 487,
    "preview": "const app = require(\"./app\");\nconst connectWithDb = require(\"./config/db\");\nrequire(\"dotenv\").config();\nconst cloudinary"
  },
  {
    "path": "tshirtstore/lcotshirtstore/middlewares/bigPromise.js",
    "chars": 147,
    "preview": "// try catch and async - await || use promise\n\nmodule.exports = (func) => (req, res, next) =>\n  Promise.resolve(func(req"
  },
  {
    "path": "tshirtstore/lcotshirtstore/middlewares/user.js",
    "chars": 778,
    "preview": "const User = require(\"../models/user\");\nconst BigPromise = require(\"../middlewares/bigPromise\");\nconst CustomError = req"
  },
  {
    "path": "tshirtstore/lcotshirtstore/models/order.js",
    "chars": 1931,
    "preview": "const mongoose = require(\"mongoose\");\n\n// shippingInfo{}\n// user,\n// paymentInfo{}\n// taxAmount\n// ShippingAmount\n// tot"
  },
  {
    "path": "tshirtstore/lcotshirtstore/models/product.js",
    "chars": 1962,
    "preview": "const mongoose = require(\"mongoose\");\n\nconst productSchema = new mongoose.Schema({\n  name: {\n    type: String,\n    requi"
  },
  {
    "path": "tshirtstore/lcotshirtstore/models/user.js",
    "chars": 2147,
    "preview": "const mongoose = require(\"mongoose\");\nconst validator = require(\"validator\");\nconst bcrypt = require(\"bcryptjs\");\nconst "
  },
  {
    "path": "tshirtstore/lcotshirtstore/nodemon.json",
    "chars": 32,
    "preview": "{\n  \"ext\": \".js, .jsx, .yaml\"\n}\n"
  },
  {
    "path": "tshirtstore/lcotshirtstore/package.json",
    "chars": 822,
    "preview": "{\n  \"name\": \"tshirtstore\",\n  \"version\": \"1.0.0\",\n  \"description\": \"a backend api for tshirt store\",\n  \"main\": \"index.js\""
  },
  {
    "path": "tshirtstore/lcotshirtstore/routes/home.js",
    "chars": 235,
    "preview": "const express = require(\"express\");\nconst router = express.Router();\n\nconst { home, homeDummy } = require(\"../controller"
  },
  {
    "path": "tshirtstore/lcotshirtstore/routes/order.js",
    "chars": 774,
    "preview": "const express = require(\"express\");\nconst {\n  createOrder,\n  getOneOrder,\n  getLoggedInOrders,\n  admingetAllOrders,\n  ad"
  },
  {
    "path": "tshirtstore/lcotshirtstore/routes/payment.js",
    "chars": 563,
    "preview": "const express = require(\"express\");\nconst router = express.Router();\nconst {\n  sendRazorpayKey,\n  sendStripeKey,\n  captu"
  },
  {
    "path": "tshirtstore/lcotshirtstore/routes/product.js",
    "chars": 1064,
    "preview": "const express = require(\"express\");\nconst {\n  addProduct,\n  getAllProduct,\n  adminGetAllProduct,\n  getOneProduct,\n  admi"
  },
  {
    "path": "tshirtstore/lcotshirtstore/routes/user.js",
    "chars": 1330,
    "preview": "const express = require(\"express\");\nconst router = express.Router();\n\nconst {\n  signup,\n  login,\n  logout,\n  forgotPassw"
  },
  {
    "path": "tshirtstore/lcotshirtstore/swagger.yaml",
    "chars": 17006,
    "preview": "openapi: \"3.0.0\"\ninfo:\n  title: Tshirt store API\n  description: LCO - a course to create API for ecomm store\n  version: "
  },
  {
    "path": "tshirtstore/lcotshirtstore/utils/cookieToken.js",
    "chars": 381,
    "preview": "const cookieToken = (user, res) => {\n  const token = user.getJwtToken();\n\n  const options = {\n    expires: new Date(\n   "
  },
  {
    "path": "tshirtstore/lcotshirtstore/utils/customError.js",
    "chars": 144,
    "preview": "class CustomError extends Error {\n  constructor(message, code) {\n    super(message);\n    this.code = code;\n  }\n}\n\nmodule"
  },
  {
    "path": "tshirtstore/lcotshirtstore/utils/demotest.js",
    "chars": 396,
    "preview": "// User.find({ qty: { $lte: 20 } })\n// /api/v1/product?search=coder&page=2&category=shortsleeves&rating[gte]=4\n// &price"
  },
  {
    "path": "tshirtstore/lcotshirtstore/utils/emailHelper.js",
    "chars": 675,
    "preview": "const nodemailer = require(\"nodemailer\");\n\nconst mailHelper = async (option) => {\n  const transporter = nodemailer.creat"
  },
  {
    "path": "tshirtstore/lcotshirtstore/utils/testOrder.json",
    "chars": 564,
    "preview": "{\n  \"shippingInfo\": {\n    \"address\": \"1 Jaipur\",\n    \"city\": \"Jaipur\",\n    \"phoneNo\": \"9898989898\",\n    \"postalCode\": \"3"
  },
  {
    "path": "tshirtstore/lcotshirtstore/utils/whereClause.js",
    "chars": 1272,
    "preview": "// base - Product.find()\n// base - Product.find(email: {\"hitesh@lco.dev\"})\n\n//bigQ - //search=coder&page=2&category=shor"
  },
  {
    "path": "tshirtstore/lcotshirtstore/views/signuptest.ejs",
    "chars": 1725,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
  },
  {
    "path": "tshirtstore/middlewares/bigPromise.js",
    "chars": 147,
    "preview": "// try catch and async - await || use promise\n\nmodule.exports = (func) => (req, res, next) =>\n  Promise.resolve(func(req"
  },
  {
    "path": "tshirtstore/middlewares/productionError.js",
    "chars": 285,
    "preview": "const CustomError = require(\"../utils/customError\");\n\nmodule.exports = (err, req, res, next) => {\n  let error = { ...err"
  },
  {
    "path": "tshirtstore/middlewares/user.js",
    "chars": 1065,
    "preview": "const User = require(\"../models/user\");\nconst BigPromise = require(\"../middlewares/bigPromise\");\nconst CustomError = req"
  },
  {
    "path": "tshirtstore/models/order.js",
    "chars": 1934,
    "preview": "const mongoose = require(\"mongoose\");\n\n// shippingInfo{}\n// user,\n// paymentInfo{}\n// taxAmount\n// ShippingAmount\n// tot"
  },
  {
    "path": "tshirtstore/models/product.js",
    "chars": 1962,
    "preview": "const mongoose = require(\"mongoose\");\n\nconst productSchema = new mongoose.Schema({\n  name: {\n    type: String,\n    requi"
  },
  {
    "path": "tshirtstore/models/user.js",
    "chars": 2147,
    "preview": "const mongoose = require(\"mongoose\");\nconst validator = require(\"validator\");\nconst bcrypt = require(\"bcryptjs\");\nconst "
  },
  {
    "path": "tshirtstore/nodemon.json",
    "chars": 32,
    "preview": "{\n  \"ext\": \".js, .jsx, .yaml\"\n}\n"
  },
  {
    "path": "tshirtstore/package.json",
    "chars": 822,
    "preview": "{\n  \"name\": \"tshirtstore\",\n  \"version\": \"1.0.0\",\n  \"description\": \"a backend api for tshirt store\",\n  \"main\": \"index.js\""
  },
  {
    "path": "tshirtstore/routes/home.js",
    "chars": 235,
    "preview": "const express = require(\"express\");\nconst router = express.Router();\n\nconst { home, homeDummy } = require(\"../controller"
  },
  {
    "path": "tshirtstore/routes/order.js",
    "chars": 774,
    "preview": "const express = require(\"express\");\nconst {\n  createOrder,\n  getOneOrder,\n  getLoggedInOrders,\n  admingetAllOrders,\n  ad"
  },
  {
    "path": "tshirtstore/routes/payment.js",
    "chars": 563,
    "preview": "const express = require(\"express\");\nconst router = express.Router();\nconst {\n  sendRazorpayKey,\n  sendStripeKey,\n  captu"
  },
  {
    "path": "tshirtstore/routes/product.js",
    "chars": 1064,
    "preview": "const express = require(\"express\");\nconst {\n  addProduct,\n  getAllProduct,\n  adminGetAllProduct,\n  getOneProduct,\n  admi"
  },
  {
    "path": "tshirtstore/routes/user.js",
    "chars": 1327,
    "preview": "const express = require(\"express\");\nconst router = express.Router();\n\nconst {\n  signup,\n  login,\n  logout,\n  forgotPassw"
  },
  {
    "path": "tshirtstore/swagger.yaml",
    "chars": 55769,
    "preview": "openapi: \"3.0.0\"\ninfo:\n  title: Tshirt store API\n  description: LCO - a course to create API for ecomm store\n  version: "
  },
  {
    "path": "tshirtstore/utils/cookieToken.js",
    "chars": 381,
    "preview": "const cookieToken = (user, res) => {\n  const token = user.getJwtToken();\n\n  const options = {\n    expires: new Date(\n   "
  },
  {
    "path": "tshirtstore/utils/customError.js",
    "chars": 214,
    "preview": "class CustomError extends Error {\n  constructor(message, statusCode) {\n    super(message);\n    this.statusCode = statusC"
  },
  {
    "path": "tshirtstore/utils/demotest.js",
    "chars": 396,
    "preview": "// User.find({ qty: { $lte: 20 } })\n// /api/v1/product?search=coder&page=2&category=shortsleeves&rating[gte]=4\n// &price"
  },
  {
    "path": "tshirtstore/utils/emailHelper.js",
    "chars": 675,
    "preview": "const nodemailer = require(\"nodemailer\");\n\nconst mailHelper = async (option) => {\n  const transporter = nodemailer.creat"
  },
  {
    "path": "tshirtstore/utils/testOrder.json",
    "chars": 564,
    "preview": "{\n  \"shippingInfo\": {\n    \"address\": \"1 Jaipur\",\n    \"city\": \"Jaipur\",\n    \"phoneNo\": \"9898989898\",\n    \"postalCode\": \"3"
  },
  {
    "path": "tshirtstore/utils/whereClause.js",
    "chars": 1272,
    "preview": "// base - Product.find()\n// base - Product.find(email: {\"hitesh@lco.dev\"})\n\n//bigQ - //search=coder&page=2&category=shor"
  },
  {
    "path": "tshirtstore/views/home.ejs",
    "chars": 1477,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
  },
  {
    "path": "tshirtstore/views/signuptest.ejs",
    "chars": 1725,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=ed"
  }
]

About this extraction

This page contains the full source code of the hiteshchoudhary/pro-backend-developer GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 91 files (175.0 KB), approximately 41.0k tokens, and a symbol index with 21 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!