{"id":22814514,"url":"https://github.com/aditya43/complete-nodejs","last_synced_at":"2026-04-10T14:37:49.627Z","repository":{"id":114669804,"uuid":"219141338","full_name":"aditya43/complete-nodejs","owner":"aditya43","description":":books: NodeJS - Express, Mongo, Sequelize, Sequelize-CLI, Mongoose, GraphQL, Websockets, Socket.io, REST APIs, ReactJS Social Network, Winston, Morgan, Helmet, Compression, Validators, SSL/TLS, Micro Services Architecture \u0026 lot more.","archived":false,"fork":false,"pushed_at":"2020-08-20T17:05:59.000Z","size":4526,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-06T02:51:15.448Z","etag":null,"topics":["axios","express","graphql","helmet","micro-services-architecture","mongodb","mongoose","morgan-middleware","mysql","nodejs","react","redux","rest-api","sequelize","socket-io","websocket","winston-logger"],"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/aditya43.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":"2019-11-02T11:00:37.000Z","updated_at":"2022-04-17T14:10:03.000Z","dependencies_parsed_at":null,"dependency_job_id":"fd3d4672-81f9-4ebf-8a5c-0c78c993e68e","html_url":"https://github.com/aditya43/complete-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/aditya43%2Fcomplete-nodejs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aditya43%2Fcomplete-nodejs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aditya43%2Fcomplete-nodejs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aditya43%2Fcomplete-nodejs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aditya43","download_url":"https://codeload.github.com/aditya43/complete-nodejs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246385415,"owners_count":20768672,"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":["axios","express","graphql","helmet","micro-services-architecture","mongodb","mongoose","morgan-middleware","mysql","nodejs","react","redux","rest-api","sequelize","socket-io","websocket","winston-logger"],"created_at":"2024-12-12T13:09:11.247Z","updated_at":"2025-12-30T19:26:29.428Z","avatar_url":"https://github.com/aditya43.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## About This Project\nNodeJS - Express, Mongo, Sequelize, Sequelize-CLI, Mongoose, GraphQL, Websockets, Socket.io, REST APIs, ReactJS Social Network, Winston, Morgan, Helmet, Compression, Validators, SSL/TLS, Micro Services Architecture \u0026 lot more.\nMy personal notes and apps.\n\n## Author\nAditya Hajare ([Linkedin](https://in.linkedin.com/in/aditya-hajare)).\n\n## Current Status\nWIP (Work In Progress)!\n\n## Deployed On Heroku\n- Weather App: [https://aditya-hajare-weather-app.herokuapp.com](https://aditya-hajare-weather-app.herokuapp.com/)\n- Tasks Manager App: [https://aditya-hajare-nodejs-task-app.herokuapp.com](https://aditya-hajare-nodejs-task-app.herokuapp.com/)\n- Socket.io Chat App: [https://aditya-hajare-socket-chat-app.herokuapp.com](https://aditya-hajare-socket-chat-app.herokuapp.com/)\n\n## License\nOpen-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT).\n\n-----------------------\n\n## Important Notes\n- [Options Request](#options-request)\n- [Debugging Using Node Debugger](#debugging-using-node-debugger)\n- [Call Stack](#call-stack)\n- [Event Loop](#event-loop)\n- [Deploying Weather App On Heroku](#deploying-weather-app-on-heroku)\n- [JEST - Things To Know](#jest---things-to-know)\n- [WebSockets Protocol](#websockets-protocol)\n- [Mongoose - Things To Know](#mongoose---things-to-know)\n- [Cookies](#cookies)\n- [Sessions](#sessions)\n- [Storing Sessions In MongoDB](#storing-sessions-in-mongodb)\n- [Allow CORS For REST APIs](#allow-cors-for-rest-apis)\n- [GraphQL](#graphql)\n- [GraphQL Query Variables](#graphql-query-variables)\n\n### Options Request\n- Browser sends a `OPTIONS` request before it sends `POST, PATCH, PUT, DELETE` etc.. requests.\n- You may typically get `405 (Method Not Allowed)` error.\n- `Express GraphQL` automatically declines anything which is not a `POST` or `GET` request. So the `OPTIONS` request is denied.\n- To fix this, install `cors` by `npm i cors --save` and use it as below:\n    ```\n        const cors = require('cors');\n\n        const app = express();\n\n        app.options('*', cors());\n        app.use(cors());\n    ```\n\n### Debugging Using Node Debugger\n- Add `debugger` keyword wherever you want to stop your program execution and begin debugging. For e.g.:\n    ```\n        //app.js\n\n        console.log('Hello World');\n        debugger; // This is where program execution will stop and you can start debugging.\n        console.log('Hello World 1');\n    ```\n- Run `app.js` above with `inspect` command as below:\n    ```\n        // In terminal\n\n        node inspect app.js\n    ```\n- Open `Google Chrome Browser` and enter following URL:\n    ```\n        chrome://inspect/#devices\n    ```\n- You should see your current Node app under `Remote Target`. Click on `inspect` link.\n- On left hand side, click on `Add folder to workspace`.\n\n### Call Stack\n- `Call Stack` is a simple data structure provided by the `V8 JavaScript Engine`.\n- It's job is to track the execution of our program and it does that by keeping track of all of the functions that are currently running.\n- The `Call Stack` data structure uses `FILO (First In Last Out)` to track the execution of our program.\n\n### Event Loop\n- `Event Loop` looks at 2 things:\n    * It looks at the `Call Stack`.\n    * And it looks at the `Callback Queue`.\n- If the `Call Stack` is empty, it's going the run the items from `Callback Queue`.\n- The `Event Loop` actually have to wait until `Call Stack` is empty before it could run items from `Callback Queue`.\n- None of our `Asynchronous Functions` are going to run unless `main() Function` is done executing.\n- Node uses other threads (`C++`) behind the scene for `Node APIs`.\n\n### Deploying Weather App On Heroku\n- Go to local Git repository root directory or project root directory.\n- Execute following command:\n    ```\n        heroku create [SUB_DOMAIN]\n\n        // For e.g.\n        heroku create aditya-hajare-weather-app\n    ```\n- **NOTE:** `aditya-hajare-weather-app` is the sub-domain and it must be unique across `Heroku`.\n- From your project root, execute following command:\n    ```\n        heroku git:remote -a [APP_NAME]\n\n        // For e.g.\n        heroku git:remote -a aditya-hajare-weather-app\n    ```\n- Execute `git remote` to list remote branches. You should see something like below:\n    ```\n        heroku\n        origin\n    ```\n- **NOTE:** `heroku` is listed under `remotes`.\n- To Deploy:\n    * To deploy master branch to Heroku:\n        ```\n            git push heroku master\n        ```\n    * To deploy contents of specific directory to Heroku root:\n        ```\n            git subtree push --prefix [DIRECTORY_NAME] heroku master\n\n            // For e.g.\n            git subtree push --prefix 10-Weather-App-Express heroku master\n        ```\n- After deployment, you can visit your app in browser. For e.g.\n    ```\n        // Weather App on Heroku:\n        https://aditya-hajare-weather-app.herokuapp.com/\n    ```\n- **Heroku Environment Variables:**\n    * To set environment variable in Heroku environment:\n        ```\n            heroku config:set KEY=VALUE\n        ```\n    * To unset/remove environment variable in Heroku environment:\n        ```\n            heroku config:unset KEY\n        ```\n\n### JEST - Things To Know\n- `.toBe()` uses `===` operator to compare values. i.e.\n    * `1 === 1`: True\n    * `{} === {}`: False. That is because when 2 objects are compared with `===` they are not equal as they are stored in different memory locations.\n- To compare objects in JEST, use `.toEqual()`.\n\n### WebSockets Protocol\n- `WebSocket` is a separate protocol from `HTTP`.\n- `WebSockets` allow for `Full Duplex Communication`.\n- `Full Duplex Communication` is just a fancy term for `Bi-Directional Communication`.\n- With `WebSockets` we have a `Persistent Connection` between client and server.\n- `Socket.io` needs to be called with a raw `HTTP Server`.\n- Event emitters:\n    * `socket.emit('EVENT_NAME', { dataObject })`: Only to self/specific client.\n    * `socket.broadcast.emit('EVENT_NAME', { dataObject })`: All other clients except self.\n    * `io.emit('EVENT_NAME', { dataObject })`: All clients including self.\n- Event emitters in `Rooms`:\n    * `io.to(room).emit('EVENT_NAME', { dataObject })`: Emits an events to everybody in a specific room.\n    * `socket.broadcast.to(room).emit('EVENT_NAME', { dataObject })`: Emits an events to everybody in a specific room except self/specific client.\n\n### Mongoose - Things To Know\n- While defining methods on `Schema`, avoid `Arrow Functions`. Instead opt out for `function()`.\n    * **Reason:** `this` is not available in `Arrow Functions`.\n    * Refer to following examples:\n        ```\n            17-Shop-App-Mongoose/models/user.js\n            11-Tasks-Manager-App/src/models/user.js\n            11-Tasks-Manager-App/src/models/task.js\n        ```\n    * For e.g.\n        ```\n            const mongoose = require('mongoose');\n\n            const userSchema = mongoose.Schema({\n                name: {\n                    type: String,\n                    required: true\n                },\n                email: {\n                    type: String,\n                    required: true\n                }\n            });\n\n            userSchema.methods.helloWorld = function() { // Not using arrow function here!\n                // Code\n            };\n\n            module.exports = mongoose.model('User', userSchema);\n        ```\n\n### Cookies\n- Cookies which are not having `expiry` and `max-age` set, will get destroyed when browser is closed.\n- To set a cookie:\n    ```\n        exports.postLogin = async (req, res, next) =\u003e {\n            res.setHeader('Set-Cookie', 'isAuthenticated=true; HttpOnly');\n            res.send(req.body);\n        }\n    ```\n- To fetch value of `isAuthenticated` cookie:\n    ```\n        const value = req.get('Cookie')\n            .split(';')[1]\n            .trim()\n            .split('=')[1];\n    ```\n\n### Sessions\n- To use sessions in `Express`, install following plugin:\n    ```\n        npm i express-session --save\n    ```\n- Steps to initialize and use session:\n    * Initilize session in middleware in `app.js`:\n        ```\n            const session = require('session');\n\n            const app = express();\n\n            app.use(session({\n                secret: 'some secret string',\n                resave: false,\n                saveUninitialized: false\n            }));\n        ```\n    * Session will be available on `req.session`.\n    * To set a value in session:\n        ```\n            req.session.isLoggedIn = true;\n        ```\n    * To fetch a value from session:\n        ```\n            const loggedIn = req.session.isLoggedIn;\n        ```\n\n### Storing Sessions In MongoDB\n- Install following package:\n    ```\n        npm i connect-mongodb-session --save\n    ```\n- Setup `MongoDB Store`:\n    ```\n        const session = require('session');\n        const connectMongoDBSession = require('connect-mongodb-session');\n\n        const MongoDBStore = connectMongoDBSession(session);\n        const store = new MongoDBStore();\n\n        app.use(session({\n            secret: 'some secret string',\n            resave: false,\n            saveUninitialized: false,\n            store\n        }));\n    ```\n\n### Allow CORS For REST APIs\n- Method #1:\n    * Using express `cors` middleware package:\n        - Install `cors` npm package:\n            ```\n                npm i cors --save\n            ```\n        - Use it in `app.js`:\n            ```\n                const express = require('express');\n                const cors = require('cors'); // CORS\n                const bodyParser = require('body-parser');\n\n                const app = express();\n\n                app.use(bodyParser.json());\n                app.use(cors()); // CORS\n\n                app.listen(8080);\n            ```\n- Method #2:\n    * Manually setting headers (**NOTE:** May not work in most cases):\n        ```\n            const express = require('express');\n            const bodyParser = require('body-parser');\n\n            const app = express();\n\n            app.use(bodyParser.json());\n            app.use((req, res, next) =\u003e {\n                // CORS Middleware\n                res.setHeader('Access-Control-Allow-Origin', '*');\n                res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE');\n                res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n                next();\n            })\n\n            app.listen(8080);\n        ```\n\n### GraphQL\n- Uses `Typed Query Language`.\n- Single `POST` request endpoint. For e.g.\n    ```\n    POST    /graphql\n    ```\n- `POST Request Body` contains `Query Expression (to define the Data that should be returned)`.\n- **Operation Types:**\n    * `Query`: To retrieve data.\n    * `Mutation`: To manipulate data.\n    * `Subscription`: To set up realtime connection via `Websockets`.\n\n### GraphQL Query Variables\n- **Example #1**\n    * Query without using variables (**Non-Recommended Way**):\n        ```\n            const graphqlQuery = {\n                query: `\n                    {\n                        posts(page: ${page}) {\n                            posts {\n                                id\n                                title\n                                content\n                                imageUrl\n                                creator {\n                                    name\n                                    email\n                                }\n                                createdAt\n                                updatedAt\n                            }\n                            totalPosts\n                        }\n                    }\n                `\n            }\n        ```\n    * Query using explicit variables (**Recommended Way**):\n        ```\n            const graphqlQuery = {\n                query: `\n                    query FetchPosts($page: Int) {\n                        posts(page: $page) {\n                            posts {\n                                id\n                                title\n                                content\n                                imageUrl\n                                creator {\n                                    name\n                                    email\n                                }\n                                createdAt\n                                updatedAt\n                            }\n                            totalPosts\n                        }\n                    }\n                `,\n                variables: {\n                    page\n                }\n            };\n        ```\n- **Example #2**\n    * Query without using variables (**Non-Recommended Way**):\n        ```\n            const graphqlQuery = {\n                query: `\n                    mutation {\n                        updateStatus(status: \"${this.state.status}\") {\n                            status\n                        }\n                    }\n                `\n            };\n        ```\n    * Query using explicit variables (**Recommended Way**):\n        ```\n            const graphqlQuery = {\n                query: `\n                    mutation UpdateUserStatus ($userStatus: String) {\n                        updateStatus(status: $userStatus) {\n                            status\n                        }\n                    }\n                `,\n                variables: {\n                    userStatus: this.state.status\n                }\n            };\n        ```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faditya43%2Fcomplete-nodejs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faditya43%2Fcomplete-nodejs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faditya43%2Fcomplete-nodejs/lists"}