{"id":27404758,"url":"https://github.com/codezaura/JavaScript-Backend-Setup","last_synced_at":"2025-12-30T19:07:55.912Z","repository":{"id":246408519,"uuid":"821020987","full_name":"Ninja-Vikash/Backend_with_JavaScript","owner":"Ninja-Vikash","description":"Experience an amazing setup guide for your backend with JavaScript | This is a just a reference copy of the Ultimate Backend Series by Hitesh Sir 🔥 on the Chai aur Code ☕ YouTube Channel","archived":false,"fork":false,"pushed_at":"2024-07-24T16:23:36.000Z","size":133,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-07-24T18:58:50.966Z","etag":null,"topics":["bcrypt","cloudinary","cookie-parser","cors","datamodelling","environment-variables","expressjs","jwt","mongodb","mongoose","mongoose-aggregate-paginate-v2","multer","nodejs","nodemon","postman","schema"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ninja-Vikash.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-27T16:41:00.000Z","updated_at":"2024-07-24T16:23:39.000Z","dependencies_parsed_at":"2024-07-22T17:58:05.113Z","dependency_job_id":null,"html_url":"https://github.com/Ninja-Vikash/Backend_with_JavaScript","commit_stats":null,"previous_names":["ninja-vikash/backend","ninja-vikash/backend_setup_using_javascript","ninja-vikash/backend_with_javascript"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ninja-Vikash%2FBackend_with_JavaScript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ninja-Vikash%2FBackend_with_JavaScript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ninja-Vikash%2FBackend_with_JavaScript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ninja-Vikash%2FBackend_with_JavaScript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ninja-Vikash","download_url":"https://codeload.github.com/Ninja-Vikash/Backend_with_JavaScript/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248830418,"owners_count":21168272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bcrypt","cloudinary","cookie-parser","cors","datamodelling","environment-variables","expressjs","jwt","mongodb","mongoose","mongoose-aggregate-paginate-v2","multer","nodejs","nodemon","postman","schema"],"created_at":"2025-04-14T05:47:09.328Z","updated_at":"2025-12-30T19:07:55.864Z","avatar_url":"https://github.com/Ninja-Vikash.png","language":"JavaScript","readme":"## Complete JavaScript Backend Setup - Chai aur Code ☕\n\n### Reference : \u003ca href=\"https://www.youtube.com/@chaiaurcode\" target=\"_blank\"\u003e*Chai aur Code*\u003c/a\u003e  💖\u003cbr/\u003e\n\n**YouTube**\u003cbr/\u003e\n\u003ca href=\"https://youtu.be/7fjOw8ApZ1I?si=YvCPzVHbJr0-3KcZ\" target=\"_blank\"\u003eComplete Backend Developer course | Part 1\u003c/a\u003e \u003cbr/\u003e\n\u003ca href=\"https://youtu.be/8k-kK3tsJFY?si=BnhIulAJjI7XarBN\" target=\"_blank\"\u003eComplete Backend Developer course | Part 2\u003c/a\u003e\n\n**About**\u003cbr/\u003e\nComplete JavaScript Backend Setup is based on the *Complete JavaScript Backend Series* from the *Chai aur Code* YouTube Channel.\u003cbr/\u003e\nSpecial Thanks to **Hitesh Sir**, for providing us with such amazing content for free! 🙏✨\n\nI will suggest to watch the videos for better explanation 👆\n\n**Description**\u003cbr/\u003e\nI have tried to write a comprehensive guide to revise *Complete Backend Developer course*.\u003cbr/\u003e\nHere, I explained things as much as I can.\u003cbr/\u003e\n\n***\n\u003e [!NOTE]\\\n\u003e **What is actually a Server? 🤔**\u003cbr/\u003e\n\u003e Server is just a software to serve something.\u003cbr/\u003e\n\u003e Server can be our phone or laptop.\u003cbr/\u003e\n\u003e Server doesn't mean a big computer.\n\u003e \n\u003e **Two major component in backend 🧩**\u003c/br\u003e\n\u003e A Programming Language\n\u003e \u003cdiv align=\"left\"\u003e\n\u003e \u003cimg src=\"https://raw.githubusercontent.com/github/explore/master/topics/java/java.png\" alt=\"Java Logo\" height=\"40\"\u003e \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u003e \u003cimg src=\"https://raw.githubusercontent.com/github/explore/master/topics/javascript/javascript.png\" height=\"40px\"\u003e \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u003e \u003cimg src=\"https://raw.githubusercontent.com/github/explore/master/topics/php/php.png\" alt=\"PHP Logo\" height=\"40\"\u003e \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u003e \u003cimg src=\"https://raw.githubusercontent.com/github/explore/master/topics/cpp/cpp.png\" alt=\"C++ Logo\" height=\"40\"\u003e \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u003e \u003cimg src=\"https://raw.githubusercontent.com/github/explore/master/topics/go/go.png\" alt=\"Go Logo\" height=\"40\"\u003e \n\u003e \u003c/div\u003e\n\u003e \n\u003e \u003cbr/\u003e\n\u003e A Database\n\u003e \u003cdiv align=\"left\"\u003e\n\u003e \u003cimg src=\"https://www.vectorlogo.zone/logos/mongodb/mongodb-ar21.svg\" alt=\"MongoDB Logo\" height=\"40\"\u003e\n\u003e \u003cimg src=\"https://www.vectorlogo.zone/logos/mysql/mysql-ar21.svg\" alt=\"MySQL Logo\" height=\"40\"\u003e\n\u003e \u003cimg src=\"https://raw.githubusercontent.com/github/explore/master/topics/postgresql/postgresql.png\" alt=\"PostgreSQL Logo\" height=\"40\"\u003e \u0026nbsp;\u0026nbsp;\u0026nbsp;\u0026nbsp;\n\u003e \u003cimg src=\"https://raw.githubusercontent.com/github/explore/master/topics/sqlite/sqlite.png\" alt=\"SQLite Logo\" height=\"40\"\u003e\n\u003e \u003c/div\u003e\n\u003e \u003cbr/\u003e\n\u003e \n\u003e **Use of backend** ⚒️\\\n\u003e In backend we deals with either\\\n\u003e `DATA` --\u003e { `Array`, `String` \u0026 `Object` }\\\n\u003e `FILE` --\u003e { Image, Video \u0026 PDF }\\\n\u003e `Third Party API`\n\u003e\n\u003e\n\u003e **Requirements** ⚙️\\\n\u003e Code Editor 💻\\\n\u003e **Visual Studio Code** (VS Code) is a free, open-source Integrated Development Environment (**IDE**) developed by **Microsoft**, offering features like **debugging**, **version control**, and extensions to support various programming languages.\n\u003e\n\u003e Download \u003ca href=\"https://code.visualstudio.com/\" target=\"_blank\"\u003e**VS Code**\u003c/a\u003e !\n\u003e \n\u003e A JavaScript run time\\\n\u003e `Node.js`, `Deno` or `Bun`\\\n\u003e Install **`Node.js` in your machine.** Because without node js `npm` commands won't work.\n\u003e \n\u003e Download \u003ca href=\"\" target=\"_blank\"\u003e**Node.js**\u003c/a\u003e !\n\u003e\n\u003e Confirm `node.js` installed or not in your machine\n\u003e ```bash\n\u003e node --version    # v20.15.0 or higher\n\u003e \n\u003e npm --version     # 10.7.0 or higher\n\u003e ```\n\n## Getting Started 🚀\nCreate a directory where you are going to set up your project.\u003cbr/\u003e\nFor example `backend`\n\nDrag it or open it using \u003ca href=\"https://code.visualstudio.com/\" target=\"_blank\"\u003e**Visual Studio Code (VS Code)**\u003c/a\u003e\u003cbr/\u003e\n\n\n### Set up your backend environment with industry-level quality 🔥\n**Initialize with npm**\n```bash\nnpm init\n```\n\u003e It will ask some questions related to your project. Please answer them accordingly.\n\n**Create files in root directory**\n```bash\ntouch .env .gitignore .prettierrc .prettierignore\n```\n**Create further directories and files**\u003cbr/\u003e\nRun the following commands one by one\n```bash\nmkdir public src\n\ncd src\n\n# Run the commands for creating files and directories in src\ntouch index.js app.js constants.js\n\nmkdir controllers db models middlewares routes utils\n\n# Back to previous directory\ncd ..\n\ncd public\n\n# Run the commands for creating files and directories in public\nmkdir temp \u0026\u0026 touch temp/.gitkeep\n```\n\n\u003e [!WARNING]\n\u003e ```bash\n\u003e mkdir folder1 folder2 folder3\n\u003e\n\u003e mkdir temp \u0026\u0026 touch temp/.gitkeep\n\u003e ```\n\u003e Won't work in Windows. 😥\n\u003e\n\u003e **Don't worry!**\\\n\u003e You can use `git-bash` for executing the command on windows.\\\n\u003e Or, You can create them manually. 😁\n\n**Install dev dependencies**\n```bash\nnpm i -D nodemon\n\nnpm i -D prettier\n```\n\u003e [!NOTE]\\\n\u003e `Nodemon` used for hot reloading for every single change in files.\\\n\u003e `Prettier` used to configure the formatting rules.\\\n\u003e `-D` is a flag to save them as a dev dependency\n\nReference:  \u003ca href=\"https://www.npmjs.com/package/prettier\" target=\"_blank\"\u003e**prettier**\u003c/a\u003e | \u003ca href=\"https://www.npmjs.com/package/nodemon\" target=\"_blank\"\u003e**nodemon**\u003c/a\u003e\n\n\n**Install dependencies**\n```bash\nnpm i express dotenv mongoose\n```\n\nReference: \u003ca href=\"https://expressjs.com/\" target=\"_blank\"\u003e**express**\u003c/a\u003e | \u003ca href=\"https://www.npmjs.com/package/dotenv\" target=\"_blank\"\u003e**dotenv**\u003c/a\u003e | \u003ca href=\"https://www.npmjs.com/package/mongoose\" target=\"_blank\"\u003e**mongoose**\u003c/a\u003e\n\n***\n### Code Updates 🤔\n`package.json`\n```json\n\"type\": \"module\",\n```\n```json\n\"scripts\": {\n    \"dev\": \"nodemon src/index.js\"\n},\n```\n\n`.gitignore` -\u003e \u003ca href=\"https://mrkandreev.name/snippets/gitignore-generator/#Node\" target=\"_blank\"\u003egitignore builder\u003c/a\u003e\n\n\n`.prettierrc`\n```json\n{\n    \"singleQuote\": false,\n    \"bracketSpacing\": true,\n    \"tabWidth\": 2,\n    \"trailingComma\": \"es5\",\n    \"semi\": true\n}\n```\n\n`.prettierignore`\n```\n/.vscode\n/node_modules\n./dist\n\n*.env\n.env\n.env.*\n```\n\n`.env`\n```js\nPORT=8000\nMONGODB_URI=mongodb+srv://\u003cusername\u003e:\u003cpassword\u003e@cluster0.cp5kxxy.mongodb.net/?retryWrites=true\u0026w=majority\u0026appName=Cluster0\nCORS_ORIGIN=*\n```\n\u003e [!IMPORTANT]\\\n\u003e Don't include any special character in your password\\\n\u003e eg. `@`, `\u0026` etc\n\n#### Config of environment variable\nEnvironment variable must load first in your application\u003cbr/\u003e\n`src/index.js`\n```js\nimport dotenv from \"dotenv\"\n\ndotenv.config({\n    path: \"./env\"\n})\n```\n\u003e [!WARNING]\\\n\u003e This is not a valid method to use `import` syntax with `dotenv`.\n\u003e \n\u003e Let's config the `package.json` to use it as a experimental method.\n\u003e ```json\n\u003e \"scripts\": {\n\u003e   \"dev\": \"nodemon -r dotenv/config --experimental-json-modules src/index.js\"\n\u003e },\n\n***\n\n### Code snippets\n\u003e [!IMPORTANT]\\\n\u003e **Resolve errors**\\\n\u003e By Providing the complete path in `import` method, which means with extensions to prevent errors.\n\u003e ```js\n\u003e import connectDB from \"./db/index.js\";\n\u003e //...\n\u003e \n\u003e import { DB_NAME } from \"../constants.js\";\n\u003e //...\n\u003e ```\n\n#### Code for database connection\n`src/db/index.js`\n```js\nimport mongoose from \"mongoose\";\n\nconst connectDB = () =\u003e {}\n\nexport default connectDB;\n```\n\u003e [!NOTE]\\\n\u003e We will connect to database using `mongoose`.\\\n\u003e Create a method for database connection and store it in a variable so that we can export it as\n\u003e ```js\n\u003e const connectDB = () =\u003e {}\n\u003e ```\n\n```js\nimport mongoose from \"mongoose\";\n\nconst connectDB = () =\u003e {\n    try {\n\n    } catch (error) {\n\n    }\n}\n\nexport default connectDB;\n```\n\u003e [!NOTE]\\\n\u003e During database connection some errors can appear.\\\n\u003e So it is better to wrap the connection code in the `try` and `catch` wrapper.\n\n```js\nimport mongoose from \"mongoose\";\n\nconst connectDB = () =\u003e {\n    try {\n\n    } catch (error) {\n        console.error(\"MONGODB connect FAILED \", error)\n        process.exit(0)\n    }\n}\n\nexport default connectDB;\n```\n\u003e [!NOTE]\\\n\u003e In catch part we will console the error with connection failed message.\n\n```js\nimport mongoose from \"mongoose\";\nimport { DB_NAME } from \"../constants.js\";\n\nconst connectDB = async () =\u003e {\n    try {\n        await mongoose.connect(`${process.env.MONGODB_URI}/${DB_NAME}`)\n    } catch (error) {\n        console.error(\"MONGODB connect FAILED \", error)\n        process.exit(0)\n    }\n}\n\nexport default connectDB;\n```\n\u003e [!IMPORTANT]\\\n\u003e Remember: \"*Our database is on another continent.*\"\\\n\u003e It will take time to process, must use `async` and `await`.\n\u003e\n\u003e `src/constants.js`\n\u003e ```js\n\u003e export const DB_NAME = \"video\"\n\u003e ```\n\n```js\nimport mongoose from \"mongoose\";\nimport { DB_NAME } from \"../constants.js\";\n\nconst connectDB = async () =\u003e {\n    try {\n        const connectionInstance = await mongoose.connect(`${process.env.MONGODB_URI}/${DB_NAME}`)\n        console.log(`\\n MongoDB connected !! DB HOST: ${connectionInstance.connection.host}`)\n    } catch (error) {\n        console.error(\"MONGODB connect FAILED \", error)\n        process.exit(0)\n    }\n}\n\nexport default connectDB;\n```\n\u003e [!NOTE]\\\n\u003e We can store the connection instance in a variable so that we can see some information and console a message for connection success.\n\n#### Database connection call\n`src/index.js`\n```js\nimport dotenv from \"dotenv\"\nimport connectDB from \"./db/index.js\";\n\ndotenv.config({\n    path: \"./env\"\n})\n\nconnectDB()\n```\nStart the server\n```bash\nnpm run dev\n```\n\n#### Create an express server\n`src/app.js`\n```js\nimport express from \"express\"\n\nconst app = express()\n\nexport { app }\n```\n\u003e [!NOTE]\\\n\u003e We will use named export as `export { app }` to export the app.\n\n`src/index.js`\n```js\nimport dotenv from \"dotenv\"\nimport connectDB from \"./db/index.js\";\nimport { app } from \"./app.js\";\n\ndotenv.config({\n    path: \"./env\"\n})\n\nconnectDB()\n.then()\n.catch()\n```\n\u003e [!NOTE]\\\n\u003e Since, we have created an `async` function. So that we can use `.then()` and `.catch()` methods.\n\n```js\nimport dotenv from \"dotenv\"\nimport connectDB from \"./db/index.js\";\nimport { app } from \"./app.js\";\n\ndotenv.config({\n    path: \"./env\"\n})\n\nconnectDB()\n.then(()=\u003e{\n    \n})\n.catch((err)=\u003e{\n    console.log(\"MONGODB Connection failed !!! \", err )\n})\n```\n\u003e Both the method accepts callback\n\n```js\nimport dotenv from \"dotenv\"\nimport connectDB from \"./db/index.js\";\nimport { app } from \"./app.js\";\n\ndotenv.config({\n    path: \"./env\"\n})\n\nconnectDB()\n.then(()=\u003e{\n    app.listen(process.env.PORT || 8000, ()=\u003e{\n        console.log(`\\n Server is running at port ${process.env.PORT}`)\n    })\n})\n.catch((err)=\u003e{\n    console.log(\"MONGODB Connection failed !!! \", err )\n})\n```\n\n### Use of `middlewares`\n`middlewares` are used modifying **request** and **response** objects, ending the request-response cycle and calling the next middleware function in the stack.\u003cbr/\u003e\n\nRemember this quotation: \u003cpre\u003emiddleware be like \"**kahin jane se phele mujhse mil kar jana**\" 😁\u003c/pre\u003e\n\nUsually created with `use` keyword.\n```js\napp.use((err, req, res, next) =\u003e {\n    // Some code to be executed  \n});\n```\n\u003e [!IMPORTANT]\\\n\u003e `middlewares` have 4 parameters\n\u003e \n\u003e `err` The error object that was thrown or passed to the next function with an error argument.\\\n\u003e `req` The request object.\\\n\u003e `res` The response object.\\\n\u003e `next` The next middleware function in the stack.\n\n**Install dependencies**\n```bash\nnpm i cookie-parser cors\n```\n\nReference: \u003ca href=\"https://www.npmjs.com/package/cookie-parser\" target=\"_blank\"\u003e**cookie-parser**\u003c/a\u003e | \u003ca href=\"https://www.npmjs.com/package/cors\" target=\"_blank\"\u003e**cors**\u003c/a\u003e\n\n`src/app.js`\n```js\nimport express from \"express\"\nimport cors from \"cors\"\nimport cookieParser from \"cookie-parser\"\n\nconst app = express()\n\napp.use(cors({\n    origin: process.env.CORS_ORIGIN,\n    credentials: true\n}))\n\napp.use(express.json({ limit: \"16kb\" }))\napp.use(express.urlencoded({ extended: true, limit: \"16kb\" }))\napp.use(express.static(\"public\"))\napp.use(cookieParser())\n\n\nexport { app }\n```\n***\n\n#### `asyncHandler( )`\nA utility is used for handling all requests and responses on every route\u003cbr/\u003e\n`src/utils/asyncHandler.js`\n```js\nconst asyncHandler = (requestHandler)=\u003e {\n    return (req, res, next) =\u003e {\n        Promise.resolve(requestHandler(req, res, next)).catch((err) =\u003e next(err))\n    }\n}\n\nexport { asyncHandler }\n```\n\u003e [!IMPORTANT]\\\n\u003e It is a higher order function which further `return`s a function\\\n\u003e We can reuse the utility. 🤩\n\n`src/utils/ApiError.js`\n```js\nclass ApiError extends Error {\n    constructor(\n        statusCode,\n        message = \"Something went wrong\",\n        errors = [],\n        stack = \"\"\n    ) {\n        super(message)\n        this.statusCode = statusCode\n        this.data = null\n        this.message = message\n        this.success = false\n        this.errors = errors\n\n        if (stack) {\n            this.stack = stack\n        } else {\n            Error.captureStackTrace(this, this.constructor)\n        }\n    }\n}\n\nexport { ApiError }\n```\n\u003e [!NOTE]\\\n\u003e Custom API Error response is very useful for simplifying the custom error messages.\n\u003e \n\u003e Here we are extending the Error `class` available in `node.js`\n\n`src/utils/ApiResponse.js`\n```js\nclass ApiResponse {\n    constructor(statusCode, data, message=\"success\"){\n        this.statusCode = statusCode,\n        this.data = data,\n        this.message = message,\n        this.success = statusCode \u003c 400\n    }\n}\n\nexport { ApiResponse }\n```\nHTTP statusCode Responses\u003cbr/\u003e\nReference: \u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Status\" target=\"_blank\"\u003e**MDN**\u003c/a\u003e\n\n***\n\n#### Data Modeling\n`src/model/user.model.js`\n```js\nimport mongoose, { Schema } from \"mongoose\";\n\nconst userSchema = new Schema({});\n\nexport const User = mongoose.model(\"User\", userSchema);\n```\n\n\u003e [!NOTE]\\\n\u003e `user.model.js` helps to identify the file by its filename.\\\n\u003e eg. the file is a model file. 🤓\n\u003e\n\u003e \n\u003e In models we store data in the form of Schemas\\\n\u003e For creating a **Schema** we use `new` keyword, Since Schema is a method which accepts an Object\n\u003e ```js\n\u003e import mongoose from \"mongoose\";\n\u003e \n\u003e new mongoose.Schema({});\n\u003e ```\n\u003e Or we can import `Schema` object for creating Schema\n\u003e ```js\n\u003e import mongoose, { Schema } from \"mongoose\";\n\u003e \n\u003e new Schema({});\n\u003e ```\n\u003e Store it in a variable and export it\n\u003e ```js\n\u003e import mongoose, { Schema } from \"mongoose\";\n\u003e \n\u003e const userSchema = new Schema({});\n\u003e \n\u003e export User = mongoose.model(\"User\", userSchema);\n\u003e ```\n\u003e `mongoose.model(\"User\", userSchema)` has two arguments: the **collection name** and the **schema type**.\\\n\u003e In MongoDB, the collection name becomes lowercase and plural. For example, **User** becomes **users**.\n\n#### How to create data fields?\nWe can simply create a data field as given.\n```js\nconst userSchema = new Schema({\n        username: String\n})\n```\n\nBut we will follow a best practice.\n```js\nconst userSchema = new Schema({\n        username: {\n            type: String,\n            required: true,\n            unique: true,\n            lowercase: true\n        }\n})\n```\n\nLet's explore how to establish a connection or relationship between two data models. 🤔\n```js\n// User Data Model\nconst userSchema = new Schema({\n        username: {\n            type: String,\n            required: true,\n            unique: true,\n            lowercase: true,\n        },\n        email: {\n            type: String,\n            required: true,\n            unique: true,\n        }\n})\n\nexport const User = mongoose.model(\"User\", userSchema)\n```\n```js\n// CartList Data Model\nconst productSchema = Schema({\n    name: {\n        type: String,\n        required: true\n    },\n    price: {\n        type: String,\n        required: true,\n        default: 0\n    }\n})\n\nconst cartModel = Schema({\n        username: {\n            type: mongoose.Schema.Types.ObjectId,\n            ref: \"User\"\n        },\n        products: [ productSchema ],\n        status: {\n            type: String,\n            enum: [\"PENDING\", \"CANCELLED\", \"DELIVERED\"].\n            default: \"PENDING\"\n        }\n}, { timestamps: true })\n\nexport const Cart = mongoose.model(\"Cart\", cartModel)\n```\n\u003e [!IMPORTANT]\\\n\u003e When we connect two data models, we often use fields like `type` and `ref` to establish relationships between them\n\u003e ```js\n\u003e username: {\n\u003e     type: mongoose.Schema.Types.ObjectId,\n\u003e     ref: \"User\"\n\u003e },\n\u003e ```\n\u003e We want the **username** from the `User` model.\\\n\u003e We need to use the `type` key to connect and the `ref` key\\\n\u003e The `ref` key holds the value of the **collection name** of the parent data model.\\\n\u003e Since the collection name of the parent is `User`, that is why we are referring to it in the child data model.\n\u003e\n\u003e ```js\n\u003e products: [ productSchema ],\n\u003e ```\n\u003e In products, we will use an `array` type because a user may purchase one or more products.\n\u003e ```js\n\u003e status: {\n\u003e     type: String,\n\u003e     enum: [\"PENDING\", \"CANCELLED\", \"DELIVERED\"].\n\u003e     default: \"PENDING\"\n\u003e }\n\u003e ```\n\u003e The `status` field has an `enum` key, which provides **constant** values to be chosen by users.\n\u003e ```js\n\u003e const cartModel = Schema({ }, { timestamps: true })\n\u003e ```\n\u003e In Mongoose, the schema constructor accepts a second object to enable `timestamps`\\\n\u003e Which automatically adds `createdAt` and `updatedAt` fields to your schema to track document creation and modification times.\n\n***\n\n#### Mongoose Aggregation Pipelines\n```bash\nnpm i mongoose-aggregate-paginate-v2\n```\n\nReference: \u003ca href=\"https://www.npmjs.com/package/mongoose-aggregate-paginate-v2\" target=\"_blank\"\u003e**mongoose-aggregate-paginate-v2**\u003c/a\u003e | \u003ca href=\"https://www.mongodb.com/docs/manual/core/aggregation-pipeline/\" target=\"_blank\"\u003e**mongoDB aggregation pipeline**\u003c/a\u003e\n\n`src/models/video.model.js`\n```js\nimport mongoose, { Schema } from \"mongoose\";\nimport mongooseAggregatePaginate from \"mongoose-aggregate-paginate-v2\";\n\n// videoSchema code\n// ...\n// ...\n\nvideoSchema.plugin(mongooseAggregatePaginate)\n\nexport const Video = mongoose.model(\"Video\", videoSchema)\n```\n\u003e [!NOTE]\\\n\u003e `videoSchema.plugin(mongooseAggregatePaginate)` helps to write aggregation pipelines\n\n#### Packages for encrypting data\n```bash\nnpm i bcrypt jsonwebtoken\n```\nReference: \u003ca href=\"https://www.npmjs.com/package/bcrypt\" target=\"_blank\"\u003e**bcrypt**\u003c/a\u003e | \u003ca href=\"https://www.npmjs.com/package/jsonwebtoken\" target=\"_blank\"\u003e**jwt**\u003c/a\u003e\n\n`src/models/user.model.js`\n```js\nimport bcrypt from \"bcrypt\";\n\n// userSchema code\n// ...\n// ...\n\nuserSchema.pre(\"save\", async function(next){\n    if(!this.isModified(\"password\")) return next();\n\n    this.password = await bcrypt.hash(this.password, 10)\n    next()\n})\n\nuserSchema.methods.isPasswordCorrect = async function(password){\n    return await bcrypt.compare(password, this.password)\n}\n\nexport const User = mongoose.model(\"User\", userSchema)\n```\n\u003e [!IMPORTANT]\\\n\u003e Password hashing is a technique to encrypt the given password to a random string.\\\n\u003e For hashing we use `bcrypt`.\n\u003e \n\u003e Mongoose provides many hooks like `pre` and `post`.\\\n\u003e By using `pre` and `post` hooks, you can effectively manage and streamline your data processing workflows in a Mongoose application.\n\u003e \n\u003e `userSchema.pre(\"event\", callbackfn())`\\\n\u003e pre is a `hook` or `method` which accepts two values as: **Event** and a **CallBack_fn()**\n\u003e\n\u003e Since, bcrypting is a time consuming task. For safety we will use a `async` function in callback.\\\n\u003e The callback function acts here as a middleware, So it must have `next()` flag to propagate to next node.\n\u003e\n\u003e Similarly, we can create custom methods using the Schema\n\u003e ```js\n\u003e userSchema.methods.isPasswordCorrect = async function(){\n\u003e    // Custom method code...      \n\u003e }\n\u003e ```\n\n\u003e [!WARNING]\\\n\u003e We can't use an arrow function here, because **arrow function doesn't have access of `this` keyword**.\n\n#### JWT ( JsonWebTokens )\n`generateAccessToken`\n```js\nuserSchema.methods.generateAccessToken = function(){\n    return jwt.sign(\n        {\n            _id: this._id,\n            email: this.email,\n            username: this.username,\n            fullname: this.fullname\n        },\n        process.env.ACCESS_TOKEN_SECRET,\n        {\n            expiresIn: process.env.ACCESS_TOKEN_EXPIRY\n        }\n    )\n}\n```\n\n`generateRefreshToken`\n```js\nuserSchema.methods.generateRefreshToken = function(){\n    return jwt.sign(\n        {\n            _id: this._id,\n        },\n        process.env.REFRESH_TOKEN_SECRET,\n        {\n            expiresIn: process.env.REFRESH_TOKEN_EXPIRY\n        }\n    )\n}\n```\n\n\u003e [!NOTE]\\\n\u003e `jwt.sign({ PAYLOAD }, SECRET, { EXPIRY })`\\\n\u003e A refresh token has a smaller payload compared to an access token.\n\u003e \n\u003e Create environment variables for `ACCESS_TOKEN_SECRET`, `ACCESS_TOKEN_EXPIRY`, `REFRESH_TOKEN_SECRET` \u0026 `REFRESH_TOKEN_EXPIRY`\n\n#### File Handling 📄\nWe don't handle files on our local server; instead, we use third-party services like **AWS** and **Cloudinary**.\n\n**Install dependencies**\n```bash\nnpm i cloudinary multer\n```\n\nReference: \u003ca href=\"https://cloudinary.com/\" target=\"_blank\"\u003e**Cloudinary**\u003c/a\u003e | \u003ca href=\"https://www.npmjs.com/package/multer\" target=\"_blank\"\u003e**Multer**\u003c/a\u003e\n\nTo upload files to Cloudinary, we will use **Multer** as a **middleware**.\n\n`src/utils/cloudinary.js`\n```js\nimport { v2 as cloudinary } from \"cloudinary\"\n\ncloudinary.config({ \n    cloud_name: process.env.CLOUDINARY_CLOUD_NAME, \n    api_key: process.env.CLOUDINARY_API_KEY, \n    api_secret: process.env.CLOUDINARY_API_SECRET\n});\n\nconst uploadOnCloudinary = ()=\u003e {\n    try {\n\n    } catch () {\n\n    }\n}\n\nexport { uploadOnCloudinary }\n```\n\u003e [!NOTE]\\\n\u003e SignUp and create an account on Cloudinary.\\\n\u003e Look for cloudinary configuration, It is more safer to store sensitive data on environment file.\\\n\u003e Uploading files to Cloudinary can cause errors, so it is better to use a try and catch wrapper around the process.\n\n```js\nimport { v2 as cloudinary } from \"cloudinary\"\n\ncloudinary.config({ \n    cloud_name: process.env.CLOUDINARY_CLOUD_NAME, \n    api_key: process.env.CLOUDINARY_API_KEY, \n    api_secret: process.env.CLOUDINARY_API_SECRET\n});\n\nconst uploadOnCloudinary = ()=\u003e {\n    try {\n\n    } catch (error) {\n        fs.unlinkSync(localFilePath) // removes the locally saved temporary file as the uplaod operation got failed\n        return null;\n    }\n}\n\nexport { uploadOnCloudinary }\n```\n\u003e We aim to maintain cleanliness in our application, promptly removing files from temporary storage if an operation fails.\n```js\nimport { v2 as cloudinary } from \"cloudinary\"\nimport fs from \"fs\"\n\ncloudinary.config({ \n    cloud_name: process.env.CLOUDINARY_CLOUD_NAME, \n    api_key: process.env.CLOUDINARY_API_KEY, \n    api_secret: process.env.CLOUDINARY_API_SECRET\n});\n\nconst uploadOnCloudinary = async (localFilePath)=\u003e {\n    try {\n        if (!localFilePath) return null\n\n        // Upload the file on cloudinary\n        const response = await cloudinary.uploader.upload(localFilePath, {\n            resource_type: \"auto\"\n        })\n\n        fs.unlinkSync(localFilePath) // removes the locally saved temporary file as the upload operation got success\n\n        return response;\n\n    } catch (error) {\n        fs.unlinkSync(localFilePath) // removes the locally saved temporary file as the upload operation got failed\n        return null;\n    }\n}\n\nexport { uploadOnCloudinary }\n```\n\u003e [!NOTE]\\\n\u003e There is a high chance that the user may not send any files to upload. In such cases, it's best to return a `null` value.\n\u003e \n\u003e Uploading files is a time-consuming task, so it's better to `await` the process and make the method asynchronous.\n\u003e ```js\n\u003e await cloudinary.uploader.upload(localFilePath, {\n\u003e     resource_type: \"auto\"\n\u003e })\n\u003e ```\n\u003e The `upload()` method accepts two arguments as local path of the file and second argument as an object to define resource_type and many other properties related to the file.\\\n\u003e We need to `return` some response to the user so that we will store it in a variable.\n\u003e \n\u003e This code snippet is **Reusable**. 🤩\n\n`src/middlewares/multer.middleware.js`\n\n```js\nimport multer from \"multer\";\n\nconst storage = multer.diskStorage({\n    destination: function (req, file, cb) {\n      cb(null, \"./public/temp\")\n    },\n    filename: function (req, file, cb) {\n      cb(null, file.originalname)\n    }\n})\n\nexport const upload = multer({ storage })    // ES6 Module `multer({ storage: storage })`\n```\n\u003e [!IMPORTANT]\\\n\u003e Multer allows us to choose the type of storage.\n\u003e\n\u003e **Memory Storage**\\\n\u003e Files are stored in memory as Buffer objects.\\\n\u003e This is suitable for handling small files or cases where you want to process the file in-memory without saving it permanently to disk.\n\u003e\n\u003e **Disk Storage**\\\n\u003e Files are stored on the disk of the server.\\\n\u003e You can configure the destination directory and the filename. This is ideal for handling larger files or when you need to persist uploaded files.\n\u003e\n\u003e For now we will use `diskStorage`.\n\n### `Controllers` and `Routes`\n\nWe will see on scroll down. How can we write controller's code effectively.\n\n`src/controllers/user.controller.js`\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\n\nconst registerUser = asyncHandler( async (req, res) =\u003e {\n    await res.status(200).json({\n        message: \"OK! Response received\"\n    })\n} )\n\nexport { registerUser }\n```\n`src/routes/user.routes.js`\n```js\nimport { Router } from \"express\"\nimport { registerUser } from \"../controllers/user.controller.js\"\n\nconst router = Router()\n\nrouter.route(\"/register\").post(registerUser)\n\nexport default router\n```\n\u003e [!NOTE]\\\n\u003e We will use `{ Router }` from \"express\"\n\n**Update `app.js` file**\n```js\n// All imports\n// ...\n\n// All middlewares\n// ... \n\n// routes\n\nimport userRouter from \"./routes/user.routes.js\"\n\n// routes declaration\n\napp.use(\"/api/v1/users\", userRouter)\n\n\nexport { app }\n```\n\u003e [!IMPORTANT]\\\n\u003e We will write all routes below the already created middlewares\\\n\u003e Because we are going to use the route as a middleware.\n\u003e\n\u003e POSTMAN Desktop App\u003cbr/\u003e\n\u003e \u003ca href=\"https://www.postman.com/downloads/\" target=\"_blank\"\u003e**Download**\u003c/a\u003e\n\u003e\n\u003e Now, We can test the response using **Postman**\\\n\u003e `http://localhost:8000/api/v1/users/register`\n\u003e \n\u003e It will give a response as\n\u003e ```json\n\u003e {\n\u003e    \"message\": \"OK! Response received\"\n\u003e }\n\u003e ```\n\u003e On a `POST` request at the given URL.\n\n#### How to write effective code for controllers ? 😎\nIf you want to create a controller which will handle all the user related functions like **login** or **signup**.\n\nThink and write the **ALGORITHMS** for the controller, What you need in your controller and what you are going to do there.\u003cbr/\u003e\nFor example:\n```js\n// ALGORITHM for Register a User\n\n// get user details from frontend\n// validation - not empty\n// check if user already exists: username, email\n// check for images, check for avatar\n// upload them to cloudinary, avatar\n// create user object - create entry in db\n// remove password and refresh token field from response\n// check for user creation\n// return res\n```\n\n\u003e [!IMPORTANT]\\\n\u003e **Algorithms are nothing just steps**. 😁\n\u003e\n\u003e Algorithms help to write code in a structured order.\\\n\u003e If we outline all the steps before writing the code,\n\u003e it saves us a lot of time because we already know what the next step should be.\\\n\u003e This eliminates the need to worry about what comes next.\n\n#### How to use `middlewares` in `Router` ?\n`src/routes/user.routes.js`\n```js\nimport { Router } from \"express\"\nimport { registerUser } from \"../controllers/user.controller.js\"\nimport { upload } from \"../middlewares/multer.middleware.js\"\n\nrouter.route(\"/register\").post(\n    upload.fields([\n        {\n            name: \"avatar\",\n            maxCount: 1\n        },\n        {\n            name: \"coverImage\",\n            maxCount: 1\n        }\n    ]),\n    registerUser\n)\n```\n\n\u003e [!IMPORTANT]\\\n\u003e We'll inject a middleware before reaching the route,\\\n\u003e `router.route(\"/register\").post(upload.fields([])), registerUser)`\n\u003e \n\u003e In this case we are using multer as a middleware for file uploading on cloudinary\\\n\u003e We have multiple options for uploading a file like `upload.single`  `upload.any`  `upload.array`\\\n\u003e We are using here `upload.fields`\n\u003e\n\u003e The `upload.fields` method allows you to define multiple file fields in a single request.\\\n\u003e This is useful when you need to upload more than one file field, each with its own set of rules.\\\n\u003e Each field can have its own name and maximum count of files that can be uploaded.\\\n\u003e This provides fine-grained control over the file upload process.\n\n***\n\n### Registration method\nWe have the Algorithm to write **register user** method.\u003cbr/\u003e\nWe will start rewriting `user.controller.js` file\n\n**1. Get data from frontend**\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\n\nconst registerUser = asyncHandler( async (req, res) =\u003e {\n\n    const { fullName, email, username, password } = req.body;\n\n})\n\nexport { registerUser }\n```\n\u003e [!NOTE]\\\n\u003e Obviously! We don't have any frontend\\\n\u003e That is why we are using POSTMAN for sending data\n\u003e\n\u003e To access data in backend\n\u003e Use `req.body`\\\n\u003e Also, We can extract the data as\n\u003e ```js\n\u003e const { fullName, email, username, password } = req.body;\n\u003e ```\n\u003e For safety purpose must console the data for the clarity what we are getting.\n\n**2. Validation for not empty fields**\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\n\nconst registerUser = asyncHandler( async (req, res) =\u003e {\n\n    const { fullName, email, username, password } = req.body;\n\n    if (\n        [fullName, email, username, password].some((field)=\u003e field?.trim() === \"\")\n    ) {\n        throw new ApiError(400, \"All fields are required\")\n    }\n\n})\n\nexport { registerUser }\n```\n\u003e [!NOTE]\\\n\u003e In the second step, we are checking for empty fields\\\n\u003e If any throw an Error\n\u003e\n\u003e ```js\n\u003e if (\n\u003e     [fullName, email, username, password].some((field)=\u003e field?.trim() === \"\")\n\u003e )\n\u003e ```\n\u003e The `some` method is used to check if any field in the array is empty.\\\n\u003e It will return `true`.\\\n\u003e Sometimes we don't sure, we have the value or not in that situation it is better to use optional chaining.\\\n\u003e `field?.trim() === \"\"`\\\n\u003e `?.` is the optional chaining operator in JavaScript.\\\n\u003e It allows you to safely access properties or call methods on an object that might be `null` or `undefined`.\\\n\u003e If field is `null` or `undefined`, the expression `field?.trim()` will return `undefined` instead of throwing an error.\\\n\u003e `trim()` removes whitespaces\n\u003e\n\u003e Since, We have a custom **ApiError** utility for handling errors\\\n\u003e Therefore, Just simply `import` it and pass two arguments as the **StatusCode** and **CustomMessage**\n\u003e ```js\n\u003e throw new ApiError(400, \"All fields are required\")\n\u003e ```\n\u003e `ApiError` is a class. `new` keyword is used to create new class object.\n\n**3. Check user exist on not**\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\n\nconst registerUser = asyncHandler( async (req, res) =\u003e {\n\n    const { fullName, email, username, password } = req.body;\n\n    if (\n        [fullName, email, username, password].some((field)=\u003e field?.trim() === \"\")\n    ) {\n        throw new ApiError(400, \"All fields are required\")\n    }\n\n    const existedUser = await User.findOne({\n        $or: [{ username }, { email }]\n    })\n\n    if (existedUser) {\n        throw new ApiError(409, \"User with email or username already exist\")\n    }\n\n})\n\nexport { registerUser }\n```\n\u003e [!NOTE]\\\n\u003e For checking the user already exist or not in the database. We need a database call.\\\n\u003e We have `user.model.js` file which is talking with database.\\\n\u003e So `import` it.\n\u003e\n\u003e Remember our database is on another continent.\\\n\u003e It will take time to connect, must use `await`\n\u003e ```js\n\u003e const existedUser = await User.findOne({\n\u003e     $or: [{ username }, { email }]\n\u003e })\n\u003e ```\n\u003e `User.findOne()` is a method to find a document inside the collection.\\\n\u003e To apply filters `$or: [{ username }, { email }]`\\\n\u003e Checks if a user available with the username or email\n\u003e\n\u003e ```js\n\u003e if (existedUser) {\n\u003e     throw new ApiError(409, \"User with email or username already exist\")\n\u003e }\n\u003e ```\n\u003e Throws a custom error.\n\n**4. Check images: Avatar is uploaded or not**\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\n\nconst registerUser = asyncHandler( async (req, res) =\u003e {\n\n    const { fullName, email, username, password } = req.body;\n\n    if (\n        [fullName, email, username, password].some((field)=\u003e field?.trim() === \"\")\n    ) {\n        throw new ApiError(400, \"All fields are required\")\n    }\n\n    const existedUser = await User.findOne({\n        $or: [{ username }, { email }]\n    })\n\n    if (existedUser) {\n        throw new ApiError(409, \"User with email or username already exist\")\n    }\n\n    const avatarLocalPath = req.files?.avatar[0]?.path;\n    const coverImageLocalPath = req.files?.coverImage[0]?.path;\n\n    if (!avatarLocalPath) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n})\n\nexport { registerUser }\n```\n\u003e [!NOTE]\\\n\u003e Since, We are using **multer** as **middleware**.\\\n\u003e Therefore, We get files from `req.files` as\n\u003e ```js\n\u003e const avatarLocalPath = req.files?.avatar[0]?.path;\n\u003e ```\n\u003e We are assuming that file path is stored in first element.\\\n\u003e And for safety purpose, we will try to access it using optional chaining. `?.`\\\n\u003e Similarly we are getting the local path of cover image.\n\u003e \n\u003e ```js\n\u003e if (!avatarLocalPath) {\n\u003e     throw new ApiError(400, \"Avatar file is required\")\n\u003e }\n\u003e ```\n\u003e Lets check for avatar is uploaded or not. If avatar is not uploaded throw an error.\n\n**5. Upload images on Cloudinary: Check avatar is uploaded or not**\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\n\nconst registerUser = asyncHandler( async (req, res) =\u003e {\n\n    const { fullName, email, username, password } = req.body;\n\n    if (\n        [fullName, email, username, password].some((field)=\u003e field?.trim() === \"\")\n    ) {\n        throw new ApiError(400, \"All fields are required\")\n    }\n\n    const existedUser = await User.findOne({\n        $or: [{ username }, { email }]\n    })\n\n    if (existedUser) {\n        throw new ApiError(409, \"User with email or username already exist\")\n    }\n\n    const avatarLocalPath = req.files?.avatar[0]?.path;\n    const coverImageLocalPath = req.files?.coverImage[0]?.path;\n\n    if (!avatarLocalPath) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n    const avatar = await uploadOnCloudinary(avatarLocalPath)\n    const coverImage = await uploadOnCloudinary(coverImageLocalPath)\n\n    if (!avatar) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n})\n\nexport { registerUser }\n```\n\u003e [!NOTE]\\\n\u003e For uploading images on **Cloudinary** we have already created utility file for this.\\\n\u003e Uploading images may take time. Must `await` the method\n\u003e ```js\n\u003e const avatar = await uploadOnCloudinary(avatarLocalPath)\n\u003e ```\n\u003e And pass the local path of the images to the method.\n\u003e\n\u003e Again check the avatar is uploaded or not in **Cloudinary**, If not uploaded throw an error.\n\n**6. Create a user object in database**\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\n\nconst registerUser = asyncHandler( async (req, res) =\u003e {\n\n    const { fullName, email, username, password } = req.body;\n\n    if (\n        [fullName, email, username, password].some((field)=\u003e field?.trim() === \"\")\n    ) {\n        throw new ApiError(400, \"All fields are required\")\n    }\n\n    const existedUser = await User.findOne({\n        $or: [{ username }, { email }]\n    })\n\n    if (existedUser) {\n        throw new ApiError(409, \"User with email or username already exist\")\n    }\n\n    const avatarLocalPath = req.files?.avatar[0]?.path;\n    const coverImageLocalPath = req.files?.coverImage[0]?.path;\n\n    if (!avatarLocalPath) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n    const avatar = await uploadOnCloudinary(avatarLocalPath)\n    const coverImage = await uploadOnCloudinary(coverImageLocalPath)\n\n    if (!avatar) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n    const user = await User.create({\n        fullName,\n        avatar: avatar.url,\n        coverImage: coverImage?.url || \"\",\n        email,\n        password,\n        username: username.toLowerCase()\n    })\n\n})\n\nexport { registerUser }\n```\n\u003e [!NOTE]\\\n\u003e Since, We are dealing with database.\\\n\u003e We know that database is in another continent.\\\n\u003e Then it will definitely take time to process so use `await`.\n\u003e\n\u003e `User.create({})` will create a new object in database.\n\u003e ```js\n\u003e const user = await User.create({\n\u003e     fullName,\n\u003e     avatar: avatar.url,\n\u003e     coverImage: coverImage?.url || \"\",\n\u003e     email,\n\u003e     password,\n\u003e     username: username.toLowerCase()\n\u003e })\n\u003e ```\n\u003e We will store the avatar url given by **Cloudinary**.\\\n\u003e Similarly we will store the cover image url but it is not required so chain it optionally.\\\n\u003e In case of no input by user show an empty string.\\\n\u003e It is better to store **username** in lowercase.\n\n**7. Remove password and Refresh Token fields**\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\n\nconst registerUser = asyncHandler( async (req, res) =\u003e {\n\n    const { fullName, email, username, password } = req.body;\n\n    if (\n        [fullName, email, username, password].some((field)=\u003e field?.trim() === \"\")\n    ) {\n        throw new ApiError(400, \"All fields are required\")\n    }\n\n    const existedUser = await User.findOne({\n        $or: [{ username }, { email }]\n    })\n\n    if (existedUser) {\n        throw new ApiError(409, \"User with email or username already exist\")\n    }\n\n    const avatarLocalPath = req.files?.avatar[0]?.path;\n    const coverImageLocalPath = req.files?.coverImage[0]?.path;\n\n    if (!avatarLocalPath) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n    const avatar = await uploadOnCloudinary(avatarLocalPath)\n    const coverImage = await uploadOnCloudinary(coverImageLocalPath)\n\n    if (!avatar) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n    const user = await User.create({\n        fullName,\n        avatar: avatar.url,\n        coverImage: coverImage?.url || \"\",\n        email,\n        password,\n        username: username.toLowerCase()\n    })\n\n    const createdUser = await User.findById(user._id).select(\n        \"-password -refreshToken\"\n    )\n\n    if (!createdUser) {\n        throw new ApiError(500, \"Something went wrong while registering the user\")\n    }\n\n})\n\nexport { registerUser }\n```\n\u003e [!NOTE]\\\n\u003e For removing password and refresh token.\\\n\u003e We can store created user reference in a variable using `findById()` method.\\\n\u003e `User.findById(user._id)` will look for the match using id.\n\u003e ```js\n\u003e const createdUser = await User.findById(user._id).select(\n\u003e     \"-password -refreshToken\"\n\u003e )\n\u003e ```\n\u003e By chain it to select the object, we can remove **password** and **refreshToken** from the response object.\\\n\u003e `select()` method uses a weird syntax I mean a string 🤔\\\n\u003e Pass the name of **fleids** to remove from the response object using **(-)** sign as prefix. eg. `-password`\n\u003e \n\u003e For more safety check again registered user is available or not?\\\n\u003e If not available throw error response with status code 500 because this is server response error.\n\n**8. Return response**\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\nconst registerUser = asyncHandler( async (req, res) =\u003e {\n\n    const { fullName, email, username, password } = req.body;\n\n    if (\n        [fullName, email, username, password].some((field)=\u003e field?.trim() === \"\")\n    ) {\n        throw new ApiError(400, \"All fields are required\")\n    }\n\n    const existedUser = await User.findOne({\n        $or: [{ username }, { email }]\n    })\n\n    if (existedUser) {\n        throw new ApiError(409, \"User with email or username already exist\")\n    }\n\n    const avatarLocalPath = req.files?.avatar[0]?.path;\n    const coverImageLocalPath = req.files?.coverImage[0]?.path;\n\n    if (!avatarLocalPath) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n    const avatar = await uploadOnCloudinary(avatarLocalPath)\n    const coverImage = await uploadOnCloudinary(coverImageLocalPath)\n\n    if (!avatar) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n    const user = await User.create({\n        fullName,\n        avatar: avatar.url,\n        coverImage: coverImage?.url || \"\",\n        email,\n        password,\n        username: username.toLowerCase()\n    })\n\n    const createdUser = await User.findById(user._id).select(\n        \"-password -refreshToken\"\n    )\n\n    if (!createdUser) {\n        throw new ApiError(500, \"Something went wrong while registering the user\")\n    }\n\n    return res.status(201).json(\n        new ApiResponse(200, createdUser, \"User registered successfully\")\n    )\n\n} )\n\nexport { registerUser }\n```\n\n### Time to test the user registration route is working or not?\n\u003e [!IMPORTANT]\\\n\u003e Keep in mind\\\n\u003e \"*It is not necessary that your code will work in one go.*\\\n\u003e *Bugs, Errors are the part of programming.* 😎\"\n\u003e\n\u003e By: *Hitesh Sir*! 💖\n\nAs we have already discussed that we don't have any frontend yet.\u003cbr/\u003e\nThat is why we will send data through **POSTMAN**\n\n#### Follow the instructions to use postman\n\n**STEP 1**: Open postman and create a new tab by clicking `+` sign\u003cbr/\u003e\nEnter the url as `http://localhost:8000/api/v1/users/register`\n\n**STEP 2**: Select `POST` method from dropdown\n\u003cselect\u003e\n    \u003coption\u003eGET\u003c/option\u003e\n    \u003coption\u003ePOST\u003c/option\u003e\n    \u003coption\u003ePUT\u003c/option\u003e\n    \u003coption\u003eHEAD\u003c/option\u003e\n\u003c/select\u003e\n\n**STEP 3**: We will send data via **Body**\u003cbr/\u003e\nBody has multiple ways to send data to backend as\u003cbr/\u003e\n\u003cdiv style=\"display: flex\"\u003e\n\u003cinput type=\"radio\" id=\"none\" name=\"datatype\"/\u003e\n\u003clabel for=\"none\"\u003enone\u003c/label\u003e \u0026nbsp;\u0026nbsp;\n\u003cinput type=\"radio\" id=\"form-data\" name=\"datatype\"/\u003e\n\u003clabel for=\"form-data\"\u003eform-data\u003c/label\u003e \u0026nbsp;\u0026nbsp;\n\u003cinput type=\"radio\" id=\"x-www-form-urlencoded\" name=\"datatype\"/\u003e\n\u003clabel for=\"x-www-form-urlencoded\"\u003ex-www-form-urlencoded\u003c/label\u003e \u0026nbsp;\u0026nbsp;\n\u003cinput type=\"radio\" id=\"raw\" name=\"datatype\"/\u003e\n\u003clabel for=\"raw\"\u003eraw\u003c/label\u003e \u0026nbsp;\u0026nbsp;\n\u003cinput type=\"radio\" id=\"binary\" name=\"datatype\"/\u003e\n\u003clabel for=\"binary\"\u003ebinary\u003c/label\u003e \u0026nbsp;\u0026nbsp;\n\u003cinput type=\"radio\" id=\"GraphQL\" name=\"datatype\"/\u003e\n\u003clabel for=\"GraphQL\"\u003eGraphQL\u003c/label\u003e\n\u003c/div\u003e \u003cbr/\u003e\n\nWe will choose the **form-data**, it has `key-value` pairs to send data.\n\u003e [!IMPORTANT]\\\n\u003e It has advantage over `raw` and `x-www-form-urlencoded`.\\\n\u003e Form data is able to send files.\\\n\u003e Since, We are sending files. So form-data is the better option. 😎\n\u003e\n\u003e In keys write the names all the fields we are accepting in backend.\\\n\u003e As `fullName` `username` `email` `password` `avatar` `coverImage`.\n\nFor better explanation, How to use postman?\u003cbr/\u003e\nCheck out the videos. 🤓\n\n### Cover Image : Bug 🐛\n*When the user does not pass a cover image*.\u003cbr/\u003e\nAs I mentioned earlier, programming often involves solving **bugs** and **errors**. 🤓\n\nWhen we try to create a user without a cover image, we get an error.\u003cbr/\u003e\nThis is not a backend or server error; it's a core JavaScript error.\n\n**Here is the solution**\u003cbr/\u003e\n`src/routes/user.routes.js`\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\nconst registerUser = asyncHandler( async (req, res) =\u003e {\n\n    const { fullName, email, username, password } = req.body;\n\n    if (\n        [fullName, email, username, password].some((field)=\u003e field?.trim() === \"\")\n    ) {\n        throw new ApiError(400, \"All fields are required\")\n    }\n\n    const existedUser = await User.findOne({\n        $or: [{ username }, { email }]\n    })\n\n    if (existedUser) {\n        throw new ApiError(409, \"User with email or username already exist\")\n    }\n\n    const avatarLocalPath = req.files?.avatar[0]?.path;\n    // const coverImageLocalPath = req.files?.coverImage[0]?.path;\n\n    let coverImageLocalPath;\n    if (req.files \u0026\u0026 Array.isArray(req.files.coverImage) \u0026\u0026 req.files.coverImage.length \u003e 0) {\n        coverImageLocalPath = req.files.coverImage[0].path\n    }\n\n    if (!avatarLocalPath) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n    const avatar = await uploadOnCloudinary(avatarLocalPath)\n    const coverImage = await uploadOnCloudinary(coverImageLocalPath)\n\n    if (!avatar) {\n        throw new ApiError(400, \"Avatar file is required\")\n    }\n\n    const user = await User.create({\n        fullName,\n        avatar: avatar.url,\n        coverImage: coverImage?.url || \"\",\n        email,\n        password,\n        username: username.toLowerCase()\n    })\n\n    const createdUser = await User.findById(user._id).select(\n        \"-password -refreshToken\"\n    )\n\n    if (!createdUser) {\n        throw new ApiError(500, \"Something went wrong while registering the user\")\n    }\n\n    return res.status(201).json(\n        new ApiResponse(200, createdUser, \"User registered successfully\")\n    )\n\n} )\n\nexport { registerUser }\n```\n\u003e [!IMPORTANT]\\\n\u003e Since we are not checking for the cover image, if the user does not provide a cover image, we need to create a checkpoint.\n\u003e ```js\n\u003e let coverImageLocalPath;\n\u003e if (req.files \u0026\u0026 Array.isArray(req.files.coverImage) \u0026\u0026 req.files.coverImage.length \u003e 0) {\n\u003e     coverImageLocalPath = req.files.coverImage[0].path\n\u003e }\n\u003e ```\n\u003e Here, we will try to access the cover image from the files if available.\\\n\u003e Otherwise, the value will be `undefined`.\n\n***\n\n### Cloudinary Response 🤩\nWe will receive an object.\u003cbr/\u003e\n`asset_id` `public_id` `version` `version_id` `signature` `width: 720` `heigth: 720` `resource_type: \"image\"` `created_at` `tags` `bytes` `type: \"upload\"` `etag` `placeholder: false` `url` `secure_url` `asset_folder` `display_name` `original_filename` `api_key`\n\n***\n\n### Login method\nWe have written method for register a user.\u003cbr/\u003e\nNow, We will write another method for login by following these Algorithm\n```js\n// ALGORITHM for User Login Method\n\n// req body -\u003e data\n// check for username or email\n// find the user\n// password check\n// access and refresh token\n// send cookie\n```\n\n**1**. Create Login method in `user.controller.js`\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e Create a login method using `asyncHandler()` and `export` it as named export\n\n\n**2**. Get data from request body\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const { username, email, password } = req.body\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e [!NOTE]\\\n\u003e Assuming that we will get `username`, `email` and `password` from the user.\n\n**3**. Check for username or email\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const {username, email, password} = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e [!IMPORTANT]\\\n\u003e Since, We can login with either `username` or `email`.\\\n\u003e Therefore, We need atleast one of them to proceed login.\n\n**4**. Find the user if exist else throw an error\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const {username, email, password} = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n    const user = await User.findOne({\n        $or: [{username}, {email}]\n    })\n\n    if (!user) {\n        throw new ApiError(404, \"User does not exist\")\n    }\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e [!NOTE]\\\n\u003e `User.findOne()` is a method to find a document in database.\\\n\u003e And we have learned that- *\"Our database is in another continent\"*.\n\u003e \n\u003e So `await` it, because database call takes time. 🐌\n\u003e\n\u003e We can use filter methods in `findOne()` inside `{}` and the method starts with `$` sign\n\u003e ```js\n\u003e const user = await User.findOne({\n\u003e    $or: [{username}, {email}]\n\u003e })\n\u003e ```\n\u003e This `$or` method will find the user basis of `username` or `email`.\\\n\u003e If the user not exist throw an error.\n\n**5**. Password validation\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const { username, email, password } = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n    const user = await User.findOne({\n        $or: [{username}, {email}]\n    })\n\n    if (!user) {\n        throw new ApiError(404, \"User does not exist\")\n    }\n\n    const isPasswordValid = await user.isPasswordCorrect(password)\n\n    if (!isPasswordValid) {\n        throw new ApiError(401, \"Invalid user credentials\")\n    }\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e [!NOTE]\\\n\u003e In the user model, We have a method for password comparison named as `isPasswordCorrect()`.\n\u003e\n\u003e Don't get confused between `user` and `User` 🤔\\\n\u003e `User` is a schema model acts as a bridge between the database and our local server. It helps to talk with database.\\\n\u003e The `user` is a variable instance holds the data of found user after the execution of `findOne()` method, and we will use it for validations.\n\u003e \n\u003e Again `user.isPasswordCorrect()` is a method for password validation. Which helps to match the entered password with the password saved in the database.\\\n\u003e Don't forget to `await` it.\n\n**6**. Generate access token and refresh token\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\nconst generateAccessAndRefreshTokens = (userId) =\u003e {\n    \n}\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const { username, email, password } = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n    const user = await User.findOne({\n        $or: [{username}, {email}]\n    })\n\n    if (!user) {\n        throw new ApiError(404, \"User does not exist\")\n    }\n\n    const isPasswordValid = await user.isPasswordCorrect(password)\n\n    if (!isPasswordValid) {\n        throw new ApiError(401, \"Invalid user credentials\")\n    }\n\n    generateAccessAndRefreshTokens(user._id)\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e For generating access and refresh token, We will create a separate internal method which will accept user id generated by mongodb.\\\n\u003e `generateAccessAndRefreshTokens(user._id)` here `_id` is generated by mongodb.\n\u003e\n\u003e It is better to write internal methods after the `import`s.\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\nconst generateAccessAndRefreshTokens = (userId) =\u003e {\n    try {\n        \n    } catch (error) {\n        throw new ApiError(500,  \"Something went wrong while generating refresh and access token\")\n    }\n}\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const { username, email, password } = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n    const user = await User.findOne({\n        $or: [{username}, {email}]\n    })\n\n    if (!user) {\n        throw new ApiError(404, \"User does not exist\")\n    }\n\n    const isPasswordValid = await user.isPasswordCorrect(password)\n\n    if (!isPasswordValid) {\n        throw new ApiError(401, \"Invalid user credentials\")\n    }\n\n    generateAccessAndRefreshTokens(user._id)\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e Since, We are dealing with database errors may occur.\\\n\u003e For the safety purpose wrap the code inside a `try` and `catch` block.\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\nconst generateAccessAndRefreshTokens = async (userId) =\u003e {\n    try {\n\n        const user = await User.findById(userId)\n\n    } catch (error) {\n        throw new ApiError(500,  \"Something went wrong while generating refresh and access token\")\n    }\n}\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const { username, email, password } = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n    const user = await User.findOne({\n        $or: [{username}, {email}]\n    })\n\n    if (!user) {\n        throw new ApiError(404, \"User does not exist\")\n    }\n\n    const isPasswordValid = await user.isPasswordCorrect(password)\n\n    if (!isPasswordValid) {\n        throw new ApiError(401, \"Invalid user credentials\")\n    }\n\n    generateAccessAndRefreshTokens(user._id)\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e [!NOTE]\\\n\u003e For generating tokens we will have to find a user.\\\n\u003e We will find the user with the passed `userId` in the parameter.\n\u003e\n\u003e `User.findById(userId)` deals with database, It will definitely take time to process, must `await` it. and the method should be `async` method.\\\n\u003e Store the received user in a variable.\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\nconst generateAccessAndRefreshTokens = async (userId) =\u003e {\n    try {\n\n        const user = await User.findById(userId)\n\n        const accessToken = user.generateAccessToken()\n        const refreshToken = user.generateRefreshToken()\n\n        user.refreshToken = refreshToken\n        await user.save({ validateBeforeSave: false })\n\n        return { accessToken, refreshToken }\n\n    } catch (error) {\n        throw new ApiError(500,  \"Something went wrong while generating refresh and access token\")\n    }\n}\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const { username, email, password } = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n    const user = await User.findOne({\n        $or: [{username}, {email}]\n    })\n\n    if (!user) {\n        throw new ApiError(404, \"User does not exist\")\n    }\n\n    const isPasswordValid = await user.isPasswordCorrect(password)\n\n    if (!isPasswordValid) {\n        throw new ApiError(401, \"Invalid user credentials\")\n    }\n\n    generateAccessAndRefreshTokens(user._id)\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e [!IMPORTANT]\\\n\u003e We have methods for generating access and refresh token in User model\n\u003e ```js\n\u003e const accessToken = user.generateAccessToken()\n\u003e const refreshToken = user.generateRefreshToken()\n\u003e ```\n\u003e `generateAccessToken()` and `generateRefreshToken()` are the methods.\n\u003e \n\u003e Now we will save the refresh token in database so that we don't have to login for every task.\\\n\u003e Database document is nothing just an object so we can access it's attributes.\n\u003e ```js\n\u003e user.refreshToken = refreshToken\n\u003e ```\n\u003e ```js\n\u003e user.refreshToken = refreshToken\n\u003e await user.save()\n\u003e ```\n\u003e `user.save()` method is used to save the refresh token in the database.\\\n\u003e Since, password is **required** for every input in database.\\\n\u003e So we can simply add a parameter as\n\u003e ```js\n\u003e await user.save({validateBeforeSave: false})\n\u003e ```\n\u003e\n\u003e Once, access and refresh tokens are generated we can `return` them to the user.\\\n\u003e This time we will `return` tokens as an object.\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\nconst generateAccessAndRefreshTokens = async (userId) =\u003e {\n    try {\n\n        const user = await User.findById(userId)\n\n        const accessToken = user.generateAccessToken()\n        const refreshToken = user.generateRefreshToken()\n\n        user.refreshToken = refreshToken\n        await user.save({validateBeforeSave: false})\n\n        return { accessToken, refreshToken }\n\n    } catch (error) {\n        throw new ApiError(500,  \"Something went wrong while generating refresh and access token\")\n    }\n}\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const { username, email, password } = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n    const user = await User.findOne({\n        $or: [{username}, {email}]\n    })\n\n    if (!user) {\n        throw new ApiError(404, \"User does not exist\")\n    }\n\n    const isPasswordValid = await user.isPasswordCorrect(password)\n\n    if (!isPasswordValid) {\n        throw new ApiError(401, \"Invalid user credentials\")\n    }\n\n    const { accessToken, refreshToken } = await generateAccessAndRefreshTokens(user._id)\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e [!NOTE]\\\n\u003e Inside the `generateAccessAndRefreshTokens()` method we are dealing with database. It is better to `await` the method.\n\u003e\n\u003e The method provides us access and refresh tokens in the form of an object. So we can destruct values from the object as `{ accessToken, refreshToken }`\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\nconst generateAccessAndRefreshTokens = async (userId) =\u003e {\n    try {\n\n        const user = await User.findById(userId)\n\n        const accessToken = user.generateAccessToken()\n        const refreshToken = user.generateRefreshToken()\n\n        user.refreshToken = refreshToken\n        await user.save({validateBeforeSave: false})\n\n        return { accessToken, refreshToken }\n\n    } catch (error) {\n        throw new ApiError(500,  \"Something went wrong while generating refresh and access token\")\n    }\n}\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const {username, email, password} = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n    const user = await User.findOne({\n        $or: [{username}, {email}]\n    })\n\n    if (!user) {\n        throw new ApiError(404, \"User does not exist\")\n    }\n\n    const isPasswordValid = await user.isPasswordCorrect(password)\n\n    if (!isPasswordValid) {\n        throw new ApiError(401, \"Invalid user credentials\")\n    }\n\n    const { accessToken, refreshToken } = await generateAccessAndRefreshTokens(user._id)\n\n    const loggedInUser = await User.findById(user._id).select(\"-password -refreshToken\")\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e [!IMPORTANT]\\\n\u003e The `user` variable doesn't have the value of refresh token because, we have accessed the user before generating tokens.\n\u003e ```js\n\u003e const user = await User.findOne({\n\u003e     $or: [{username}, {email}]\n\u003e })\n\u003e ```\n\u003e That is why, we need the updated user instance as well as we have some unnecessary data fields like password and refresh token in the created `user` instance.\n\u003e \n\u003e So time to make another database call to get updated `user` instance excluding password and refresh token, and store it in another variable as `loggedInUser`\n\u003e ```js\n\u003e const loggedInUser = await User.findById(user._id).select(\"-password -refreshToken\")\n\u003e ```\n\n**7**. Sending cookie\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\nconst generateAccessAndRefreshTokens = async (userId) =\u003e {\n    try {\n\n        const user = await User.findById(userId)\n\n        const accessToken = user.generateAccessToken()\n        const refreshToken = user.generateRefreshToken()\n\n        user.refreshToken = refreshToken\n        await user.save({validateBeforeSave: false})\n\n        return { accessToken, refreshToken }\n\n    } catch (error) {\n        throw new ApiError(500,  \"Something went wrong while generating refresh and access token\")\n    }\n}\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const { username, email, password } = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n    const user = await User.findOne({\n        $or: [{username}, {email}]\n    })\n\n    if (!user) {\n        throw new ApiError(404, \"User does not exist\")\n    }\n\n    const isPasswordValid = await user.isPasswordCorrect(password)\n\n    if (!isPasswordValid) {\n        throw new ApiError(401, \"Invalid user credentials\")\n    }\n\n    const { accessToken, refreshToken } = await generateAccessAndRefreshTokens(user._id)\n\n    const loggedInUser = await User.findById(user._id).select(\"-password -refreshToken\")\n\n    const options = {\n        httpOnly: true,\n        secure: true\n    }\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e [!NOTE]\\\n\u003e When we send cookies, we have to design some options for the cookies.\\\n\u003e Options are nothing just an Object\n\u003e ```js\n\u003e const options = {\n\u003e    httpOnly: true,\n\u003e    secure: true\n\u003e }\n\u003e ```\n\u003e These options defines that cookies are modifiable in the server only. But we can access and see them in frontend.\n\nReturn a response\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\nconst generateAccessAndRefreshTokens = async (userId) =\u003e {\n    try {\n\n        const user = await User.findById(userId)\n\n        const accessToken = user.generateAccessToken()\n        const refreshToken = user.generateRefreshToken()\n\n        user.refreshToken = refreshToken\n        await user.save({validateBeforeSave: false})\n\n        return { accessToken, refreshToken }\n\n    } catch (error) {\n        throw new ApiError(500,  \"Something went wrong while generating refresh and access token\")\n    }\n}\n\n\n// Register User\n// ...\n// ...\n\n\nconst loginUser = asyncHandler( async (req, res) =\u003e {\n    \n    const { username, email, password } = req.body\n\n    if (!username || !email) {\n        throw new ApiError(400, \"username or email is required\")\n    }\n\n    const user = await User.findOne({\n        $or: [{username}, {email}]\n    })\n\n    if (!user) {\n        throw new ApiError(404, \"User does not exist\")\n    }\n\n    const isPasswordValid = await user.isPasswordCorrect(password)\n\n    if (!isPasswordValid) {\n        throw new ApiError(401, \"Invalid user credentials\")\n    }\n\n    const { accessToken, refreshToken } = await generateAccessAndRefreshTokens(user._id)\n\n    const loggedInUser = await User.findById(user._id).select(\"-password -refreshToken\")\n\n    const options = {\n        httpOnly: true,\n        secure: true\n    }\n\n    return res\n    .status(200)\n    .cookie(\"accessToken\", accessToken, options)\n    .cookie(\"refreshToken\", refreshToken, options)\n    .json(\n        new ApiResponse(\n            200,\n            {\n                user: loggedInUser, accessToken, refreshToken\n            },\n            \"User logged in Successfully\"\n        )\n    )\n\n} )\n\nexport { \n    registerUser,\n    loginUser\n}\n```\n\u003e [!NOTE]\\\n\u003e In the response object we wil return `status` code, `cookie`s and a `json` object.\n\u003e ```js\n\u003e return res.status(200)\n\u003e ```\n\u003e\n\u003e We have access of `cookie`s because we have injected a middleeware for `cookie`s in `app.js`.\n\u003e ```js\n\u003e return res\n\u003e .status(200)\n\u003e .cookie(\"accessToken\", accessToken, options)\n\u003e ```\n\u003e `cookie(name, value, options)`\n\n### Logout method\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\n// generateAccessAndRefreshTokens method\n// ...\n// ...\n\n// Register User\n// ...\n// ...\n\n// Login User\n// ...\n// ...\n\n\nconst logoutUser = asyncHandler( async (req, res) =\u003e {\n    \n} )\n\nexport { \n    registerUser,\n    loginUser,\n    logoutUser\n}\n```\n\u003e Create a logout user method using `asyncHandler()`.\n\n\u003e [!IMPORTANT]\\\n\u003e For logout we don't need any kind of password validation.\\\n\u003e Logout must be a secured method so that nobody could logout any other user by providing their username or email.\n\n#### Authentication middleware\nAuthentication middleware is a custom middleware. 😋\u003cbr/\u003e\n`src/middlewares/auth.middleware.js`\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler\";\n\nexport const verifyJWT = asyncHandler( async (req, res, next) =\u003e {\n    \n})\n```\n\u003e Create a method as `verifyJWT` with the help of `asyncHandler()`\n\u003e \n\u003e We have learned that middleware has four parameters as\\\n\u003e `(err, req, res, next) =\u003e {}`\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler\";\nimport { ApiError } from \"../utils/ApiError\";\n\nexport const verifyJWT = asyncHandler( async (req, res, next) =\u003e {\n    try {\n    \n    } catch (error) {\n        throw new ApiError(401, \"Invalid Access Token\")\n    }\n})\n```\n\u003e Start a `try` and `catch` block.\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler\";\nimport { ApiError } from \"../utils/ApiError\";\n\nexport const verifyJWT = asyncHandler( async (req, res, next) =\u003e {\n    try {\n\n        const token = req.cookies?.accessToken || req.header(\"Authorization\")?.replace(\"Bearer \", \"\")\n\n        if (!token) {\n            throw new ApiError(401, \"Unauthorized request\")\n        }\n    \n    } catch (error) {\n        throw new ApiError(401, \"Invalid Access Token\")\n    }\n})\n```\n\u003e [!IMPORTANT]\\\n\u003e We have already saved some information in `cookie`s during the user login. So now `cookie`s are accessible.\\\n\u003e We can get values from `cookie`s if available.\n\u003e\n\u003e We are trying to get access token from `cookie`s using **optional chaining** `(?.)` for safety.\n\u003e ```js\n\u003e req.cookies?.accessToken\n\u003e ```\n\u003e If the above method will get fail then get the value from header.\n\u003e ```js\n\u003e req.header(\"Authorization\")?.replace(\"Bearer \", \"\")\n\u003e ```\n\u003e \n\u003e If token not available throw an error.\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler\";\nimport { ApiError } from \"../utils/ApiError\";\nimport jwt from \"jsonwebtoken\";\n\nexport const verifyJWT = asyncHandler( async (req, res, next) =\u003e {\n    try {\n\n        const token = req.cookies?.accessToken || req.header(\"Authorization\")?.replace(\"Bearer \", \"\")\n\n        if (!token) {\n            throw new ApiError(401, \"Unauthorized request\")\n        }\n\n        const decodedUser = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET)\n    \n    } catch (error) {\n        throw new ApiError(401, \"Invalid Access Token\")\n    }\n})\n```\n\u003e We will use `jwt` for verifying and the `verify()` method has two arguments **token** and **secret**.\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler\";\nimport { ApiError } from \"../utils/ApiError\";\nimport jwt from \"jsonwebtoken\";\nimport { User } from \"../models/user.model\";\n\nexport const verifyJWT = asyncHandler( async (req, res, next) =\u003e {\n    try {\n\n        const token = req.cookies?.accessToken || req.header(\"Authorization\")?.replace(\"Bearer \", \"\")\n\n        if (!token) {\n            throw new ApiError(401, \"Unauthorized request\")\n        }\n\n        const decodedUser = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET)\n\n        const user = await User.findById(decodedUser?._id).select(\"-password -refreshToken\")\n\n        if (!user) {\n            throw new ApiError(401, \"Invalid Access Token\")\n        }\n    \n    } catch (error) {\n        throw new ApiError(401, \"Invalid Access Token\")\n    }\n})\n```\n\u003e [!NOTE]\\\n\u003e Store the decoded user in a new variable without password and refresh token.\n\u003e\n\u003e For finding the decoded user in the database we have only one bridge, I mean `User` model schema.\\\n\u003e If the user not exist throw an error.\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler\";\nimport { ApiError } from \"../utils/ApiError\";\nimport jwt from \"jsonwebtoken\";\nimport { User } from \"../models/user.model\";\n\nexport const verifyJWT = asyncHandler( async (req, _, next) =\u003e {\n    try {\n\n        const token = req.cookies?.accessToken || req.header(\"Authorization\")?.replace(\"Bearer \", \"\")\n\n        if (!token) {\n            throw new ApiError(401, \"Unauthorized request\")\n        }\n\n        const decodedUser = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET)\n\n        const user = await User.findById(decodedUser?._id).select(\"-password -refreshToken\")\n\n        if (!user) {\n            throw new ApiError(401, \"Invalid Access Token\")\n        }\n\n        req.user = user;\n        next()\n    \n    } catch (error) {\n        throw new ApiError(401, \"Invalid Access Token\")\n    }\n})\n```\n\u003e [!IMPORTANT]\\\n\u003e As discussed earlier, middlewares have the capacity of modifying `req` and `res` object.\\\n\u003e In this case we are adding an object in `req` object.\n\u003e \n\u003e And propagate it to the next node in the list using `next()` flag.\n\u003e\n\u003e Since, we are doing nothing with the `res` object. So that we can replace it by a underscore `(_)` in the parameter.\n\n#### Adding `route`s to the `user.routes.js`\n**1**. Create login route\n```js\nimport { Router } from \"express\"\nimport { loginUser, registerUser } from \"../controllers/user.controller.js\"\nimport { upload } from \"../middlewares/multer.middleware.js\"\n\nconst router = Router()\n\n// User registration route\n// ...\n\nrouter.route(\"/login\").post(loginUser)\n\nexport default router\n```\n\n**2**. Create logout route\n```js\nimport { Router } from \"express\"\nimport { loginUser, logoutUser, registerUser } from \"../controllers/user.controller.js\"\nimport { upload } from \"../middlewares/multer.middleware.js\"\nimport { verifyJWT } from \"../middlewares/auth.middleware.js\"\n\nconst router = Router()\n\n// User registration route\n// ...\n\nrouter.route(\"/login\").post(loginUser)\n\n// Secured routes\nrouter.route(\"/logout\").post(verifyJWT, logoutUser)\n\nexport default router\n```\n\u003e [!NOTE]\\\n\u003e We have a middleware as `auth.middleware.js` for verifying.\\\n\u003e Inject it in the logout route before hitting the logout user controller.\n\u003e \n\u003e Middleware executes one after one in the series, and they must have a `next()` flag for the propagation.\\\n\u003e `post(middleware1, middleware2, endpoint)`\n\nBack to the `user.controller.js`\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\n// generateAccessAndRefreshTokens method\n// ...\n// ...\n\n// Register User\n// ...\n// ...\n\n// Login User\n// ...\n// ...\n\n\nconst logoutUser = asyncHandler( async (req, res) =\u003e {\n\n    await User.findByIdAndUpdate(\n        req.user._id,\n        {\n            $set: {\n                refreshToken: undefined\n            }\n        },\n        {\n            new: true\n        }\n    )\n\n} )\n\nexport { \n    registerUser,\n    loginUser,\n    logoutUser\n}\n```\n\u003e [!IMPORTANT]\\\n\u003e To logout we need a user.\n\u003e \n\u003e In the logout method we don't send any data from the frontend like `username` or `email`.\\\n\u003e Because user is already logged in that is why we are trying to log out.\\\n\u003e\n\u003e Also, we have injected a middleware in the logout route as `verifyJWT`.\\\n\u003e Which modifies the `req` object and adds a new attribute as `user` with user data fields in the form of object.\\\n\u003e Accessing values from the `user` object embedded with `req` object is possible with dot notation as `req.body.[ data-field ]`\n\u003e\n\u003e When we logout a user, we must have to reset or clear the value of refresh token.\n\u003e ```js\n\u003e User.findByIdAndUpdate()\n\u003e ```\n\u003e is a mongodb method used to find and update any data field in the document. It accepts three arguments as \n\u003e ```js\n\u003e findByIdAndUpdate(\n\u003e       req.user._id,        // finds the user on the basis of id generated by mongodb\n\u003e       {\n\u003e           $set: {\n\u003e               refreshToken: undefined             // Value to be updated\n\u003e           }\n\u003e       },\n\u003e       {\n\u003e           new: true       // for getting the most updated value\n\u003e       }\n\u003e )\n\u003e ```\n\n```js\nimport { asyncHandler } from \"../utils/asyncHandler.js\"\nimport { ApiError } from \"../utils/ApiError.js\"\nimport { User } from \"../models/user.model.js\"\nimport { uploadOnCloudinary } from \"../utils/cloudinary.js\"\nimport { ApiResponse } from \"../utils/ApiResponse.js\"\n\n\n// generateAccessAndRefreshTokens method\n// ...\n// ...\n\n// Register User\n// ...\n// ...\n\n// Login User\n// ...\n// ...\n\n\nconst logoutUser = asyncHandler( async (req, res) =\u003e {\n\n    await User.findByIdAndUpdate(\n        req.user._id,\n        {\n            $set: {\n                refreshToken: undefined\n            }\n        },\n        {\n            new: true\n        }\n    )\n\n    const options = {\n        httpOnly: true,\n        secure: true\n    }\n\n    return res\n    .status(200)\n    .clearCookie(\"accessToken\", options)\n    .clearCookie(\"refreshToken\", options)\n    .json(\n        new ApiResponse(200, {}, \"User logged Out\")\n    )\n\n} )\n\nexport { \n    registerUser,\n    loginUser,\n    logoutUser\n}\n```\n\u003e Set options for `cookie`s and remove saved `cookie`s using `clearCookie()`.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodezaura%2FJavaScript-Backend-Setup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcodezaura%2FJavaScript-Backend-Setup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcodezaura%2FJavaScript-Backend-Setup/lists"}