{"componentChunkName":"component---src-templates-post-js","path":"/post/node-is-simple-part-2","result":{"data":{"contentfulHero":{"coverImage":{"file":{"url":"//images.ctfassets.net/xmu5vdhtphau/1jqMTE2RJBiMLIcZAnu6It/5495c6ec7df10a55768df442e73fe4b2/home-hero-min.jpg","fileName":"home-hero-min.jpg"}}}},"pageContext":{"post":{"id":"b3d09618-2070-534d-9b38-0e83af866296","slug":"node-is-simple-part-2","title":"Node Is Simple — Part 2","createdAt":"Jul 15, 2020","tweetText":null,"type":"blog","video":null,"podcast":null,"categories":[{"id":"50768c9e-fc69-55ce-8a68-88617e5bcfbd","name":"How To","slug":"how-to"},{"id":"a397ebc3-492b-5568-b45d-6d4aa9722be7","name":"Tutorials","slug":"tutorials"}],"image":{"file":{"url":"//images.ctfassets.net/xmu5vdhtphau/H0hK6NW9d5IUfT0boXBBc/b7b2052395c92ae841256065a5566286/node_is_simple.png","fileName":"node_is_simple.png"}},"author":{"name":"Nipuna Weerasekara","bio":{"childMarkdownRemark":{"html":"<p>Part time web developer, full time dreamer… Find me @ <a href=\"https://niweera.gq\">https://niweera.gq</a></p>"}},"avatar":{"file":{"fileName":"1_cuJOF_sqBLbMA69vCFMqEQ.jpeg","url":"//images.ctfassets.net/xmu5vdhtphau/4iEstuN4qOq6h1vKjwpPRW/413c90f5bfa0c51170b560407e31c7c6/1_cuJOF_sqBLbMA69vCFMqEQ.jpeg"}}},"bodyContent":{"childMarkdownRemark":{"html":"<p><strong><em>tl;dr</em></strong> — <em>This is the second article of the</em> <strong><em>Node is Simple</em></strong> <em>article series. In this article series, I will be discussing how to create a simple and secure NodeJS, Express, MongoDB web application.</em></p>\n<p>Hello, my friends, this is part two of <strong>Node is Simple</strong> article series, where I will be discussing how to add MongoDB to your web application. If you haven’t read my first article you can read it from here: <a href=\"https://node.dev/post/node-is-simple-part-1\">Node is Simple - Part 1</a></p>\n<hr>\n<h2>So what is <a href=\"https://www.mongodb.com/\">MongoDB</a>?</h2>\n<p>If you haven’t heard of MongoDB that is news to me. It is the most popular database for modern web applications. (Yeah, yeah, <a href=\"https://firebase.google.com/\">Firebase</a>, <a href=\"https://firebase.google.com/docs/firestore\">Firestore</a> are there too.) MongoDB is a NoSQL database where it has documents as the atomic data structure and a collection of documents is a <strong>Collection.</strong> With these documents and collections, we can store data as we want.</p>\n<pre><code>{     \n \"\\_id\": \"5cf0029caff5056591b0ce7d\",     \n \"firstname\": \"Jane\",     \n \"lastname\": \"Wu\",     \n \"address\": {       \n     \"street\": \"1 Circle Rd\",       \n     \"city\": \"Los Angeles\",       \n     \"state\": \"CA\",       \n     \"zip\": \"90404\"     \n },     \n \"hobbies\": \\[\"surfing\", \"coding\"\\]   \n}\n</code></pre>\n<p>This is how a simple document is constructed in MongoDB. For our tutorial, we will use <a href=\"https://www.mongodb.com/cloud/atlas\">MongoDB Cloud Atlas</a> which is a MongoDB server as a service platform. I am not going to explain how to create an Atlas account and set up a database since it is really easy and the following is a really good reference.</p>\n<p><a href=\"https://towardsdatascience.com/getting-started-with-mongodb-atlas-overview-and-tutorial-7a1d58222521\">Getting Started with MongoDB Atlas: Overview and Tutorial</a></p>\n<p>After creating the MongoDB account and set up the database obtain the MongoDB URI which looks like this.</p>\n<pre><code>**_mongodb+srv://your\\_user\\_name:your\\_password@cluster0-v6q0g.mongodb.net/database\\_name_**\n</code></pre>\n<p>You can specify the following with the URI.</p>\n<p><em>your\\</em>user_name:_ The username of the MongoDB database</p>\n<p><em>your\\</em>password:_ The password for the MongoDB database</p>\n<p><em>database\\</em>name:_ The MongoDB database name</p>\n<p>Now that you have the MongoDB URI, you can use <a href=\"https://www.mongodb.com/products/compass\">MongoDB Compass</a> to view the database and create new collections.</p>\n<h2>Now let’s move on to the coding, shall we?</h2>\n<p>First of all, let me tell you something awesome about linting. To catch errors in your code, before running any tests, it is vital to do linting. In linting, tools like ESLint, look at your code and displays warnings and errors about your code. So let’s set up ESLint in your development environment.</p>\n<ol>\n<li>Setting up ESLint in VSCode</li>\n</ol>\n<p>This is a good reference to setting up ESLint in VSCode: <a href=\"https://www.digitalocean.com/community/tutorials/linting-and-formatting-with-eslint-in-vs-code\">Linting and Formatting with ESLint in VS Code</a></p>\n<ol start=\"2\">\n<li>Setting up <a href=\"https://www.npmjs.com/package/eslint\">ESLint</a> in WebStorm</li>\n</ol>\n<p>First, install ESLint in your project path.</p>\n<pre><code>$ npm install eslint --save-dev\n</code></pre>\n<p>There are several ESLint configurations to use. Let’s create <em>.eslintrc.json</em> file in the project root folder and specify the configurations.</p>\n<pre><code>{\n  \"env\": {\n    \"browser\": true,\n    \"commonjs\": true,\n    \"es6\": true,\n    \"node\": true\n  },\n  \"extends\": [\"eslint:recommended\"],\n  \"globals\": {\n    \"Atomics\": \"readonly\",\n    \"SharedArrayBuffer\": \"readonly\"\n  },\n  \"parserOptions\": {\n    \"ecmaVersion\": 2018\n  },\n  \"rules\": {}\n}\n</code></pre>\n<figcaption>_.eslintrc.json file (The configuration file for ESLint)_</figcaption>\n<p>After that go to settings in WebStorm and then select <em>Manual ESLint configuration</em>.</p>\n<p><img src=\"//images.ctfassets.net/xmu5vdhtphau/5F4OK4WRvLzo5MSP0KORs1/3e25487a9cd93709f0dc337fc3e1500f/1.png\" alt=\"1\"></p>\n<figcaption>ESLint configuration settings on WebStorm</figcaption>\n<p>Then click <em>OK</em> and done and dusted.</p>\n<h2>Show me the Code!!!</h2>\n<p>Alright, alright, let’s move on to the real deal. Now we are going to create a <a href=\"https://mongoosejs.com/\">Mongoose</a> reference for the MongoDB database and create some models. Mongoose is the Object Document Model for the MongoDB in NodeJS environment. It is really easy to use and the <a href=\"https://mongoosejs.com/docs/guide.html\">documentation</a> is really good. Let me tell you a super-secret. Read the documentation, always read the documentation. Documentation is your best friend. 🤣</p>\n<p>So first let's install the mongoose package inside the project folder.</p>\n<pre><code>$ npm install mongoose --save\n</code></pre>\n<p>Now let’s create the database connection file <em>index.js</em> in <em>/database</em> folder.</p>\n<pre><code>const mongoose = require(\"mongoose\");\nconst config = require(\"../config\");\nconst dbPath = config.MONGO_URI;\nconst chalk = require(\"chalk\");\n\nmongoose\n  .connect(dbPath, {\n    useNewUrlParser: true,\n    useUnifiedTopology: true,\n    useCreateIndex: true,\n    useFindAndModify: false\n  })\n  .then(() => {\n    console.log(chalk.yellow(\"[!] Successfully connected to the database\"));\n  })\n  .catch(err => {\n    console.log(chalk.red(err.message));\n  });\n\nconst db = mongoose.connection;\n\ndb.on(\"error\", () => {\n  console.log(chalk.red(\"[-] Error occurred from the database\"));\n});\n\ndb.once(\"open\", () => {\n  console.log(\n    chalk.yellow(\"[!] Successfully opened connection to the database\")\n  );\n});\n\nmodule.exports = mongoose;\n</code></pre>\n<figcaption>/database/index.js file (Contains MongoDB configurations)</figcaption>\n<p>Now let’s update the /<em>config/index.js</em> file.</p>\n<pre><code>const fs = require(\"fs\");\n\nconst SERVER_CERT = fs.readFileSync(__dirname + \"/server.cert\", \"utf8\");\nconst SERVER_KEY = fs.readFileSync(__dirname + \"/server.key\", \"utf8\");\n\nmodule.exports = {\n  SERVER_CERT,\n  SERVER_KEY,\n  HTTP_PORT: 8080,\n  HTTPS_PORT: 8081,\n  MONGO_URI:\n    \"mongodb+srv://your_user_name:your_password@cluster0-v6q0g.mongodb.net/students\"\n};\n</code></pre>\n<figcaption>/config/index.js file (Contains configurations of the project)</figcaption>\n<p>Remember to change the MONGO_URI according to the one you obtained from MongoDB Cloud Atlas instance.</p>\n<p>Now let’s create a simple mongoose model. Create <em>index.js</em> inside <em>/models</em> folder.</p>\n<pre><code>const mongoose = require(\"../database\");\nconst Schema = mongoose.Schema;\n\nconst studentSchema = new Schema(\n  {\n    name: { type: mongoose.SchemaTypes.String },\n    city: { type: mongoose.SchemaTypes.String }\n  },\n  { strict: true, timestamps: true }\n);\n\nconst collectionName = \"student\";\n\nconst Student = mongoose.model(collectionName, studentSchema, collectionName);\n\nmodule.exports = {\n  Student\n};\n</code></pre>\n<figcaption>/models/index.js file (Contains Mongoose model schemas)</figcaption>\n<p>As simple as that. Now let’s create a simple service to create a student using the endpoint. Create <em>index.js</em> file inside <em>/services</em> folder.</p>\n<pre><code>const { Student } = require(\"../models\");\n\nmodule.exports = class StudentService {\n  async registerStudent(data) {\n    const { name, city } = data;\n\n    const new_student = new Student({\n      name,\n      city\n    });\n\n    const response = await new_student.save();\n    const res = response.toJSON();\n    delete res.__v;\n    return res;\n  }\n};\n</code></pre>\n<figcaption>/services/index.js file</figcaption>\n<p>Simple right? Now let’s use this service inside a controller. Remember our controller, we created in the first article. Let’s update it.</p>\n<pre><code>const router = require(\"express\").Router();\nconst asyncWrapper = require(\"../utilities/async-wrapper\");\nconst StudentService = require(\"../services\");\nconst studentService = new StudentService();\n\n/** @route  GET /\n *  @desc   Root endpoint\n *  @access Public\n */\nrouter.get(\n  \"/\",\n  asyncWrapper(async (req, res) => {\n    res.send({\n      message: \"Hello World!\",\n      status: 200\n    });\n  })\n);\n\n/** @route  POST /register\n *  @desc   Register a student\n *  @access Public\n */\nrouter.post(\n  \"/register\",\n  asyncWrapper(async (req, res) => {\n    const response = await studentService.registerStudent(req.body);\n    res.send(response);\n  })\n);\n\nmodule.exports = router;\n</code></pre>\n<figcaption>/controllers/index.js file (Contains Express Router to handle requests)</figcaption>\n<p>It’s not over yet. If you run this application as of now and send a POST request to the <em>/register</em> endpoint, it would just return a big error message. It is because our application still doesn’t know how to parse a JSON payload. It would just complain that <em>req.body</em> is undefined. So let’s teach how to parse a JSON payload to our web application. It is not much but it’s honest work. We have to use a simple Express middleware called <a href=\"https://www.npmjs.com/package/body-parser\">Body-Parser</a> for this situation. Now let’s set up this.</p>\n<p>First, install the following packages inside the project folder.</p>\n<pre><code>$ npm install body-parser helmet --save\n</code></pre>\n<p>Create the file <em>common.js</em> inside <em>/middleware</em> folder.</p>\n<pre><code>const bodyParser = require(\"body-parser\");\nconst helmet = require(\"helmet\");\n\nmodule.exports = app => {\n  app.use(bodyParser.json());\n  app.use(helmet());\n};\n</code></pre>\n<figcaption>/middleware/common.js file (Contains all the common middleware for the Express app)</figcaption>\n<p><a href=\"http://expressjs.com/en/resources/middleware/body-parser.html\">Body-Parser</a> is the middleware which parses the body payload. And <a href=\"https://www.npmjs.com/package/helmet\">Helmet</a> is there to secure your web application by setting various security HTTP headers.</p>\n<p>After that let’s export our middleware as a combined middleware. Now if we want to add new middleware all we have to do is update the <em>common.js</em> file. Create <em>index.js</em> file inside <em>/middleware</em> folder.</p>\n<pre><code>const CommonMiddleware = require(\"./common\");\n\nconst Middleware = app => {\n  CommonMiddleware(app);\n};\n\nmodule.exports = Middleware;\n</code></pre>\n<figcaption>/middleware/index.js file (Exports all the common middleware)</figcaption>\n<p>We are not done yet. Now we have to include this main middleware file inside the <em>index.js</em> root file. Remember we created the <em>index.js</em> file inside the project root folder. Let’s update it.</p>\n<pre><code>const express = require(\"express\");\nconst chalk = require(\"chalk\");\nconst http = require(\"http\");\nconst https = require(\"https\");\nconst config = require(\"./config\");\n\nconst HTTP_PORT = config.HTTP_PORT;\nconst HTTPS_PORT = config.HTTPS_PORT;\nconst SERVER_CERT = config.SERVER_CERT;\nconst SERVER_KEY = config.SERVER_KEY;\n\nconst app = express();\nconst Middleware = require(\"./middleware\");\nconst MainController = require(\"./controllers\");\n\nMiddleware(app);\napp.use(\"\", MainController);\napp.set(\"port\", HTTPS_PORT);\n\n/**\n * Create HTTPS Server\n */\n\nconst server = https.createServer(\n  {\n    key: SERVER_KEY,\n    cert: SERVER_CERT\n  },\n  app\n);\n\nconst onError = error => {\n  if (error.syscall !== \"listen\") {\n    throw error;\n  }\n\n  const bind =\n    typeof HTTPS_PORT === \"string\"\n      ? \"Pipe \" + HTTPS_PORT\n      : \"Port \" + HTTPS_PORT;\n\n  switch (error.code) {\n    case \"EACCES\":\n      console.error(chalk.red(`[-] ${bind} requires elevated privileges`));\n      process.exit(1);\n      break;\n    case \"EADDRINUSE\":\n      console.error(chalk.red(`[-] ${bind} is already in use`));\n      process.exit(1);\n      break;\n    default:\n      throw error;\n  }\n};\n\nconst onListening = () => {\n  const addr = server.address();\n  const bind = typeof addr === \"string\" ? `pipe ${addr}` : `port ${addr.port}`;\n  console.log(chalk.yellow(`[!] Listening on HTTPS ${bind}`));\n};\n\nserver.listen(HTTPS_PORT);\nserver.on(\"error\", onError);\nserver.on(\"listening\", onListening);\n\n/**\n * Create HTTP Server (HTTP requests will be 301 redirected to HTTPS)\n */\nhttp\n  .createServer((req, res) => {\n    res.writeHead(301, {\n      Location:\n        \"https://\" +\n        req.headers[\"host\"].replace(\n          HTTP_PORT.toString(),\n          HTTPS_PORT.toString()\n        ) +\n        req.url\n    });\n    res.end();\n  })\n  .listen(HTTP_PORT)\n  .on(\"error\", onError)\n  .on(\"listening\", () =>\n    console.log(chalk.yellow(`[!] Listening on HTTP port ${HTTP_PORT}`))\n  );\n\nmodule.exports = app;\n</code></pre>\n<figcaption>/index.js file (Contains the Express app configuration)</figcaption>\n<p>Well done people, now we have completed setting up MongoDB connection and the model. So how do we test this? It is so simple, we just have to use a super easy tool called <a href=\"https://www.postman.com/\">Postman</a>.</p>\n<h2>Testing API endpoints with Postman</h2>\n<p>I hope you all know what Postman does. (Not the one that delivers letters ofc.) Install Postman and fire it up.</p>\n<p><img src=\"//images.ctfassets.net/xmu5vdhtphau/ZGIz9cvXhxHGF1WtHq4LJ/63d6a71a9b3a2ec89f72e3f1c18a9af1/2.jpeg\" alt=\"2\"><img src=\"//images.ctfassets.net/xmu5vdhtphau/7zNST0cSgnmnwVk4Jn6Man/a9e0f9ddae9a43383613c8118a6b9398/2.jpeg\" alt=\"2\"></p>\n<figcaption>Figure 1: Postman Settings</figcaption>\n<p>As in figure 1, change the settings for SSL certificate validation. And set it to off. Since we only have a self-signed SSL certificate. (Remember tutorial one.) After that, we are ready to go.</p>\n<p><img src=\"//images.ctfassets.net/xmu5vdhtphau/2CgEc5YjKwYItNch6N3Wmo/32e7d00851dba90eb11fa609cdcd6ef5/3.png\" alt=\"3\"></p>\n<figcaption>Figure 2: Request creation in Postman</figcaption>\n<p>As in figure 2, create your JSON body request. Add your name and city. Then click Send.</p>\n<p><img src=\"//images.ctfassets.net/xmu5vdhtphau/7wa5ISuyFy6NzFWWnfaoBV/f088c7699a69aca595464143fb629f57/4.png\" alt=\"4\"></p>\n<figcaption>Figure 3: Response to the request</figcaption>\n<p>If everything goes as it should, you’ll see this response. If you see this response, voila, everything works correctly. Now let’s take a look at MongoDB Compass.</p>\n<p><img src=\"//images.ctfassets.net/xmu5vdhtphau/6JQEbHhxzEzr5l06wDPPdp/8f3e7f731a6f8b8ec212f9763c3ac1a1/5.png\" alt=\"5\"></p>\n<figcaption>Figure 4: MongoDB Compass view</figcaption>\n<p>As in figure 3, you'll see how it shows in the database. Here, the MongoDB database is “<em>students”</em> and the collection is “<em>student”</em> and the document is the one that is showed in the view.</p>\n<p>Now that was easy right? So that’s it for this tutorial. In the coming tutorial, I’ll add some more CRUD operations to give you more details on working with MongoDB. All the code is saved in the GitHub repo and matched with the commit message. Look for the commit message “Tutorial 2 checkpoint”.</p>\n<p><a href=\"https://github.com/Niweera/node-is-simple\">Niweera/node-is-simple</a></p>\n<p>Until we meet again, happy coding…</p>"}}}}}}