{"id":21943564,"url":"https://github.com/rohan220217/nodejs","last_synced_at":"2026-04-13T06:10:15.861Z","repository":{"id":42900746,"uuid":"251501860","full_name":"rohan220217/NodeJS","owner":"rohan220217","description":"A backend for movies rental application using nodeJS  ","archived":false,"fork":false,"pushed_at":"2023-01-05T18:15:32.000Z","size":259,"stargazers_count":1,"open_issues_count":11,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-03T17:49:04.493Z","etag":null,"topics":["bcrypt-hashing-library","express-js","express-middleware","expressjs","fawn","jwt-tokens","loadash","mongoose-crud-operation","nodejs","npm-package"],"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/rohan220217.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}},"created_at":"2020-03-31T04:39:40.000Z","updated_at":"2022-06-30T20:09:26.000Z","dependencies_parsed_at":"2023-02-04T09:46:59.778Z","dependency_job_id":null,"html_url":"https://github.com/rohan220217/NodeJS","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rohan220217%2FNodeJS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rohan220217%2FNodeJS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rohan220217%2FNodeJS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rohan220217%2FNodeJS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rohan220217","download_url":"https://codeload.github.com/rohan220217/NodeJS/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244981293,"owners_count":20542288,"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-hashing-library","express-js","express-middleware","expressjs","fawn","jwt-tokens","loadash","mongoose-crud-operation","nodejs","npm-package"],"created_at":"2024-11-29T03:33:04.962Z","updated_at":"2026-04-13T06:10:15.827Z","avatar_url":"https://github.com/rohan220217.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Getting Started with Node\n- Node is a runtime environment for executing JS code.\n- Essentially, Node is a C++ program that embeds Chrome’s v8 engine, the fastest\nJS engine in the world.\n- We use Node to build fast and scalable networking applications. It’s a perfect\nchoice for building RESTful services.\n- Node applications are single-threaded. That means a single thread is used to\nserve all clients.\n- Node applications are asynchronous or non-blocking by default. That means\nwhen the application involves I/O operations (eg accessing the file system or the\nnetwork), the thread doesn’t wait (or block) for the result of the operation. It is\nreleased to serve other clients.\n- This architecture makes Node ideal for building I/O-intensive applications.\n- You should avoid using Node for CPU-intensive applications, such as a video\nencoding service. Because while executing these operations, other clients have\nto wait for the single thread to finish its job and be ready to serve them.\n- In Node, we don’t have browser environment objects such as window or the\ndocument object. Instead, we have other objects that are not available in\nbrowsers, such as objects for working with the file system, network, operating\nsystem, etc.\n\n------------------------------------------------------\n\n# Node Core\n\n- We don’t have the window object in Node.\n- The global object in Node is “global”.\n- Unlike browser applications, variables we define are not added to the “global”\nobject.\n- Every file in a Node application is a module. Node automatically wraps the code\nin each file with an IIFE (Immediately-invoked Function Expression) to create\nscope. So, variables and functions defined in one file are only scoped to that file\nand not visible to other files unless explicitly exported.\n- To export a variable or function from a module, you need to add them to\nmodule.exports:\nmodule.exports.sayHello = sayHello;\n- To load a module, use the require function. This function returns the\nmodule.exports object exported from the target module:\nconst logger = require(‘./logger’);\n- Node has a few built-in modules that enable us to work with the file system, path\nobjects, network, operating system, etc.\n- EventEmitter is one of the core classes in Node that allows us to raise (emit) and\nhandle events. Several built-in classes in Node derive from EventEmitter.\n- To create a class with the ability to raise events, we should extend EventEmitter:\nclass Logger extends EventEmitter {\n}\n-----------------\n# NPM\n\n- Every Node application has a package.json file that includes metadata about the\napplication. This includes the name of the application, its version, dependencies,\netc.\n- We use NPM to download and install 3rd-party packages from NPM registry:\n- All the installed packages and their dependencies are stored under\nnode_modules folders. This folder should be excluded from the source control.\n- Node packages follow semantic versioning: major.minor.patch\n- Useful NPM commands are:\n    - Install a package\n    ```npm i \u003cpackageName\u003e ```\n    - Install a specific version of a package\n    ```npm i \u003cpackageName\u003e@\u003cversion\u003e```\n    - Install a package as a development dependency\n    ```npm i \u003cpackageName\u003e —save-dev```\n     - Uninstall a package\n    ```npm un \u003cpackageName\u003e```\n     - List installed packages\n    ```npm list —depth=0```\n     - View outdated packages\n    ```npm outdated```\n     - Update packages\n    ```npm update```\n     - To install/uninstall packages globally,\n    ```use -g flag.```\n--------------------\n# Building RESTful APIs with Express\n- REST defines a set of conventions for creating HTTP services:\n    - POST: to create a resource\n    - PUT: to update it\n    - GET: to read it\n    - DELETE: to delete it\n- Express is a simple, minimalistic and lightweight framework for building web\nservers.\n    -  Build a web server\n        ```\n        const express = require(‘express’);\n        const app = express();\n        ```\n    -  Creating a course\n        ```\n        app.post(‘/api/courses’, (req, res) =\u003e {\n        // Create the course and return the course object\n        res.send(course);\n        });\n        ```\n    - Getting all the courses\n         ```\n        app.get(‘/api/courses’, (req, res) =\u003e {\n        // To read query string parameters (?sortBy=name)\n        const sortBy = req.query.sortBy;\n         // Return the courses\n        res.send(courses);\n        });\n        ```\n    - Getting a single course\n        ```\n        app.get(‘/api/courses/:id’, (req, res) =\u003e {\n        const courseId = req.params.id;\n        // Lookup the course\n        // If not found, return 404\n        res.status(404).send(‘Course not found.’);\n        // Else, return the course object\n        res.send(course);\n        });\n        ```\n    - Updating a course\n        ```\n        app.put(‘/api/courses/:id’, (req, res) =\u003e {\n        // If course not found, return 404, otherwise update it\n        // and return the updated object.\n        });\n        ```\n    - Deleting a course\n        ```\n        app.delete(‘/api/courses/:id’, (req, res) =\u003e {\n        // If course not found, return 404, otherwise delete it\n        // and return the deleted object.\n        });\n        ```\n    - Listen on port 3000\n        ```\n        app.listen(3000, () =\u003e console.log(‘Listening…’));\n        ```\n- We use Nodemon to watch for changes in files and automatically restart the\nnode process.\n- We can use environment variables to store various settings for an application. To\nread an environment variable, we use process.env.\n    ```\n    // Reading the port from an environment variable\n    const port = process.env.PORT || 3000;\n    app.listen(port);\n    ```\n- You should never trust data sent by the client. Always validate! Use Joi package\nto perform input validation.\n\n------\n# Express: Advanced Topics\n- A middleware function is a function that takes a request object and either\nterminates the request/response cycle or passes control to another middleware\nfunction.\n- Express has a few built-in middleware functions:\n    - json(): to parse the body of requests with a JSON payload\n    - urlencoded(): to parse the body of requests with URL-encoded payload\n    - static(): to serve static files\n- You can create custom middleware for cross-cutting concerns, such as logging,\nauthentication, etc.\n    -  Custom middleware (applied on all routes)\n        ```\n        app.use(function(req, res, next)) {\n        // …\n        next();\n        }\n        ```\n    -  Custom middleware (applied on routes starting with /api/admin)\n        ```\n        app.use(‘/api/admin’, function(req, res, next)) {\n        // …\n        next();\n        }\n        ```\n- We can detect the environment in which our Node application is running\n(development, production, etc) using ``` process.env.NODE_ENV and\napp.get(‘env’). ```\n- The config package gives us an elegant way to store configuration settings for\nour applications.\n- We can use the debug package to add debugging information to an application.\nPrefer this approach to ```console.log() ```statements.\n- To return HTML markup to the client, use a templating engine. There are various\ntemplating engines available out there.``` Pug, EJS and Mustache ```are the most\npopular ones.\n\n\n-------------\n# CRUD Operations using Mongoose and MongoDB\n\n- MongoDB is an open-source document database. It stores data in flexible, JSONlike\ndocuments.\n\n- In relational databases we have tables and rows, in MongoDB we have\ncollections and documents. A document can contain sub-documents.\n\n- We don’t have relationships between documents.\n\n- To connect to MongoDB:\n    ```\n    // Connecting to MongoDB\n    const mongoose = require(‘mongoose’);\n    mongoose.connect(‘mongodb://localhost/playground')\n    .then(() =\u003e console.log(‘Connected…’))\n    .catch(err =\u003e console.error(‘Connection failed…’));\n    ```\n- To store objects in MongoDB, we need to define a Mongoose schema first. The\nschema defines the shape of documents in MongoDB.\n    ```\n    // Defining a schema\n    const courseSchema = new mongoose.Schema({\n    name: String,\n    price: Number\n    });\n    ```\n- We can use a SchemaType object to provide additional details:\n    ```\n    // Using a SchemaType object\n    const courseSchema = new mongoose.Schema({\n    isPublished: { type: Boolean, default: false }\n    });\n    ```\n- Supported types are: String, Number, Date, Buffer (for storing binary data),\nBoolean and ObjectID.\n- Once we have a schema, we need to compile it into a model. A model is like a\nclass. It’s a blueprint for creating objects:\n    ```\n        // Creating a model\n        const Course = mongoose.model(‘Course’, courseSchema);\n    ```\n\u003e CRUD Operations \n\n- Saving a document\n    ```\n    let course = new Course({ name: ‘…’ });\n    course = await course.save();\n    ```\n- Querying documents\n    ```\n    const courses = await Course\n    .find({ author: ‘Rohan’, isPublished: true })\n    .skip(10)\n    .limit(10)\n    .sort({ name: 1, price: -1 })\n    .select({ name: 1, price: 1 });\n    ```\n- Updating a document (query first)\n    ```\n    const course = await Course.findById(id);\n    if (!course) return;\n    course.set({ name: ‘…’ });\n    course.save();\n    ```\n- Updating a document (update first)\n    ```\n    const result = await Course.update({ _id: id }, {\n    $set: { name: ‘…’ }\n    });\n    ```\n- Updating a document (update first) and return it\n    ```\n    const result = await Course.findByIdAndUpdate({ _id: id }, {\n    $set: { name: ‘…’ }\n    }, { new: true });\n    ```\n- Removing a document\n    ```\n    const result = await Course.deleteOne({ _id: id });\n    const result = await Course.deleteMany({ _id: id });\n    const course = await Course.findByIdAndRemove(id);\n    ```\n \n-------------\n# Mongoose: Validation\n\n- When defining a schema, you can set the type of a property to a SchemaType\nobject. You use this object to define the validation requirements for the given\nproperty.\n    ```\n    // Adding validation\n    new mongoose.Schema({\n    name: { type: String, required: true }\n    })\n    ```\n- Validation logic is executed by Mongoose prior to saving a document to the\ndatabase. You can also trigger it manually by calling the validate() method.\n- Built-in validators:\n    - Strings: minlength, maxlength, match, enum\n    - Numbers: min, max\n    - Dates: min, max\n    - All types: required\n- Custom validation\n    ```\n    tags: [\n    type: Array,\n    validate: {\n    validator: function(v) { return v \u0026\u0026 v.length \u003e 0; },\n    message: ‘A course should have at least 1 tag.’\n    }\n    ]\n    ```\n- If you need to talk to a database or a remote service to perform the validation,\nyou need to create an async validator:\n    ```\n    validate: {\n    isAsync: true\n    validator: function(v, callback) {\n    // Do the validation, when the result is ready, call the callback\n    callback(isValid);\n    }\n    }\n    ```\n- Other useful SchemaType properties:\n    - Strings: lowercase, uppercase, trim\n    - All types: get, set (to define a custom getter/setter)\n        ```\n        price: {\n        type: Number,\n        get: v =\u003e Math.round(v),\n        set: v =\u003e Math.round(v)\n        }\n        ```\n\n----------\n# Mongoose: Modelling Relationships between Connected Data\n- To model relationships between connected data, we can either reference a\ndocument or embed it in another document.\n\n- When referencing a document, there is really no relationship between these two\ndocuments. So, it is possible to reference a non-existing document.\n\n- Referencing documents (normalization) is a good approach when you want to\nenforce data consistency. Because there will be a single instance of an object in\nthe database. But this approach has a negative impact on the performance of\nyour queries because in MongoDB we cannot JOIN documents as we do in\nrelational databases. So, to get a complete representation of a document with its\nrelated documents, we need to send multiple queries to the database.\n\n- Embedding documents (denormalization) solves this issue. We can read a\ncomplete representation of a document with a single query. All the necessary\ndata is embedded in one document and its children. But this also means we’ll\nhave multiple copies of data in different places. While storage is not an issue\nthese days, having multiple copies means changes made to the original\ndocument may not propagate to all copies. If the database server dies during an\nupdate, some documents will be inconsistent. For every business, for every\nproblem, you need to ask this question: “can we tolerate data being inconsistent\nfor a short period of time?” If not, you’ll have to use references. But again, this\nmeans that your queries will be slower.\n    - Referencing a document\n        ```\n        const courseSchema = new mongoose.Schema({\n        author: {\n        type: mongoose.Schema.Types.ObjectId,\n        ref: ‘Author’\n        }\n        })\n        ```\n    - Referencing a document\n        ```\n        const courseSchema = new mongoose.Schema({\n        author: {\n        type: new mongoose.Schema({\n        name: String,\n        bio: String\n        })}\n        })\n        ```\n- Embedded documents don’t have a save method. They can only be saved in the\ncontext of their parent.\n    -  Updating an embedded document\n        ```\n        const course = await Course.findById(courseId);\n        course.author.name = ‘New Name’;\n        course.save();\n        ```\n- We don’t have transactions in MongoDB. To implement transactions, we use a\npattern called “Two Phase Commit”. If you don’t want to manually implement this\npattern, use the ```Fawn NPM package```:\n    - Implementing transactions using Fawn\n        ```\n        try {\n        await new Fawn.Task()\n        .save(‘rentals’, newRental)\n        .update(‘movies’, { _id: movie._id }, { $inc: numberInStock: -1 }})\n        .run();\n        }\n        catch (ex) {\n        // At this point, all operations are automatically rolled back\n        }\n        ```\n- ObjectIDs are generated by MongoDB driver and are used to uniquely identify a\ndocument. They consist of 12 bytes:\n    - 4 bytes: timestamp\n    - 3 bytes: machine identifier\n    - 2 bytes: process identifier\n    - 3 byes: counter\n- ObjectIDs are almost unique. In theory, there is a chance for two ObjectIDs to be\nequal but the odds are very low (1/16,000,000) for most real-world applications.\n    - Validating ObjectIDs\n        ```\n         mongoose.Types.ObjectID.isValid(id);\n         ```\n- To validate ObjectIDs using joi, ```use joi-objectid NPM package```.\n\n\n----\n\n# Authentication and Authorization\n- Authentication is the process of determining if the user is who he/she claims to\nbe. It involves validating their email/password.\n- Authorization is the process of determining if the user has permission to perform\na given operation.\n- To hash passwords, use ```bcrypt```:\n    - Hashing passwords\n        ```\n        const salt = await bcrypt.genSalt(10);\n        const hashed = await bcrypt.hash(‘1234’, salt);\n        ```\n    - Validating passwords\n        ```\n        const isValid = await bcrypt.compare(‘1234’, hashed);\n        ```\n- A JSON Web Token (JWT) is a JSON object encoded as a long string. We use\nthem to identify users. It’s similar to a passport or driver’s license. It includes a\nfew public properties about a user in its payload. These properties cannot be\ntampered because doing so requires re-generating the digital signature.\n\n- When the user logs in, we generate a JWT on the server and return it to the\nclient. We store this token on the client and send it to the server every time we\nneed to call an API endpoint that is only accessible to authenticated users.\n\n- To generate JSON Web Tokens in an Express app use jsonwebtoken package.\n    - Generating a JWT\n        ```\n        const jwt = require(‘jsonwebtoken’);\n        const token = jwt.sign({ _id: user._id}, ‘privateKey’);\n        ```\n- Never store private keys and other secrets in your codebase. Store them in\nenvironment variables. Use the config package to read application settings\nstored in environment variables.\n\n- When appropriate, encapsulate logic in Mongoose models:\n    - Adding a method to a Mongoose model\n        ```\n        userSchema.methods.generateAuthToken = function() {\n        }\n        const token = user.generateAuthToken();\n        ```\n- Implement authorization using a middleware function. Return a ```401 error\n(unauthorized)``` if the client doesn’t send a valid token. ```Return 403 (forbidden)``` if\nthe user provided a valid token but is not allowed to perform the given operation.\n- You don’t need to implement logging out on the server. Implement it on the client\nby simply removing the JWT from the client.\n- Do not store a JWT in plain text in a database. This is similar to storing users’\npassports or drivers license in a room. Anyone who has access to that room can\nsteal these passports. Store JWTs on the client. If you have a strong reason for\nstoring them on the server, make sure to encrypt them before storing them in a\ndatabase.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frohan220217%2Fnodejs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frohan220217%2Fnodejs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frohan220217%2Fnodejs/lists"}