Node Projects - Task Manager API

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up everybody this is john from coding addict and welcome to the first node.js project video task manager api if you watched my node.js and express tutorial video this is the first project of the second part of the series now initially the idea for the second part was to make a big api but after careful consideration i decided to split it up in four or five smaller apps since that has worked really well in my react series and of course it goes without saying complete the small apps first and only then work on the big api since that way by the time we start working on the big api project you'll be at least familiar with all the building blocks of large api before we tour the app let me just mention a few things first my assumption is that you have watched the tutorial part since we'll right away dive into the database setup so if you're still iffy on things like modules and basic express route setup it's probably going to make a bit more sense to complete tutorial video first second even though the app might look basic remember that it's our first api and the goal is to get us familiar with persisting data on the database and only once we're comfortable with that then we can move on to more complex topics like advanced queries auth complex validation and multi-part error handling also during the project we're not going to work on the front end it's just there so you can see how our responses are consumed by the front-end app so essentially how the api is used in real life since that way at least in my opinion you get a bigger picture not just a postman results don't get me wrong postman is awesome and we'll definitely use it during the project but whenever i'll feel that it's necessary i'll also whip up the front end so you get the entire picture as far as the app we've got a task manager where we can create read delete and modify tasks and again let me repeat the whole deal is that all our data is on a database not in the local storage or in some random array on our server as far as the bare bones functionality it goes something like this where of course i can read all the tasks i can create a new one soon here i can say new task i submit and of course we do that by sending a post request then we have option of removing the task and if we want we can navigate to separate page where we get info only about that one specific task and if we want we can edit so in here i can go with old task and i edit the data and of course now i can go back to all the tasks and i can see that it is completed and the text is different as well and once we know what we're going to be building now let's get to work in order to follow along with the video you'll need a star project and you can get one at johnsmilk.com then the url is www johnsmilk.com look for the project more specifically node and express one and both of these links go to the same repo so just click on any of them and then just get hold of the repo in my case i think i'm gonna go with clone option so i'm back in my terminal i'll zoom in we're gonna go with cd desktop so i'll set it up on a desktop and then of course i go with git clone and then copy and paste the url and once you get the repo then let me showcase what you'll find inside so drag and drop and in here you'll find no tutorial that we worked on the express tutorial and of course the task manager and more specifically in the task manager you'll find the final folder so this is a complete source code however there's one gotcha that i want to talk about where you will need a database connection string in order to spin it up so don't just go there and then run npm install and then npm start and then get mad if the project doesn't start up so essentially in order for everything to work you need to set up dot env file and in there set up a variable by the name of uri and set it equal to connection string and of course i'm going to cover that later on in the videos so that's about final and as far as the starter if you watch the tutorial part this should look very familiar so essentially in the public one we have the front-end application again not something we're going to work on we're going to work on a back end but since i want to showcase how everything is going to look with the real app that's where you have there the public folder and as i said if you're interested in just html and css you can actually find the same exact project in my html and css course and then also we have git ignore so essentially in this file we say which files are going to be ignored by the source control and i'll talk about it a bit more when we're setting up the env file then we have app.js with straight up console log and then in the package.json you'll find all our dependencies which at the moment are dot env express and mongoose now of course in tutorial we only got familiar with express but as we progress we the project of course i'll cover the other two as well in order to have a smooth development process i also set up nodemon as a dev dependency and then the command to start up is npm start that should do it for the setup and i think now we're ready to start working on a project and once we're familiar with the setup let's kick things into gear and actually start working on a project the first thing that you need to do is to navigate to the starter folder again you're looking for the third project the task manager and then more specifically the star folder and i think the fastest way to navigate there is by just typing cd and then grab the star folder and drop it here and then once you're in the starter before you do anything make sure that you install all the packages and of course we do that by running npm install and then once all the packages are in place in order to spin up the nodemon we need to go with npm start unless of course you want to change it to a different command if that's the case then make the changes and then use that command instead so in my case i'll just wait a little bit i mean it shouldn't take too long there's not that many packages in there and then once i have all the packages in place then of course like i said we're going to go with npm start and if you see task manager in the console we are in good shape and now let's set up the most basic express server which essentially is just going to be listening for one route forward slash hello and it's going to be on port 3000. now if you want to jog your memory and test it out yourself just pause the video and resume once you're done if you don't want to do that just keep on watching the video and the way we set up the most basic express server is by setting up a variable by the name of express then we'll set it equal to require and that's going to be equal to our express package then we need to initialize it so we go with app and that is equal to express and we invoke it and then unlike the previous examples we'll actually set up a variable by the name of port and for time being we'll hard code this to 3 000 but eventually there's going to be more code and i'll talk about the reasoning later so for now just set up the variable and we'll be in good shape and here we need to go with amp.listen of course and first thing we pass in is the port and the second is the console.log so we go here with some kind of text and i'm going to go with server is listening on port and then of course we pass in the port value and i always like to add those three dots as well so i'll do it in this case and then i'll open up my console the moment i have server is listening on port 3000 which is just awesome so now let's also set up that one a lonely route so above the port i'm gonna go with my comment routes and then we'll just say app.get so this is going to be a get request now what is going to be the url well we'll go with forward slash and hello so that's going to be the path and then of course we have the callback function once the user hits the route and we're looking for rec and res so request and response and we simply want to go with reg.send and then we'll pass task manager and app so i'll save it here i'll navigate to the browser and i'm looking for port 3000 of course and then we'll go with hello and if we see task manager app displayed in a browser then of course we are off to the great start beautiful and once we have the bones in place next let's take a look at our application so we can decide what route eventually we're going to have and i can see that i'm getting all my tasks so there will definitely be a get request that gets me all my items now i can also create a new task so there will be a post request that can create a new task now we can also delete one so there will be a route for that and if we click on edit we open up a new page and in here we get info about specific route so there will be a get request that just gets me info about one single task and also we'll have the ability to edit so if i change the completed from true to false if i successfully edit that then if i go back to the tasks of course in here i don't see the check mark which means that i successfully added it to task and what that means is that there's also a route for the update and in summary our routes are going to look something like this where there will be a get request on api version one and then tasks so this will get all the tasks then there will be a post request on api version one tasks again the same url however the method is different so total different functionality in this case we'll create a new task and then we have get route with params so with the id of the task that gets us that single task and of course one for update and one for delete and since there's a lot to unpack over here i'll spend the next video on the reasons behind such api structure all right so let's go step by step and probably your first question is well why do we go here with forward slash api and then version one and essentially that is just a convention we need to understand that on the server we also might have different routes not just the routes for the api so for example you could be serving a index page here on a forward slash meaning there could be a nice index.html page that you're serving up over here and then also on the same server you have the api routes so convention is effectively just to signal that all of these are the api routes now as far as the version well as you're setting up the api eventually you might want to change some things so it's easier if you have this version because that way when you create a new one then you can just direct everybody to api and then version two three or whatever and while we're still on that same note why don't we navigate to a hacker news one the one that i showed you previously with algolia and you'll notice exactly the same setup more essentially they go with domain and then forward slash and then api and then version number one and that leads me to my next point where if you're ever in doubt or if you're just interested on different setups just check out the different apis there's tons of apis out there and you can just look for one then take a look at their setup and then decide if what they're doing makes sense to you then of course you can implement in your project if not then just move on to a different api and eventually you'll find a setup that makes the most sense to you after that you're probably wondering okay i understand the api high-end that version that kind of makes sense but why do we go here with get and then tasks then we have the post and the same tasks and then for get patch and delete we go to the tasks but then we're looking for the colon why isn't this written in a different way where we're just looking for a single task or something along those lines and to give you a short answer that is a convention but since there's more to it i want to actually cover that in a few videos so i want to set up the basic routes with just some simple responses then i want to open up the postman and do a little bit of setup over there and then right before we start setting up the database i actually want to spend one video on just talking about the convention and then lastly if you remember in tutorial we worked with put and now for the update we're using patch and i know that this might be a little bit frustrating to you but that's also going to be something that we will cover a bit later once we have already a working application because that way i believe that i can give you a solid example of the differences between the put and patch that's about it for the general route structure so now let's start implementing it not bad and bad i think we're good with the general structure so now let's start implementing it and i want to right away set up the router as well as the controllers and if you remember at the very end of the express tutorial i covered why is that necessary and essentially the short answer is that as our application grows bigger it's not going to be very sustainable if we'll just start dumping everything in the app.js and for temping i just want to create this one route now as far as the response it's just going to be a simple string that says hey here are all the items or something along those lines and then once we have that one in place then we'll add rest of them and then we'll test it out in postman so let's get cracking and i'm going to go with new folder so here will be all the controllers and in this case i'm going to be looking for tasks and i also want to set up a routes folder so in the routes folder we'll go with new file and same thing we're going to go with tasks js and then as far as the setup in the route we need to look for the express router so say const express and that is equal to require and then again we'll look for express and this should be a refresher because we did cover that at the end of the express tutorial so just to jog your memory if we go back to express tutorial and then more specifically we'll look for the final one the file 13 the router people shows a basic router example and essentially we have two options we can either go with router or get and then add all the controllers one by one or we can actually change them together where we go with router and then user route so this is going to be the main route in our case api version 1 and then tasks and then we chain get and post and i think i'm going to go with this setup so first let's start by setting up the router and that is equal to express and then router we invoke it and then eventually we'll import controllers but for now of course we don't have any so let's just leave that one blank and we'll go with router router then route like i said then forward slash and then i want to go with get method and for time being i'll just hard code the response over here so say wreck and rise and res dot and send and like i said we'll just start simply so say all items now let's save that one and then all the way in the bottom we want to go with module exports and that is equal to our router so now back in the app.js we want to import the router we want to import our tasks and we want to set up the middleware so in here let's just go with const and then routes and that is equal to require and then like i said we're going to be looking in the routes folder and then more specifically we're looking for tasks and then right after this hello and don't worry we'll change that one a little bit later for time being it can just stay the way it is we'll go with app.use and then of course what route are we looking for well we want to go with api then version one and then tasks so that's going to be that root route for the tasks router and then we just want to go with our routes and you know what let's just change the round my bad for some reason i went with routes let's just call it tasks i believe it's going to make a bit more sense and since we'll be sending json from our application for example when we're creating a new task and since i want to access that data in my routes what we need to do of course is get middleware that is built into express and that middleware is express json so above the routes we'll go here and i'll try to spell this correctly since that is always an issue hopefully this is correct middleware and then we'll just go with app.use and eventually we'll set up the static one as well but since at the moment we have barely any routes i'm just gonna go with express and json if you remember if we don't use this then we won't have that data in rec.body so i'll save it here and i'll leave the comments just so we all are on the same page and before i test it out in the browser let me just double check so i'm using the middleware where i'm saying that i'm looking for api version one and then tasks and then i pass in my router my tasks router and then in the router effectively i have this root path which just matches whatever i pass over here so again i go with api version one and then tasks and then i set up a get route where i manually pass in my controller and here i just say res.send and i pass in a string of all items and looks about right so let me go here and we're going to go with localhost 3000 since it's a get request of course we can access it again api version one and then tasks and we should see a string of all items and if we do then of course we're heading in the right direction so the last thing that i want to do in this video is to first close my express tutorial one and then in the controllers we want to create a new file and we'll call this tasks.js and again just to jog your memory the whole deal why we're setting up separate routes and separate controllers because if i'll try to jam everything in app.js it's going to get messy pretty fast so what i want to do right now is take this logic and place it in a separate file because eventually of course there will be way more logic than just res dot send so i'm going to go to my controllers and effectively i want to create my function the controller function and i'm just going to go with const get all and then tasks and i'll set it up as an r function i'm looking for rec and res and functionality will be exactly the same whereas dot send and we're just gonna go with all and then items and then we're gonna go with module exports and since i'm gonna add more functions in here i'll right away export it as an object so say get all tasks that's when i'm exporting and then back in the routes of course i want to access it so i'll say here that i wanted the structure get all tasks from and of course we need to require it and in this case we're looking in the controllers so i'm going to go two levels up i'm looking for controllers and then more specifically task so instead of hard coding this value of course i'll just pass it in and i'll say get all tasks and if i go back to my url and if i can still see all items then of course we are in good shape and let me just test it out where i'll change this around and i'll say all items from from the file and then if we go back yep we still have the correct result and with this in place now we can set up the same basic structure for rest of the routes as well beautiful and in the same fashion let's set up rest of the controllers so we have the get one now i want to create one for the post one for get but that's going to be a single item and we also have one for patch and one for delete and pretty much in all of them the setup is going to be exactly the same as far as functionality i'll just send back and i'll say what the controller is doing since of course we haven't connected to the database or anything like that and i just need to come up with a name in my case i'm going to go with create task and again we have rack and res and then we want to copy and paste since i want to speed this up and i'll just say create task create task and why don't we change this one around and we'll say get all tasks now we want to copy and paste and we'll have three more we'll have one for getting the task so get task and here we'll say get single task then we'll have one for updating and that's exactly how we'll call it we'll say update task the same is going to be over here and then the last one of course will be delete and then task and you guessed it we also need to change the text and now of course we want to place that in the same object so let's go with create task then get task then we have update task and last one is delete task and then back in the routes of course we want to import them so say here create task get task then update task and delete one and now we just need to set up the routes if we take a look at the app.js these two the get and post are going to go to api version 1 and then tasks and then the rest of them are going to be wii d id params so same initial path but then we'll just add the forward slash and then id and that of course is where we're going to pass the id of the task so where i have the get request to get all the tasks i'll change that post and of course which controller are we going to use of course the create task one and then we can simply go to the next line and we'll go with router then route and like i said we'll go with forward slash and then id and then we're looking for get route and that will be equal to get the single task then we'll set up our patch and that will be equal to update task and then lastly we have delete one and now will be equal to delete task now since we know that we can only really test the single task and get all tasks because that's the default method the browser performs we'll stop over here and in the next video we'll spin up the postman to quickly test all of our routes because trust me you don't want to go any further without knowing that at least the basic setup works because you can set up whatever logic you have over here if there's a small bug and you cannot access these strings then you'll spend way more time later searching for that bug nice job and once we have the basic structure for all of our routes now let's test them out in a postman so i'm gonna head back to my desktop i'm looking for the postman and since in this case we'll spend way more time over here i also want to cover some configuration options so for starters i want to switch to a dark mode because i think you'll appreciate that more so if you want to do that as well just go to the cog and then you're looking for the settings here and then in the settings just look for themes and of course we have a dark theme as well so that's the first thing that i'm going to do then we want to create a collection now why would you want to do that well since we'll be setting up multiple routes and they'll reference the same application which is going to be easier as we create more and more applications and in order to create that collection we go here and click on creating the collection and for starters i just want to change the name so i'll click on these three dots over here and of course we're looking for rename and then i'm just gonna go with zero 3 and we'll call this task manager now if you're not happy with this name of course pick your own one and once i have the task manager then we want to start by creating a request so we create a new request it's going to be a get request and instead of typing all the time manually here local and then host and we're going to go with 3000 and then of course api version 1 and then tasks what we want to do is set up a global variable now there's multiple ways how we can do that you can actually set up the environment so think of this as a dev environment and then you can have production environment but in our case we'll just set up this local host and then 3000 api and version 1 simply as a variable and you can do it from here as you can see they even give you a suggestion and all that but i'm just going to go the long route where we click here on that eye and then notice i have already won for the url i have localhost 3000 and then i actually changed it later to forward slash api so now what i want to do i want to showcase how we can remove it so if i go over here and if i remove it and i set up a new one in this case again i'll call this url and then as far as this value well i'm just going to take this whole thing so i'm going to go with localhost and then 3000 and of course we're looking for api and if you want you can also include the tasks but in my case i'll stop right after the version one so let's copy that one again i'm setting this up as a global but you can set it up in the environment as well and then once we add that we should be able to right away access it so now of course we just need to save it and then in order to use it we need to go back and you know what i'll remove everything for now and if we go with these double curlies this is going to give us access to those variables and all the way in the bottom we have the url and of course as you can see it is global so in here i'm going to go with url i'll close it and then i'll go with forward slash and then tasks and once i save i should get back get all tasks and of course that means that our basic setup works and before we continue and do the same thing with the rest of tasks now of course we want to save it and not only want to save it we want to save it in our collection so let's click over here save as and let's give it a more meaningful name and in this case again i'll say get all tasks and of course we're looking for task manager so this is going to be saved in this collection and we simply click on save so if i take a look at my task manager now of course i have get all tasks where we use the global variable and we can successfully see our string and i'll close few of these tabs because it's getting quite busy and let's do the same thing for the rest of them so in this case i'm going to be testing the create one the one for the post that's why we need to change the method that's the first thing you want to do then we'll go with our url again we'll close it out forward slash and then tasks and remember now we want to send some data correct now we're not doing anything with that data on a server but just for the kicks why don't we send it i'm gonna go here with body then we're looking for the raw and of course we're not looking for text we're looking for json we just need to make sure that we use the correct syntax and in this case i'll say name and now we'll be equal to testing and we just click on send and if we can see create task we are in good shape now since i also want to test out whether my middleware is working i'm going to go back to my controllers i'm looking for create task and in here instead of just going with send we're going to go with json so now i'll be sending back the json and i'll pass in reg dot body so if you want of course you can kind of log it on a server but in my case i think it's gonna be faster if i just send back whatever i'm getting from the client so if we go back and if we change this around and we'll say here shake and bake and if we add a comma and then completed we set to true once we send that should be our response and of course the only thing that's left to do as far as the create route is go to save as and then we'll say create task save it and now let's continue again i'll close these ones just so it's not that busy and in this case i want to go with get route then we want to go here with the url again and of course we haven't set up the database so there's no real id but we can definitely test it out if we just go with tasks and then whatever gibberish so in this case i'm gonna go with hello so that's gonna be my id so we're not sending anything as far as data but we are using the params again if we take a look at the routes we can clearly see that we have forward slash and then id that is going to be our param and if we want to test it out where we have get task of course we have the request and the id is sitting in the params so in here i'll do the same thing i'll say json and we'll just say id and that one is equal to rec params and the id so if we save here and then go back and just use the get route and click send we have the key with the name of id and then the value is hello so if we'll change it around and if we'll say peter of course the value will be peter again same spiel we got save as and we'll name this update task or i'm sorry get single task my apologies get single task let's save it and then we have two more we have one for update and one for remove and in order to speed this up i don't think i'm going to do any testing anymore we simply want to open up a new route we want to go with patch in this case and again we're going with url and then forward slash tasks whatever value you want to pass in over here so i'm going to go with 1 2 3 send and of course i have update task beautiful let's save that one and we'll write here update and task and the last one of course is delete so let's close these two and again your request we're looking for delete method the url is going to be exactly the same and then we want to go with forward slash tasks and then any of the ids that we have already used since we'll change that later anyway and once we send the response should be delete task now if you don't want to go with save as you can simply click on command s that's going to be a shortcut and we go here with delete and then task and of course we save it in the same task manager and once we can clearly see that we can access all our routes correctly then we can move on to our next topic okay and once we're done with the postman before we start setting up our database let's quickly talk about our routes more specifically why we use such structure long story short it's because we're building a rest api and since these days the term api is used pretty much for everything let's just all agree that in our case since we're building a server essentially we want to create a http interface so the other apps most likely front-end ones can interact with our data that's how we view api in the scenario and when it comes to rest it stands for representational state transfer and arguably the most popular api design pattern and essentially it's a pattern that combines http verbs route paths and our resources aka data so effectively rest determines how the api looks like now let me emphasize something it's a pattern not a strictly enforced set of rules so nothing stops you from setting your own api in totally different manner in fact if you have used apis on your front-end apps you know that some of them have totally different structure i guess the best advice i can give you is this whatever pattern you decide on stick with it or in other words be consistent otherwise it's just going to be very confusing for your users and this is a common approach where you have the main list so that could be orders that could be customers that could be items whatever and of course in our case it is tasks and in order to get all the items we go with get method and then if we want to create one it's going to be the same endpoint but we just go with different method and of course in this case it is post and not to be redundant we already discussed this before but just because they have the same url the same endpoint since the methods are different in this case we have get and of course in the second scenario we have post these are two totally different requests please keep that in mind and then for individual item you have the same path pretty much so you have api and then tasks orders customers or whatever and then you just use the params to point to that one specific item and then if you want to get the item then of course it is a get method for update you'll use put or patch and then to delete one you'll use the delete method instead and since json is a common format for receiving and sending data in rest api we'll use that approach as well so even though at the moment we use send method in our outs eventually we'll switch to json method instead also i'd like to point out that rest in general is somewhat fuzzy in fact oftentimes you'll deviate a weight from straight up rest since that's what the setup will require one more thing you can probably notice something essentially our api allows our user to perform a crowd operations on our data and crud stands for create read update and destroy and it's a common approach where the api interface is built around crud since those are usually or typically operations that users or apps want to perform on a given data whether it is again users orders customers or in our case of course it is going to be a task and we'll return to credit a little later when i can actually show you how it relates to our data lastly there's obviously more to rest and some of that we will discuss in later projects but since i'm not a big fan of long slide videos and i believe we covered all the major points we'll stop right here and move on to our database setup if you remember in express tutorial the route setup was extremely similar to that we have right now with one big caveat we used basic array to store some list of items on our server and based on the request we performed some kind of operation on the list and then send back the response and of course that is not very serious approach to store our data and therefore starting with this project we'll set up and connect to a proper database and pretty much for the remainder of the course we'll use nosql or non-relational database by the name of mongodb now i'm not going to dwell on differences between non-relational and relational databases as well as pros and cons for each of them but the major difference is that unlike traditional database where we have rows and columns in mongodb we can simply store everything as json and basically it doesn't care how the data relates to each other instead of tables we have collections which represent group of items and instead of rows we have documents which represent single item and a document is a set of key value pairs and as far as data types we can use strings numbers arrays objects and many more it's very easy to get started and even though you can set it up on your local machine as well we'll right away go for cloud option since that's something you'll probably end up doing anyway we'll use mongodb atlas which is a official option basically it's created by the same people who created mongodb and since they offer generous free tier you'll just have to create an account and you'll be good to go and once we're familiar with mongodb let's set up and configure mongodb atlas so we can host and manage our data in the cloud i have the account already but since i want to cover all the steps in detail i'll set up another dummy account together and remember we can set up the entire thing for free so don't worry your credit card can stay nicely tucked away in your wallet if you get stuck or confused in any of the steps we're about to take here is an awesome resource you can use just google create mongodb atlas and follow this link which actually brings us to official docs and here you'll find a checklist which we're going to use as a roadmap for the following few videos and what is the first thing they want us to do create a new account so let's do this people i'm going to open this up in new tab and then of course you can find a bunch of useful info in here yada yada you keep on scrolling and i actually want to navigate to a login page and i'm just going to pretend that i don't have the account and we're going to go for sign up and here of course you just need to provide all the necessary info and once you have filled everything out and as i said no don't worry this is not my real phone number then of course just click on sign up and up next they're gonna ask for organization and project name and in my case i'm gonna go with node and express course then i'll pick javascript we'll click on continue and we probably can actually skip this but let's just leave it there and up next they want us to set up the cluster now if you take a look at the checklist actually cluster is already second step so let's go back here and pretty much you always want to show for a free one unless of course you want to start paying them so in here we'll just go with create cluster that's going to be the free one then it's using aws okay awesome as far as region i'm going to go with this one then we have cluster tier and additional settings and we'll leave them both as default and lastly i just want to change the name and i think i'm going to go with node express and project and once we're done we just need to click on create cluster and we'll get ourselves a new cluster now as you can see over here they say that it's going to take a little bit of time which is usually the case so i'll stop the video here and i'll see your next one where we'll continue with our steps and once our cluster is ready to go before we start messing around with data so with collections and documents and all that there's few things that i want to do first and i'm going to start by setting up the database access so effectively in here we'll set who can access our database now i'm not talking about the atlas account no i'm talking about the database and collections we're about to set up and we simply need to click on add new database user and we're gonna go with password and if you get some default values just wipe them clean and i'll simply go with john and as far as the password i'm just gonna go with one two three four please please please do not do that in your own setup the only reason why i'm doing that because you'll be able to see my password anyway and don't worry once i'm done setting up this project of course i will change my password so it's not going to be 1 2 3 4. and once you're done with the user and password notice we have database user privileges and this user can read and write to any database so i'll leave it the way it is and we'll add a new user that's good i'll close this one and then we want to set up the network access so we want to set up from where we can access our database and you can already imagine that of course once we deploy the project then of course we'll set up that ip address but for time being while we work locally we might as well set up access from anywhere now if you want you can set up your own ip address here so you can just add the current one but in my case i'm going to go allow access from anywhere and i'll just click on confirm and lastly i want to get the connection string that we're going to use once we connect our database to our application and in here what you're looking for is connect so you want to go back to the cluster then connect and then you want to go with connect your application so not the compass one not the shell actually the second one here connect your application and then i'm going to go with 3.6 or later that's about right and then you just want to copy this one and then navigate back to our project now eventually we'll set it up as the environment variable yes that's going to be the case but for the time being i'll simply create a new folder in the starter and i'll call this db and then inside of the db there's going to be a new file and i'll call this connect gis and then i want to create a new variable and i'll call this connection string and i'll set it equal to that value now we'll have to add some values over here but we'll do that later once we're actually ready to connect our application to the database so just take the string copy and paste set it up in the db and then connect js and now we can start exploring the atlas setup and once we have set up database access network access as well as the connection string now let's actually explore the data part and we want to click on collections then we're going to go with our own data and then we need to come up with a database name now the first one will be a dummy one and of course once we connect to our application then we'll create a task manager one so the first one i'll just call store and then they ask us to create a collection and don't worry i'll cover what actually our collections and all that but for time being i'm just going to go with product and then we'll create one and once we have everything in place we are ready to start creating documents so whenever we talk about mongodb we'll have the database so that essentially is going to be that application again in our case eventually this will be the task manager one and then inside of that database we'll have collections now if you're familiar with regular databases you can think of them as tables and in our collections we'll have group of mongodb documents so if i name my one products you can probably already guess that here i'll have list of products and if i'll decide that my store will also have users of course i can go here and create a new collection and as a quick side note we won't have to do this manually i'm just showing you the general setup manually of course eventually all this is going to happen automatically once we connect from our task manager so i have a list of products and then of course i can also create a list of users or list of orders and hopefully you get the gist and once we have our list now let's talk about the individual items so i can go to any of my collections and then once i'm here i can insert a document and document in mongodb effectively represents that one single item and what's really cool that just like javascript object effectively it's a set of key value pairs now by default the moment we create a new document we'll get this underscore id which is going to be that unique id so we don't need to worry about the ids and then of course we need to set up a type so what is going to be the type for our document what is going to be type for the item and if you click over here as you can see these are options we can set it up as an array binary boolean and yada yada and i'm purposely not going to spend too much time on types since eventually we'll set it up from our server anyway and at that point the setup is going to be a bit different since we'll use tool called mongoose now in our case what are we looking for well we're just looking for the string i'm just going to go here with name and then i'll set it equal as first and product so here of course i can insert and now not only i have the product collection but i also have my first item my first document and here comes the biggest gotcha and mongodb documents have a dynamic schema and what that means in plain english is the simple fact that documents in the same collection don't need to have the same set of fields or the structure so if i were to go to insert document and instead of string i'm going to go with array and i'm gonna call this colors and then i'll set my first one to be red then second one blue and if i'll save it as far as mongodbe is concerned they're still the same items in this product collection so nothing stops you from doing that now just because you can does not mean you should and therefore we will use additional library by the name of mongoose which will set up that structure for us but as far as straight up mongodb yes both of these documents are still part of this product collection even though their structure might be totally different a few videos ago while discussing rest i mentioned crud create read update and destroy or delete and now i want to quickly show you how is that going to look like with our current manual setup i fully understand that some parts might look really silly especially the read one but in my opinion it's important we start with the basics and hopefully that way we'll have a better understanding of overall principles when we need to implement crud in our rest api so what does crud means in our manual setup well first we want to create an item correct so in here we just find any of the collections and in this case i'm going to stick with products since i already have some items over here and then we simply go with insert document and again we just come up with a type and then some kind of value and my case i think i'm gonna go with another name and i'll just leave it as a string and i'll say test crud i'll insert the document and i'm done so we're done with the first part where we created an item now the second one reading them well we simply stare at the screen and we can see that we have three items so i can see that i have three products again in our application that just means that we'll be able to read the documents that we have in our database when we're working with gui it's very straightforward where you're just staring at the screen then we want to update them and then with the manual approach we just look for this little pencil and we say that we want to change some values around here so in here i could go with another item and i'll say green so now of course i have successfully updated the array as well and you know what let's also add one more and i'll call this orange then i update and i'm done with that part as well so not only we can create read but we can also update and then last one delete well we simply look for another icon in this case we are looking for the trash icon so we just click here and now of course we remove the item so that's the basic approach of crud in our manual setup all right and once our database is ready to go now we need to connect to it from our server and we can definitely use the native mongodb driver and i believe the package name was just that mongodb but a very popular alternative is to use package by the name of mongoose instead which is a object data modeling library and essentially the reason why it's so popular and why we're going to use it in this and rest of our projects is because right out of the box it comes with bunch of goodies that make our development faster now i'm not going to list them in this video since you'll see them in action in all of our projects just let me repeat that yes you can set up your apps with just native mongodb package but the reason mongos is so popular is because it has extremely straightforward api and it basically does all the heavy lifting for us when it comes to our project i already installed mongoose so we can start using it right away but if you want to use mongoose in your own future projects the command is npm install and mongoose and one last thing in this project we're going to be using mongoose version 5 something so if by the time you're watching this uh if they have a higher version pretty much everything's starting from six so if you have five point i don't know 14 15 or whatever you'll be still in good shape but if by the time you're watching this they already have version six their api might also be different and at that point you have two options install this particular mongoose version or just use the latest one and utilize their docs all right and once we're familiar with mongoose let's kick it up a notch and finally start using our database on our server and the first thing we need to do is to set up a connection and at least a basic setup is going to look something like this where we're going to import mongoose and of course we're going to do that in connect js so i'm looking for db folder and then more specifically for connect js and then here at the top above the connection string i'm going to go with const mongos that's the name of my instance and then that is equal to require and of course i'm looking for the markers and once i have the instance then the method name is connect so we go here with mongoose.connect and the first thing we want to pass in is the connection string but if you remember i said that we'll have to make some changes take a look so this is going to be my username correct but then what is the value for the password of course that is some dummy value so in here we need to pass in our actual password so in my case of course that is one two three four but i strongly suggest using more secure one for your application and then here at the very end we have my first database so this is what they set up by default and that's going to be the name for the database if i don't change it and you're probably wondering well wait a minute i mean we didn't set this up on the atlas so why it's here you see if it's not going to be there it's going to be created for you so here you have two options either you can just go with this one or in my case i'm going to remove it and again just make sure that you don't remove more than you should so you want to remove everything starting with the forward slash all the way to the question mark and in here of course you need to come up with a name and in my case i'm going to go with the same name as my application so since i have 0.1 for no tutorial and then task manager is 0.3 that's exactly what i'm going to set up over here so i'm going to go with 0.3 then hyphen and i think i'm going to go uppercase so i'm going to go with 0.3 task and manager again this is going to be the database name and if you haven't created that database already they will create for you and once we add these changes our connection string is ready to go so now we simply need to pass in as a first argument now the second argument is going to be options and effectively this is where we'll pass in some values just to avoid some deprecation warnings and you'll see what i'm talking about in a second but for time being we'll just leave it empty and then this returns a promise so we simply can go with dot then and since i want to see whether i'm successful as far as the connection i'll just pass in the callback function and i'll say log and of course i'll remove the semicolon and i'll say connected connected to the db dot dot and then since there might be an error as well we also want to go with catch and of course we'll just be looking for the error so we have our callback function and i'll say error and we'll simply cancel log the error so say here cancel log and i'm going to be looking for the error and once we save nothing happens and the reason why nothing happens is because we're not executing this function yet but if you remember during tutorial one of the first things that i covered is the fact that if we have a function in a module where the function is effectively executed there and then we only need to import meaning require the module and we'll right away execute the function so i simply want to navigate to app.js and then this is just temporary because we will change this setup around this one we won't leave it this way i just want to get the connection up and running and therefore i'm just going to go to app.js and then we go with require and notice i'm not assigning this to any kind of variable simply go with require then we look in the db and then more specifically we're looking for the connect and once you save you'll have tons of deprecation warnings and don't worry we'll fix them in a second but all the way on the bottom if everything is correct over here if you passed in the correct password and you grab the correct connection string then you should see connected to the database and if i want to test out the error i'll simply remove the four since i know that that is going to be a wrong password so once i save now of course i'll have this error so i'm just going to keep on scrolling and notice here it's going to say atlas error and of course i already know why because my password is correct and if we'll take a look at our graphical interface in the atlas once we refresh we're not going to see any changes because again we haven't set up any kind of logic so you're looking at it you're like okay i still have one database what's happening don't worry once we start adding the items that database will be created for us in my case 0.3 task manager and even though i will refactor this in the next video because there's some gotchas that i want to talk about before we do that i'll show you how we can remove those depreciation warnings in a console and if you remember we just need to pass in a second argument which is going to be an object and in here we just need to pass in following key value pairs and we'll start with use new url parser and we'll set it equal to true then we'll look for use create index we'll set that one equal to true and then we'll go with use find and modify that one will be false and then lastly we want to go with use unified topology and that one will set equal to true so once i save now i don't have any of those warnings i simply see servers listening on port 3000 and then i have connected to the database and if that is also something that you see in a console you are in good shape and we're ready to move on to the next step nice we have successfully connected to the database and life is great but before we start messing around with the data there's something that's bugging and simply the fact that our server and database connection don't work in sync now what do i mean well let's take a look at the console so first i have console log that our server is listening on port 3000 and only then we're connecting to the database but if we think about it what is really a use for our server if we are not connected to the database whatever we're about to do is going to fail anyway so what i'm trying to say is wouldn't it make more sense if we try to connect to the database and only if we're successful then we spin up the server if not well then we'll just kill the application and in order to do that we need to restructure our code a bit where i'm not going to invoke mongoose connect in the connect.js i'll refactor the code and i'll set it up as a function and instead we will invoke it in the app.js and in order to do that we'll just remove this dot then and catch now options of course stay we're not doing anything with that and here let's create a function we'll say connect and db and that is equal to our function so essentially we're setting up the arrow function and eventually we'll set up the env variable and effectively we'll pass it from the app.js and therefore i'll add the parameter here the url for time being we won't use it we'll do the same thing what we did before where we're just passing in the connection string that's coming up in next video and then i want to grab this mongoose connect cut it out and then from this connect db i just want to return that result so effectively what we're returning we're turning a promise correct and then all the way at the bottom we're going to go with module and export so now of course we want to export it and where we want export of course connect and db so once we have this setup then we'll just have server is listening on port 3000 because now of course we want to assign it to some kind of variable and again the order is really up to you but i'm just going to put it below the tasks so i'll just move it over here below the tasks and i'll say that that is equal to connectdb so effectively i'm just getting that function over here and i'll set it equal to the required one and then once i have access to the function then all the way in the bottom i want to set up one more function by the name of start and in this function we will invoke connect db and then only if we're successful then we'll spin up the server so let's go somewhere here in the bottom and we'll say can't start again we'll use the arrow function and since i know that my connectdb returns a promise correct i can set this function as a sync and that way of course we can use the await keyword and every time we have a synchronous operation it's very useful to set it in the try catch block so that way if there is an error we can handle it as well and in try block we'll pass in a weight so since i know that it returns a promise i'll use my await keyword then i'm going to go with connectdb again eventually we'll pass in the string coming from the env file for time being we just have hard-coded e and d connect js and then only if we're successful then we'll spin up the server so i'll move this line of code right below the connectdb and again we'll just spin up the server if the connection is successful if not we're going to go with console.log and then we'll just look for the error so once we save nothing happens we don't spin up the server because of course now we have a function so all the way on the bottom i'm just going to go with start and then you'll notice that there's a console log for the server now of course we don't have the console log for the connection because we removed that in connect.js but if you really want to test it out again go back over here and just mess with your password and you'll right away see that we'll get that error in console and in here it says bad auth authentication fail so we know that our setup works so if of course we will have a wrong password then we won't be successful however if everything goes smoothly then we should see that our server is listening on port 3000 not bad not bad we have set up the connection we have refactor code and we're almost almost almost ready to start tinkering with data but there's one last thing that i want to do first and that is simply setting up the dot env file now why we would want to do that well let's think about it eventually we might push this up to the github correct and what do you think is going to happen the moment i push this up to the getup of course everyone who takes a look at my repo can nicely grab the string and then tamper with my data and how we can avoid that well the solution is to set up dot env file where we can keep our secret and then in our application we'll have to use a package by the name of dot env and of course i already installed it for you and then we'll be able to access those secret variables anywhere in our application and once we push this up to the github if we add git ignore so dot git ignore file and then in here we specifically say which files we want to ignore and make sure that you add dot env now i also added node modules because that is common practice since that folder is so big but as far as keeping secret secrets make sure that not only you set up dot env and of course use the package because otherwise you won't be able to access the variables but always always always the moment you set up dot env also set up dot git ignore and that way we'll just push this up to the github and then dot env will be ignored so when people come and see your repo they won't see this secret connection string so let's start here by creating dot env and in my case i'm going to do that in the root so i also suggest you do the same so i'm going to go to the star i'm looking for new file and i'm going to go with dot and then env and in here we have again key value pairs however we don't need to use the quotation marks and i think i'm going to go with and then uri in this case so i'm not going to go with long name the connection string and then you simply want to take this value so cut it out from the connect js go back to dot env set it equal to my uri and then where i have connect js i can simply remove it and then remember when we were setting up the function i said that i'm going to be looking for the parameter but of course initially we were not using it now of course i want to use it so i'll remove the hard-coded connection string and i'll say url and we'll just save now there's going to be an error don't worry because of course we're not passing that connection string notice over here we have the parameter blah blah blah is undefined okay that was expected now what we want to do is go to the app.js since over here we invoke start and then we want to pass in that value from the dot envy into the connect db and in order for us to access those secret variables we simply need to require that package so i'm going to go below connect db and we'll just say require and notice how we don't have to assign it to any kind of variable we just go with dot env and that's the package name and as i said if you want to install you just go with npm install and then the package name dot env pretty self-explanatory and then you want to use process dot env and then whatever is the variable name so let me save my dot env and then back in the app.js once we require we just want to go with dot and config so essentially we just want to invoke the config so now if we keep on scrolling where we have the connect db we want to go with process dot envy and remember that was one of those global variables we go with dot env and then we go with or whatever the name for your variable is in my case that is uri and we'll save it and of course we're back in business because i have server is listening on port 3000 again very very important if you want to keep your secret variables actually secret set up the dot env get the package and you'll be able to access them anywhere in your application by using process dot env and then whatever e is the name of the variable beautiful and once our connection string is a env variable now let's set up the structure for our future documents and assign them to the collection and we're going to do that using schema and model from the mongoose and the way it's going to look like we're going to go to our starter and we'll create yet another folder and in this case we'll call this models and then inside of the models we'll create a new file and we'll call this task.js so i'm going to go here with task.js and then the setup is going to be following where again we import mongoose and we set it equal to require and then mongoose of course and then we're looking for mongoose dot schema so we set up a new variable and i'll call this task schema schema and that is equal to new so we're using the constructor and we go with new mongoose and schema and you're probably wondering okay what on earth is happening well if you remember when we were setting up the atlas manually one of the first things that i mentioned is the fact that for our document there is no set structure but that's exactly what i want where for my tasks i only want a name which is going to be a string and a completed property which is going to be a boolean because you would have to agree that it's not going to make much sense if somewhere in my tasks i'll have an array with the color values correct so therefore we go here we go with schema and using schema we'll set up the structure for all the documents that eventually will have in our collection and the syntax is following where again we use key value pairs and eventually we'll set them equal to an object and we'll pass in more options but since i just want to get something quickly in our database we'll just start quick and dirty where essentially i want to come up with a key in my case again that is going to be name and completed so those are going to be the two keys and i'll just set up the types so that is a bare minimum where you go with the key name and then the actual schema type so what type of data this is going to be and if you're interested on what options we have just navigate to mongoose official docs and then look for schema types keep on scrolling and then of course you can see string number and yada yada so i'm going to navigate back and i'll say name so that's going to be my first key and i'll just set it equal to string then comma and of course i'm looking for completed completed that is going to be my second key and that will be set equal to boolean again bare bones setup will do more complicated a little bit later and then once we have the schema so essentially once we have the structure for the data now we want to set up that model and think of model as a representation for the collection so these guys are sticking in a product so now of course we'll create tasks collection and then all the tasks that we're about to push into our database of course will be added to that specific collection and what's even more cool in mongoose a model is a wrapper for the schema so if the schema defines the structure for the document like the type validations and etc a mongoose model provides an interface to the database so using the model will be able to create update query and delete our documents with great ease since the api is extremely extremely straightforward and you'll see what i mean in the upcoming videos and we do that by creating a model and we right away export so go with module dot exports and that is equal to mongoose then model and then model is looking for two things it is looking for the name and then we want to pass in the schema so in here i'm going to go with task and then comma and of course this is the schema that i want to pass in so say here task schema and once we're done with this the only thing we need to do is go to our controllers and start using our model beautiful we have set up our first schema as well as the model and of course we want to start using it and yes we will use it in controllers therefore we'll navigate there and i'm going to be looking for my model and i'll assign it to the task variable i'll say require i'm looking in the models folder and then more specifically task and then before we continue let me just give you a brief overview of what we're about to do so if we navigate back to mongoose docs and more specifically if you're looking for the models we can find here more info you can see that models are fancy constructors compiled from skiven definitions an instance of a model is called a document and then they give you this example pretty much everything that we did in last video apart from the fact that of course they have different values and here we have nice explanation that the first argument is singular name of the collection your model is for since mongoose automatically looks for the plural lowercase version of your model name so effectively eventually we'll have the tasks then dimension one more time that the instance of the model is called document and there are few ways how we can create one we can go this route or we can use dot create and here they showcase the callback function approach but we can also use a weight and essentially what create is looking for well it's looking for the object with those properties so in our case we have name as well as the completed correct and of course we can pass this manually but wouldn't it make more sense if we just go to create task route and since we know that in there we can access the task data in the request.body why don't we just pipe it through and pass it along to our model create method and it's going to work something like this where i'll grab the body of course it's going to be coming from my postman here shake and break and the value will be true and then instead of sending it back we'll pass it into task dot create now since i'm going to be using a weight on a task dot create of course i want to refactor this and i'll say that this function the create task actually is going to be async so my controller will be async and then instead of the function body i'm going to go with task and i'll set it equal to oh wait like i said i'm not going to use the callback function approach i'll use a weight instead and we'll await for task dot create and like i said if you want you can hard code this here you can say name and then first task and of course we can do the same thing for completed but i already covered why it's going to make way more sense if we just take this rec.body so whatever we're getting from the postman and then let's just pass that object into task.create and let's see what happens so i'll remove it here and i'll just say rec.body over here and as far as the response well now i'm just waiting for that task so instead of wreck that body in a response i'll place my task and i also want to add the status and if you remember the correct status was 201 effectively that is if you have a successful post request and then instead of json being equal to rec.body we'll pass in the object and in here we'll pass in our task and then once we save again nothing happens because we haven't triggered the post request but if we go back to the postman and if i click here send what i should see is this i should see the task so that's my object and now check it out we have this underscore id and what that means well that means that we created a new document with the following properties we have name we have completed we of course have the id like i just mentioned and we also have this underscore underscore v so of course these two are created by default every time we create the document and then these ones we provided so if you want to keep on testing we're going to go with second task and we'll set maybe the completed to false again this is all quick and dirty just because i want to have some data in my database there will be still some modifications to the code but if we can see these successful responses where we have tasks with underscore id what that also means my friends is that when we go to our database and if i refresh check it out now of course i have the task manager like i said that's my database and what do you know of course i have the tasks collection now what do i have in task collection i have documents what documents shake and bake and second task and if you have the same result congrats we're off to the great start nice at this point we can successfully create new tasks and persist them in our cloud database so now it's really just about applying the same concepts to the rest of our routes but before we set up the rest of the four controllers in a similar fashion there are a few important things that i want to cover first for starters i just want to showcase that since we set up our schema only the properties that we specified in our schema will be passed on to the database and everything else is going to be ignored don't believe me let's try it out first i just want to showcase that in our schema we specified two properties name and completed so now if i go back to the postman and i'll just set up testing schema that's gonna be my name testing schema i'll leave completed as false but if i try to add some properties that are not on my schema effectively they will be just ignored so my guys i'm just going to say random is equal to random now i do still need to use the proper jsons index and then i'll just add the amount and i'll set it equal to five now you can add ten thousand properties and again the result is going to be exactly the same so i'll just leave these two and we'll try to send it so here i send and then check it out now what i get back is only the name and only the completed again let me repeat only the properties that you set in your schema will be passed on to the database everything else will be ignored which of course is really really cool because that way we can avoid this mess where if you remember back in the store when i was setting up the products one has name the other one has the colors because there is no structure for these documents when we use schema there is a structure so whatever we set up in a schema is gonna be passed on to this database and whatever comes as an extra is just gonna be ignored all right and once we've got that out of the way next i want to talk about validation you see even though we only accept the properties that are specified in the schema our current setup has one big doozy there is no validation so essentially we can pass in empty values how is that going to look like well again we can go back to the postman and in first example i'll just remove completed and i'll pass in the name as an empty string now i do need to fix this comma here but you'll see that actually we're successful so i can create item this way and what's even more interesting is that i can send an empty object and i'll still be successful and you have to agree that actually this is not the best setup correct so that way we can just set up a bunch of empty items now what can we do about it well we can add the validation to our schema now before we continue though let me just say that when it comes to validation since it's a pretty big topic we'll just be scratching the surface the plan is to show you more features as we progress with the upcoming projects since i have a feeling that if we'll spend the next hour or two on just validation understandably a lot of you will lose interest and attention don't worry though the end of the video i will show you where you can get more info so at the moment we have a very minimal setup where we have properties and we just specify the type however we can set up our properties as objects and then we can also set up built-in validators how is that going to look like well i'll remove the string part from the name and then i'll set it equal to an object i'll add a comma of course since i need to keep the proper syntax and here the first property we want to set up is type now it's still going to be a string but now of course we can add more validators now what validators can we use for starters we can go with required so what this is going to do is if i pass in the value the object without my name property then it's gonna spit back big fat error now at the very basic level you can set up equal to true or false either it is required or not but if you want a custom message you can actually set it equal to an array where you go with the first value again true or false and then you add a comma and then you pass in that custom message and in my case i'm going to go with must provide and name now what else i can do well i can trim so imagine the scenario in a postman if i go here with name and if i pass in here spaces and then john effectively with our current setup that's exactly how we'll save it in our database and if i don't want that i can simply go back where we have the object and then the property that you're looking for is trim and we'll set it equal to true and what's also really nifty that for strings we can get min values or max values and in my case since i don't want my value to be bigger than 20 characters for the name one i can go with max and property that we're looking for is length make sure that you spell it correctly this is always a doozy for me when it comes to length and again we'll set it equal to an array and i'll say that the value for my string is going to be 20 and then in here we'll just go with name cannot be more than and of course we'll set it equal to 20 and nine characters and essentially we're done with basic validators for name because like i already mentioned i really just want to scratch the surface so you get the main idea and then as we're progressing with the project then of course we'll implement more features and i want to do the same thing for completed where i'm not going to go with required hopefully this is clear and you'll see in a second what kind of error we have if we don't pass the name but for the completed i just want to show you that we can also set some default values and again we want to remove this boolean and we're going to go type we'll set it equal to boolean and then as far as the default value the property is simply default and as far as default in this case for the task property completed i think it's going to make most sense if we'll set it equal to false again just to showcase how is that going to look like in a real project so as i'm adding the task new task by default it's not going to be completed and only when we navigate to a specific task page and i say yep it's completed now we can add it and then of course we can navigate back to all the tasks this was just my setup of course there's million different ways how you can do that but that's why in here when i'm setting up my validators i set my completed one to be equal to false so now of course we can save it and we can test it out so i'm going to navigate back to my setup here in a postman and as you can see completed is still not required and that is done on purpose so essentially i already set this up as default false so i don't want to set it up as required therefore we don't need to pass it here but i just want to see how it nicely is going to trim and how we also will get errors if we don't pass in any values so in here let me just try with the john and notice once we send we actually get trimmed value back and completed is set to false right away okay that's an awesome start but notice what happens if we send an empty string so let me remove all the values let me click on send and now check it out so we have here this sending request and the reason why we're not getting anything back because we have big fat error in our console we have validation error and there's few things that we need to understand about this error first it is caused in a task schema because we finally set up the validator and we set it equal to true and of course we're sending empty string so that's the same thing as if i were to send completely empty object over here so if i cancel it and if i send it again notice again we're not getting the response that's point number one number two if you take a look at the console you see that we have this unhandled promise rejection and this error is originated blah blah blah blah and long story short it is caused in our create task because we have a weight keyword however we're not handling this gracefully we don't have the try catch block where we set up the await in the try and if there's an error then of course we do something about it and since this video is already getting quite long i'll actually do that in the next one so just put this one on ice and then in next video we'll set up a proper response and just to recap as far as basic validation we just need to set our property equal to an object then we need to set up still the type and in our case that was the string and then we can go with the required if we want to have a custom message then we just set it equal to an array and the first item is going to be the value whether that's true or false for required and then the second one will be the custom message then for the string we can also use trim and that's just going to make sure that we don't have any white space and you can probably already guess that there's one for the min length as well and in a completed one we covered how we can add a default value as well so for this one we set it equal to false and if one of our validations is going to fail then of course we won't be successful of adding that item and like promised if you want to learn more about validation just head on over to mongoose docs so navigate here and then you're looking for the validation and as you can see there's quite a bit of info here so if your idea of good time is scouring through the docs you won't be disappointed not bad not bad i think we have good general understanding of the basic validation in mongoose so now let's switch gears and talk about how we can handle it more gracefully because at the moment well we're just leaving our user hanging correct so if the user sends some kind of request with incorrect data then of course we have the error here on the server but as you can see the user is just hanging and probably it's not the best approach and again the whole reason for that is because we have a synchronous operation however we're not handling if there is an error and the fix is following where we want to go with try catch and then we want to place our await in the try block and i'll also right away set up my response so if we are successful i still want to send back the response with our task document the one that we're getting back from the model and then the second thing if there is an error what do we do well we could also send back the response and in this case the status is going to be 500 and effectively that is just a general server error and as i said i'm purposely using just a general server error status code the 500 one since we'll discuss errors in greater detail later in the project and then we can go with json and i'll set up the message property and i'll set it equal to my error so now if we save and if i go back and if i send one more time you'll notice that instead of hanging we actually get a response and in here i can see that the status is 500 so it's definitely our response at this point in time you probably have two questions first do we really need to wrap all our logic in every controller in trying catch since i can give you a hint that in the remaining controllers we'll also use the functions and we'll stick a weight in front of them and the short answer is yes for timing we'll have to do that but then eventually by the end of the project i'll show you multiple ways how we can simplify that and how we can omit this boilerplate code for try and catch then your next question probably is okay we get the response but this error seems a bit lengthy can we make it shorter and my answer again is yes we can and the most basic approach is going to look something like this instead of setting message property equal to another parameter just simply set it equal to generic there was another string value as far as more complex setup i'll discuss it at the end of the project since i want to keep moving along with the rest of the functionality as far as my setup i will keep sending this giant object since that way i can show exact error messages we're getting and as far as our api i think we're actually in pretty good shape where we can create a task we do have some basic validations and if there is any kind of error well we simply send back 500 that there is a server error and we send back error message yes quite long one but at least it's better than leaving the user hanging and if we want to try out the max length and simply go here with name and then i'll just add some gibberish just so it's more than 20 characters so let me tap it out here and then once i save again we get the error message where we have name cannot be more than 20 characters that should do it for this video and now we're ready to move on to our next topic and once we're done discussing the validation as well as the need for try and catch since we have synchronous operation why don't we continue with our controllers and up next i want to work on get all tasks so we know already how we can create a task we know that we have a model in the model we pass in the schema and then in order to get the instance we go with the name of the model and of course the method name is dot create now what about rest of the cred operations and again we'll use our best helper the mongoose docs and if we navigate there and then if we look for queries then we can have this nice text where it says mongoose models provide several static helper functions for and this should be already familiar crud crowd operations and each of these functions returns a mongoose query object now we'll work with query object way more in the next project but for time being we just need to understand that on every model we have these methods that we can use starting with delete many all the way to update one and the one that we want to use right now is this one the fine one and i'll just open this up in a separate tab and then we can see that as far as the parameter we want to pass in the filter object now what does that mean well it means that if i'll leave this filter object empty this is just going to get me all the documents so in our case this is just going to get us all the tasks now if we start supplying the values for example in our case we could say completed equal to true of course that is going to get us what that is going to get us only the documents that are completed again the way i've set up the projects of the next project the second project is the one where we'll take a deep dive into the filtering sorting and all that for time being we just need to understand if we want to get all the documents which is going to be in our case for the get all tasks controller we simply need to use find now it's also really interesting is the fact that if we go back and if we keep on scrolling we can read that a query also has dot then function and thus can be used a promise now there is a caveat where technically it's not returning a promise that's why i say here used as a promise and essentially what that means for us is that yes we can use a weight so for simplicity we can stick a weight in front of it and we'll be in good shape however if you keep on scrolling you'll read that queries are not promises and there are situations where it's really important but if we keep on reading here they have that then function for a sync await as a convenience so long story short similarly to how we created task with a wait and we set up try and catch block we'll do it here as well and the way we'll do that we'll go with try catch so in here of course there's going to be an error but if we're successful then of course we'll just send back all the tasks so let's start here with const and i'll set it equal to the tasks and the value will be equal to a weight so use a weight keyword therefore in front of the function i want to set up my sync and then i want to go with task so that's going to be the name of the model and then the static function name is fine and since i want to get all the documents in the task collection therefore i'll just stick here a empty object and then as far as the error well i'll just simplify this well in order to speed this up i'll just copy the error from the create task and pass it here as well and now the only thing is missing is our response if we're successful what do we want to do well we want to go with res dot and then we're looking for the status in this case the status is going to be 200 and then json and in here i'll just say tasks so i'll be sending back the object and then instead of that object there's a property by the name of tasks and as far as the value it's going to be equal to whatever i'm getting back from the find and i'm just using the es6 shorthand where if the property name is exactly the same as the variable for the value well we can omit the second part and effectively it's the same as if i were to write like this so we have tasks equal to tasks and then with es6 we can just shorten this up and once we save and if we go back to the postman and you know let me fix this one i'll say here properly i'll say testing testing task because i want to save that create one so save it here so it stays as our request and i'll close it and then if we go to all the tasks and we simply hit send now what we should see is of course our object and check it out now we have all the tasks so we have our array and then inside of that array we have items of course each item is represented as an object so successfully we have set up the second route as well for all the tasks and here we use the find static function and we pass in the empty object which just gets us all the documents in the collection and in our case of course those are our tasks and then if we're successful if there was no error we just go with res dot status so we set up the status for response and we send back a json and i just jam all my tasks awesome and once we have set up the controllers for create task and get all tasks next i want to work on get desk and effectively in our application that route provides info about specific tasks so in here i can see all the tasks i can create one of course but if i want to edit it i'm going to click on edit button and then notice how i'm getting the info about this specific task of course normally you wouldn't share the id but in this case i just wanted to provide more info so not just a name but also an id so that way you can clearly see that this info is just about this task and similarly i can go to the next one and again i'll get the id i'll get the name and whether it's completed or not now in this video of course we won't set up the edit but at least we'll get that specific info and general the setup is going to be pretty similar to the one we have with get all tasks however we'll also have to implement a specific response if the id that we pass in doesn't match any of the tasks that we currently have and in order to get up and running we'll navigate back to the docs to the mongoose docs and in this case we're looking for the find one static helper function just like we used find in this case we're looking for find one open up new browser window and then notice as far as the parameters we go with conditions so we pass in conditions object and they're very helpful here where they say find one adventure whose country is croatia otherwise no so essentially we use a weight just for convenience we have our model then we have find one and then we pass in the object and in that object we set up what well we set up the condition and in this case they look for the country in our case of course we will look for a task and we'll use the id so i'll say get me the task whose id is equal to whatever i'm getting from the params otherwise we'll get back now so let's now get back i'm looking for get task and remember in here of course i'm getting that params id and before we type anything here in the controller i just want to set it correctly my id because of course initially well i was just passing here repeater but of course that's not the case anymore and since i want to use the id that i'm getting back from the i'm going to go to all the tasks i'll run it of course i get my list awesome and then pick any of the tasks it doesn't really matter which one just look for the id copy this one and then go back to the single task and then of course instead of peter pass in the id and send and if you get back the id key with this value with that long string value which is an id then of course we're in good shape and i'm doing this just so we don't have to count the log here on the server you can definitely do so but i just think that it's more convenient for us to see those logs here in a postman and then once we have everything in a place i want to go with my get task and here what's the logic well we could start by setting up i sync of course because we'll use the await then we'll go with our try catch block and then i'll move this sucker up and then first we just want to get that id out of the params so of course you can write it the long way but i always like to do the structuring first so we'll go here with const id and then i always prefer giving it somewhat useful alias otherwise you just end up with bunch of ids and then once in a while it's just confusing which id is for what so i'll say grab me the id which is coming from the params but use the alias of task id from now on and then i set it equal of course to rec dot params so it's the same object that i'm getting and then of course we want to use that find one correct so we're going to go with const this is going to be our document that we're getting back if we're successful and we'll go with await and then task and then find find one and then like i said we pass in the object and in this case i'm going to be looking for underscore id so not the name but underscore id which matches to that in the params so i'll use here task and then id and if i'm successful beautiful we'll send back the task if not then we'll have to send back the 404 response so here we'll go with res dot and we're looking for status so say that everything is correct we were successful and therefore we'll go with res dot status 200 then dot json and then i just want to pass in a task i'll say yep that's the task you're looking for now there also might be a case where there's something wrong with an id where essentially yes we're getting the value from the params but it doesn't match any of the tasks and if you remember documentation then we get null so what is the case then well then i want to check if the task actually is null and then of course i want to send back different response now make sure make sure make sure that you always always always set up here return otherwise what's going to happen while javascript is going to be reading the code and if you don't have the return even though there might be no task well you'll send one response and then you'll send the next one right after that so always always make sure that you have return so that way javascript knows okay so now i just need to return from the function and in here we go with res.status now in this case though of course task that we're looking for doesn't exist and the status code for that is 404 and then again we go with json here and we'll pass in the message in the object and the message we'll be following we'll say no task with id and then colon and then we'll just look for task and then id and eventually of course we also might have the error and i'll talk about these two errors in the next video because that's going to be a common theme that will set up for the upcoming rounds and i kind of want to give it a separate video so in here let's just scroll up and let's just look for that generic one the res.500 and then we'll just pass in the error copy this one and then scroll down and below where we have the catch of course pass it in so if i go back right now to my postman and if i click on send i should get shaken bake because of course that is the id now if you don't believe me we can go back to all the tasks let's keep on scrolling and then i think i'm going to be looking for this testing schema because some of them are actually empty when we were testing out that's when we were setting them up so now grab this id instead go back to single task and then copy and paste and of course now the value is going to be testing schema and like i mentioned previously i'll talk about errors why we have two of them essentially why we have two responses for the errors in the next video but that's how we can set up a route to get a single item so we go again with try catch we set up async and then we use the static function find one and then of course in this case we're looking for the id that has the value the same as in our params if we can find one awesome we send back that specific task if not then we send back 404 and then all the way in a catch block we have our generic error okay so why do we have these two responses well we have four or four with no task with this eddy and then we still have the generic one well simply because we can have two types of errors and in order to show you that we just need to navigate back to the postman and then notice where we have the params where i set up this long id why don't we try changing the last value so instead of b that i have here i'm gonna go with zero and once we send well we should get the message no task we blah blah blah id why well because of course in our database we don't have any item whose id is matching and i can clearly see the 404 that means of course that that is our response but if we change this around and then instead of keeping the same amount of characters we start removing or adding you'll see this error and the name of this error is cast error so effectively what's happening if we have the correct syntax for the id but we cannot find the item then of course we'll have to deal with it ourselves because essentially there is no task with this id but if the id is actually going to have the wrong syntax meaning it's not going to match the amount of characters that mongoose is looking for then of course we'll get the error from the mongoose and like i already mentioned this is going to be somewhat common setup for us for the upcoming controllers as well because for both of them for update task as well as delete task at the end of the day we'll still have to find that one specific item and if we're not successful then we'll send back the 404 but we'll always have this generic one as well just in case the actual syntax for the id is totally off awesome i think we're moving in nice space and up next i'll actually work on the lead task why well because with update task it's a bit more complicated and i kind of want to leave it as the last one because i promised you that i'll show you the differences between put and patch as well so therefore let's work on delete now most of the stuff is going to be exactly the same so once you're comfortable with delete i think you'll have no problem setting up update task as well and just to showcase in our application if we go back to all the tasks if you click on removing the task there we go now of course we just remove the task and the setup is going to be very very similar to getting the task of course the biggest difference is going to be the method or the function that we're going to use and in this case we're looking for find one and delete but everything else pretty much is going to be the same so if you want you can just copy and paste and change the values but in my case since it's going to be a bit more productive why don't we type it all together so i'll go with my sync we go with try catch block now i have simple res dot sense so i'll just remove it all together then we want to look for that id in the params because again setup isn't going to be exactly the same where we pass in the id with our params and we'll call this task id and that one is equal to rec dot params then once we have access to params we just want to go with const task is equal to await again task and then find one and remove or i'm sorry delete so find one and delete and in here we want to pass in the id again so underscore id and that one is equal to our task and then id and then once we have the setup of course then we have two options if such task exists then we send back r200 if the task doesn't exist so essentially if this is equal to null then of course we go with r404 and in this case i will speed this up a little bit where i'll grab the if condition like so and then as far as the response initially i'm gonna go with a json object and i'll set task equal to task but at the very end of the video i'll discuss multiple options that we have so this is the 404 if we're not successful again if that item doesn't exist with that particular id if we are successful we go with res dot and then status and we pass in 200 and then we just go with json and then we pass in the task so essentially that way in the postman we'll be able to see which task we removed and then just like the previous controllers we'll grab our generic one as well and set it up in the catch one so if there is an error there's to be a message property with that particular so we navigate back to the postman and we're looking for delete task again we have this dummy value in my case that is peter but in your case it might be something else so again we need to go to get all tasks run it so now of course we can see all our tasks and then just pick whichever you want to remove and you know what in my case i'm going to go for those empty ones first because i don't want them in my database anyway so i'll go over here i'll grab the id and then i'm looking for delete task copy and paste and then once i save check it out now of course i can see that i removed this task and i'll remove another dummy one as well so let me run it one more time now i can clearly see that i have only one without a name since i removed the previous one so let me just grab it over here and then back to delete task copy and paste and then send and of course i can clearly see that i removed this one as well and just to showcase again why we have those two errors let's go back to all the tasks let's send and i'll grab the first one for shake and bake and what you'll notice is that if i pass in the id and if i just change the last value so i still keep the same structure then of course we'll get our 404 so no task with id and of course i have 404 now if i'll start adding or removing the items and of course what you'll see is this error so of course this is coming from our catch block hopefully that makes sense and then lastly i just want to mention that as far as this response i purposely set it up here as a task just so we can see in the postman because i think it's a bit useful when we're setting up our first api but by any means you're not limited to sending this type of response why well because usually when it comes to deleting a task you're really not looking for the data here take a look at our front end it really doesn't care what task we're actually removing because the way the functionality works is i click on a button then i'm looking for the response and if the server sends back this 200 then right away on my front end i go like okay awesome i was successful so let me fetch the entire list one more time so it's not like i take that item and then i do something about it no i just say i want to remove the item if i'm successful awesome i'll do one thing if i'm not successful then of course i want to display some error message or something along those lines therefore if you go back and if you change this around to for example and i'll just show you some common ones that you might see in the other apis so let me comment this one out i'll copy and paste and then as long as you go with 200 you can simply even go like this you can say send that's it that's all you have to do and the functionality will still work or you might see something like this where again copy and paste and then if we go with json and some people just go with task and then set it equal to null and you might add a status property here with success and as you can see sky is the limit i'm just showing you what type of responses you might get back because again the main idea is that if you're successful if you're getting d200 already on a front end you know what's happening so most likely you're not going to be looking for that one specific item that you're deleting but again in my case i just set up this task so we can nicely see in a postman what we're moving so i'll remove these two lines of code here and then i'll just set it back to my json where i have task is equal to task and as a quick sign out once we're done setting up the update task route i'll spend an entire video on various options that you have for your responses so just put the pin on that and we'll come back to it a bit later all right and we have successfully arrived at our last controller the update task one and if we are comfortable with getting the single task and setting up the delete task we should be in good shape because yes there's going to be a bit more functionality because in this case not only are we looking for the id but we'll also need the body since of course we'll be updating something correct and then the second thing we have to pass in some options since by default we won't get right away the validators working and also we won't get the item that we just updated and don't worry of course i'll talk about all of that in detail so for now just to stay consistent i'll move this sucker down i'll move it below the delete task and let's just start simply by accessing both of the things let's get the params one and then the body one so we just wanna see that we are successful on acquiring both of those things so i'll set this up as async is just a simple send so i'll just remove it and we're going to go with try catch and for now let's just go with arrest dot and then status we'll set it equal to 200 and then the json one and here i want to grab two things i want to grab my id just double check that i'm getting it properly from the params and also the body so for now above the res dot status let's set up the id one more time we'll say id so we're destructuring from the reg dot params right dot params and second one is going to be rec.body and if you want you can assign it to a data or whatever but in my case i'm just going to set up the property here and set it equal to directly so let's just say id is equal to a task id and then data is going to be equal to rec.body again why are we going to be passing data well because if we're updating something of course you need that new info correct so if i go back to my application and if i say that instead of walking the dog i want to walk the cat of course i need to supply this name otherwise it's not going to make any sense the same goes for completed i need to pass in that key with the new value and in this case of course it's going to be false so once i click edit notice i'm successful awesome so if i go back to all the tasks now i have lock the cat and in order to test this out again we need to go back to the postman we're looking for getting all the tasks since i want those correct ids and you can pick any of them doesn't really matter i think i like the shake and bake the most so take this one then we need to go to patch the update task one copy and paste and then in response we should see the id correct we're not gonna see the data since we haven't set up anything here in our body at least not right now but we'll do it in a second but of course now we're just getting update task so let's see let me go back here update task probably i didn't save the file my apologies let me run one more time and now i should see the id that matches of course my shake and bake but as far as data there's nothing there why well because i haven't sent anything from my front end right so now let's go to the raw and then we'll set it equal to the json and then we set up our object and remember we're looking for the name and i'll just say testing edit func functionality i guess and then we're going to be looking for completed and we'll set it equal to let's just double check in here it's true so let's go with false and let's set it here of course now not only i'm getting the id just coming from the params but i also have the data property and in there of course i can clearly see those values again the whole deal why i'm doing this is just so we don't have to console.log on a server and once we have all of this in place now let's roll up our sleeves and actually set up our functionality so i'll remove this one we don't care about this one right now and again we want to go with the task meaning i'll sign up a variable with the name of task and i'll set it equal to await and of course now we're looking for task the model name and then find one and if this one was find one and delete what do you think is going to be this one well it is find one and update and in here we need to pass in a few things first we need to pass in the object where again we set up our condition so in this case again i'm going to go with id matches to that one in the params so underscore id equal to task id that's step number one then of course we need to pass in that new data since we're updating something correct so let's go here with comma and that's going to be the second value so essentially you need to set up the object and set up which properties you're updating but remember we're already getting that as far as reg.body so reg.body is right away this object so i can simply set up my next parameter like so where i go with reg.body and then we have options object but i first want to show you what happens if we don't use it and then we'll add both of the values in there as well so let's start here again by checking the task because again we might have a situation where there is no task with that specific id and again just speed this up or copy and paste and then if we are successful then of course i want to send back the task i'll say task is equal to task and don't forget the generic error where we go to res.status and then you already know the rest copy and paste and you'll notice something interesting since we don't have the options you'll notice the following thing where i go with testing edit function okay that's awesome i completed false but essentially what we're gonna get back is the original value so remember the shaken bag effectively this is what we'll get back so once i send notice yeah i get 200. so i was successful but notice the value here it's shaking big and what's more interesting that once i click on getting all the tasks it's actually changed so i was successful so here's the gotcha the reason why is that happening is because we're not passing in the options and as far as the options we want to do two things we want to get the new one back because by default we're getting the old one that's why we were successful but in our update response we got the old value and the second thing which you'll notice is the fact that we're not running the validators so if you remember when we were setting up the model one of the things that i set up for the name was required equal to true now if i try to update item with name equal to an empty string i'm actually going to be successful now again we're getting back the old value and in order to check the new one we just need to run get all tasks notice and i promise you i'll say this for the last time in this video the reason for that is because we don't have the options object and in order to set it up we just need to go back to all the controllers and like i said third parameter is going to be our options and then we simply go with new true so this will always always always return that new item the one that is already updated and then the another property we can run is run validators and we'll set it equal to true so once we do that of course we fixed both bugs so if i for the final time i guess in this video go back to my postman and in here i'm going to go back to shake and bake and we'll set the value equal to true we should see that right away so i can see shake and bake and if i try to do that without passing anything in the name then of course i'll get my big fat error because when i was setting up the model i said that name is actually required awesome and believe it or not we're actually done with our basic setup as far as the api and in order to showcase that i'll simply go back to app.js and then i want to serve my static files because this is where my app is sitting and of course since our api is up and running we can simply set up those static files the app and the functionality should work and if you remember in order to serve static files we need to use another middleware and we're going to go with app.use we'll pass in express and the name is static and then in here we just simply need to say where the static files are located and in our case of course that is in the public folder and let me just say that if your code is exactly like mine everything is going to work now back in the app.js i don't think we need that hello one anymore so let me remove this one folder out i'll just leave the version one and then tasks and then if i go to localhost 3000 and i remove that hello i should see my app and i can clearly see that these are all the tasks that i currently have and if i want to add new one i'm just going to say testing app and once i add of course i have all the way in the bottom a testing app well effectively i have two but we right away can also practice on deleting so there it is now we can delete the items all the way to second task then if i want to see the single task just click over here notice now i have the task id as well as second task and then eventually if i want to edit well i just click here on completed and i'll say third task third task and if everything is correct we should see task edited now i still need to fix the css but as long as you see the correct text you should be in good shape now of course by the time you're watching this i'll fix this but the idea is following if i try to edit the item without providing the name now of course i'll get error please try again i just need to fix the css where essentially if i'm successful i still get this red color and then once i navigate back now these are going to be my task if you're interested in the actual app just navigate to the public one you'll see that i used vanilla.js just so everyone can be on same page and essentially as far as the logic you're looking for browser app.js and i'm not going to show you the entire thing but as far as submitting the new task i'm just listening for submit event then i prevent the default i'm looking for the value in the input and notice that i'm using the axios library and check out the method what is the method name that is post why well because that's how we can pass data onto the server correct now what is the url that should be familiar we have api version one and then of course i'm looking for the tasks and in here i pass in the data so unlike the postman where we were doing that manually now of course i just grab the input and i'll pass it in and if you remember the completed was set to false right from the get go so i don't need to worry about that i just need to pass in the name and again everything is in try catch so if i'm successful then of course what happens well then i add the correct alerts and all that and then i just refetch one more time tasks now if i'm getting the error then of course i'll add different alerts and hopefully you get the gist and just to lastly showcase the delete one if we scroll up a little bit notice the method here and like i previously mentioned the only thing i'm looking for here is the response if everything is correct if i have 200 awesome i just refetch all the tasks if not then there's an error and essentially i don't remove it from my dom that's why i said that technically when you're set up for the delete in most cases you're not gonna have to send back that item that you're removing and now it's simply about making this app better because yes we have the core functionality in place we can definitely test it out on the front end and everything is awesome but there's some things that we would want to fix for example i want to remove all these strike catch blocks i don't want to repeat myself in such a way i also want to set up one place where we're dealing with errors and other improvements so in the following videos we'll make our app better so we have the core functionality in place now we just want to make it better all right and up next i want to finally discuss put method versus patch method so why in this api in our routes we used patch and during tutorial we used put so here's the deal yes put and patch are both are both for updating the resource but the assumption is that when you use put you're trying to replace the existing resource and patch is for partial update and since i'm fully aware that this might sound like mumbo jumbo to you let me give you an example so if we go to our postman and then more specifically update task if the id is correct then only the properties that i'll pass in will be updated so in this case if i'm gonna go with shake and bake number two and i'll actually remove completed only the property that is passed in will be updated so if i send check it out now i get the task and i can clearly see that completed is there even though i didn't pass it why well because that's how our functionality is set up in the controller so if i'll pass completed and i'll set it equal to false of course it will be updated as well so if i go here completed and i'll set it to false yes in this case since i'm passing the property of course now i'm going to get the new result now what is the difference with put well let me go the long route and actually set up one more controller but keep in mind that this is going to be just temporary controller so if you don't want you can just sit back and relax and we'll start in our routes where essentially i want to go with my route and in this case i'm still looking for this forward slash and then colon id because again the functionality is going to be almost the same but i'm looking for a different method and i'm looking for put and of course now we just need to create the controller and in my case eventually i'll call this update or i'm sorry edit task just so it's a little bit different so of course i'm not exporting that yet but i'll right away set it here in my structure i'll say edit task and then back in the controllers i just want to go below the update task again this is just going to be temporary but i'll go with const edit and then task and that one is going to be equal to whatever i have over here we simply need to add one more option in the find one and update so let me select this whole thing just so we don't have to type it from scratch and all the way in the bottom we're gonna go with edit task and like i said it's going to be temporary so in here i'm not going to save it with all my routes but let me just save my current ones and i'll close all of these windows and let's set up a new route so in this case it's going to be a put route and remember we have our variable so i'm looking for url and then i'm looking for the tasks and of course i want to grab some kind of id so let me get again all the tasks here and i'm going to stick with shaken back because i like that name so much so let me grab this id here then back in tasks i will pass it in and then let's try to recreate the same functionality that we have for now in the patch and essentially what i really want is just to pass in some data in my body so i'm going to go here with raw again we're looking for json and we'll set it up name equal to john nothing particularly original and once i save of course now shaken bake has the name of john but here comes the biggest difference between put method that we're using over here and the patch method so idea with put is that if i send only the name my expectation is that all the rest of the properties which of course in our case is just completed will be removed from that item so we will replace that item and how is that going to look like in our controller well here everything is going to be exactly the same but by default mongoose doesn't do that so by default mongoose is going to be like okay so you want to get the item you want to update it awesome just get me the properties you want to update and rest of them will stay the same and if i actually want to remove those properties the ones that i'm not passing in with my request i need to add another option here and the option name is overwrite and we need to set it equal to true so now you'll notice that back in my postman if i send here with name and let's just keep it interesting and pass in peter check it out we have name and the complete is still there now why it's still there well because in our model we have default set to false so there is some default one if i remove it you'll notice that with output method the way the controller works right now if i send it right now then of course i'll just get the name so completed is not there anymore so if i take a look at all the tasks now in the first one actually completed is missing so that is going to be the difference where when we work with put the expectation is that we'll replace the item so we'll just pass in the properties that we want to set up in item and then the rest of them effectively will be removed but when we're working with patch we're just updating the properties that we're passing in just remember that in real life you will see the apis where the put method is used with the same functionality as the patch now in our case for the remainder of the project we'll use the patch one instead so therefore i'll remove this edit one and here as well and the same i want to do in routes like i said this is just for demonstration purposes so save it here and i also want to remove this route from my postman just so it's not in a way so say don't save and i'm back to my five routes and of course for the update i'm using the patch one and before we start refactoring our code and adding some extra middleware let's just spend a few minutes on our responses and more specifically on the other options you have when setting them up and i'll use get all tasks route as my example just keep in mind that the same goes for the rest of them and essentially when i was setting up the route i said that you have tons of options here as far as the response so in my case i'm just setting up course djson object and then i set the property tasks equal to tasks but you can also do something like this where i'll copy and paste and i'm going to go with res.status so this won't change we're just talking about the object that we're sending back and instead of simply just sending tasks you could also add the amount of tasks and for this property name of course sky is the limit whatever you want to come up with in my case i'm going to go with amount but you can also call it maybe value maybe the number of hits or something along those lines and here you're just looking for tasks and of course the length like so and also what we could do and i'll just comment these options out just so they can stay for your reference and let me copy and paste so i don't have to type arrest that status also what we could do well i could set up a flag here where i say success is equal to true and then of course we need to keep in mind if that is the case then you also need to add something here where you have the error whether that is 404 error or it's the general 500 one so effectively here i just add this extra bit of data where i say yeah the success was true and then you can even place it in the data property and then say tasks is equal to tasks and also maybe add the amount so that's also something that you might see around for example the hacker news api uses the number of hits like so essentially you just get that value and again that is going to be equal to the array that you're getting back equal to a length and once i said of course my response is going to look like this now if you don't like the success one go maybe with status that's also something that you might see around where we set up status is equal to success for the successful responses and then for errors of course we're going to go with status and then fail or error or whatever string value you might want to set up and if you're wondering why am i showing you this is because i want you to be aware of your options so just because i'm setting it this way where i just pass in the tasks of course that's not a rule that's pretty much my preference and why i don't prefer setting up the statuses or successes or the data here that is simply because of the front-end so in my experience when we use front-end there's two things that are going on effectively when we have asynchronous responses we already have try and catch and because of that i find the status or success to be a bit redundant because effectively just like i showed you with delete if i'm successful then of course this code will run regardless and then if there's some kind of error then of course i'm gonna have my code e in the catch block and why i don't like setting up the data well because on my front end usually i use axios and if you're familiar with axios it right away returns a data property so it right away has that data object so if you set this response in such a manner where you have data returned in the object then on the front end you'll have data and then in that data object you have another data so essentially on the front end you need to do something like this where there is a data object inside of that data object there's another data object and then you only get the tasks which is of course not the end of the world but in my case again i find it a bit redundant and lastly when it comes tutorials and courses i also enjoy the fact that there's less typing in the setup where i just pass in the tasks so be aware of your options my suggestion is whichever route you pick just stick throughout the api so there's no confusion don't set up one type of response for one route and then go totally different in a different route that's going to be very confusing to whomever is using your api and lastly let me just say this yes you can set up your own api responses however you like but if you want our front-end app the one that's sitting in the public to work properly the responses have to be exactly the same as mine because that's what the app is expecting if you'll set it up willy-nilly then you might get some bugs not bad not bad once we have discussed our response options next i want to work on route not found so at the moment life is awesome we have our application everything works if i go to index.html of course i can see the application if i go to api then version 1 and then tasks of course i can see all the tasks what happens if i go with api version 1 and then hollow so i have cannot get api blah blah blah and i can clearly see in my browser that of course we get 404 error but essentially this is going to be the default one and instead i want to set up the custom one just like they have in algolia one or again if you're looking for some kind of resource and the server can find the resource and essentially we still get the 404 but of course the value here is unknown now it doesn't really matter what you set up as far as the value just want to showcase how we can set up a custom 404 response and the way we do that we go back to our application here and then in the app.js i want to remove these comments because i think we're clear on the rest api and location here is very important so we have the middleware for public and json that still stays the same then we have all our routes for the tasks and then right after that we want to go with app.use and then we'll pass in our middleware function the one that will handle the 404 and send some kind of custom response now we haven't created it yet so let's go back to our starter we'll create a new folder because there's going to be a few middlewares that we'll set up in the upcoming videos so say middleware and then inside of the middleware we want to go with new file and i'll call this one not surprisingly not found and js and as far as the logic well we'll still have access to oreck and res so we just need to come up with function name in my case it's going to be not found and i'll set it equal to rec and res and then as far as the response i'm just going to go with res dot then status and of course in this case it's 404 so the server is letting the user know that it cannot find the resource and then as far as the message i'll just use the simple send and i'll say route does not and exist so now of course we just need to export this and we do that with module then exports of course and we'll set it equal to our not found and then back in the app.js above the app.use i guess we're going to go with const not found is equal to require then we're looking of course e in our middleware so let me say dot middleware and then more specifically we're looking in and not found and then in the app.used we'll just stick not found one and once we save and in this case i'll just use the postman just so you can see that it's going to work exactly the same and if we're looking for the url and then we'll go with hello now of course we have our custom one we have route does not exist which is pretty awesome and just to showcase that it's going to be the same scenario in the browser as well notice once we refresh we have route does not exist so we set up the middleware folder in there we have not found.js and then back in the app.js we import the function we set some kind of name in my case it's not found and then all the way in the bottom we go with app.use and we pass in the function and in that function we'll have access to rack and res and in our case we're just interested in the response and we'll set up a 404 with whatever message we want to send back awesome and up next i want to work on asynchronous wrappers for all our controllers why well because we have asynchronous operations and yes it's very useful to use these try catch blocks but you'll have to agree with me that it becomes somewhat redundant pretty much for every controller setting up try and then catch and as you can see essentially i'm just copying pasting the code around so there has to be a better solution and that better solution is to create a middleware function that essentially will wrap our controllers and in there we'll just set up the functionality where we don't have to repeat ourselves and before we continue let me just say that there are some npm packages that do that for us and most likely in the upcoming project we'll use them instead since that way we can save some time on the setup but i think it's very important to have at least a general idea of what the package is doing instead of blindly installing it and therefore in our first project we'll set up the basic logic ourselves and we'll start over here with new file and i'll call this async js and then inside of it i'm just going to go with const async wrapper so i simply create a function at the moment nothing's happening here and then i want to export it so module exports and then a sync wrapper and once we set up the export now of course i just want to go to my controllers and import that middleware so i'm looking in the middleware and i'm looking for async so in here let's just call this a sync wrapper again and that is equal to require then we navigate to our middleware folder and of course we're looking for the async and now what we want to do is wrap all of our controllers now i'm not going to wrap all of them right away i'll just start with get all tasks just so you understand how it is going to work so what we want to do here is just to take this async wrapper this function and just wrap our current controller and essentially it's going to look like this where we go with async wrapper and we pass in the controller the current controller as an argument and since we know that we can do that in javascript we are in good shape so we pass it in and then back in the async of course i need to set up the parameter so since i'm passing in already in the controllers my function my controller as an argument back in my thing.js my middleware i just need to go with some kind of parameter now you can call this callback you can call this function it doesn't really matter in my case i'm just going to go with fn and what am i trying to do here well i'm trying to avoid this try catch so essentially i want to have my cake and eat it too where i can still use this nice await syntax but i don't have to set up these try catch blocks how can we do that well we set up the try catch blocks inside of the wrapper and the first thing that i want to do from this function is to return another one so in here i'll say return hsync and then if you remember in the express by default we right away got request response as well as the next so that's what i'm trying to do over here since i wrapped my controller in my middleware and if you pay close attention we're actually invoking the async wrapper right away now of course i want to pass in those requests response and next down to my function down to this controller correct because now of course i wrap my controller in my middleware and the way we do that we return another function since i'll use a weight inside of the function body that's why i set it up here as async and please please please keep something in mind where these ones the rec res and next will have access to right away because at the end of the day we return another function from async wrapper and then inside of the function body one of the things that i want to do is pass these rec res and next from express down to this function so hopefully that is clear again we get these ones by default the reason why we have access to them because from our async wrapper we actually return another function so that's how we'll have right away access to them and then in the function body we'll decide what to do with our parameter with our argument which is our current controller and as far as logic i want to go with try catch block and then inside of the try block i'm going to go with a weight and function and here we'll pass in rec res and next and then once we have passed all of these things down to our controller of course now have access to them in here as well and then also since there might be a case for an error we'll go with next and then we'll pass in the error and if you're wondering what's happening over here essentially we're passing this to a next middleware which we haven't set up yet in our app.js so that's what's coming up in the following videos we'll set up another set of middleware and in this case we'll deal with errors so once we save over here we can go back to the controllers and now i can remove the try catch block so remove the try catch block completely and at this point you should only have these two lines of code where we're waiting to find all the tasks and if we're successful we send back those tasks and as far as the async wrapper we take our controller as a argument and then since we return the function we have access to rec res and next that are coming from the express and we set up the try catch block and in here we have a weight because our controller is still async and we know that by default a sync function will always always return a promise so in here i just have a wait and i'm waiting for that promise to be settled either resolved or rejected and since my controller will still need to access rack res and possibly next since i get them from express i pass it down to my controller and then if there is an error so in here if we trigger some kind of error whether in get all tasks or any of the controllers then of course we'll catch it over here and we'll pass it to a next set of middleware which we haven't set up yet and now of course once we have everything in place now we just want to apply these changes to all the routes now i fully understand that some people are very negative about refactoring the code and to some degree i sympathize with that because i also hold the opinion where it's not very useful if we're all the time refactoring the application but it was important for me to show you the long way first because that way you have a good understanding of how everything works and now we just set up the middleware that actually handles that so let's go back to the controllers and slowly but surely let's add this a sink wrapper to all the routes and the setup is going to be following for all of them where we start with a sync wrapper so we set up our two parentheses here and we need to make sure that second parenthesis the closing one is right after the curly brace correct then we want to remove the try block as well as the catch block and again we'll be just left with a weight does that create if we're successful we send back the task and effectively we want to do that for all our controllers so let me go here with a sync wrapper same deal wrap this guy here and then we have try and we remove the catch but we are leaving this one so i will work with this one a little bit later for time being we'll leave it as it is with this response and once we set up our custom error there's going to be some changes here as well let's keep on scrolling we're looking for the async wrapper and again we want to add the closing one right after the curly brace we still pass in the function i'll remove my try i'll remove my catch here and we'll save it and the same goes for updating the task as well so we go here with async wrapper and we'll close it then we want to remove try and we want to remove catch and just to try it out why don't we go to create task and then i'm just gonna go with creating task creating task let's try it out everything still works i can create my task but if i'll try to add a task with an empty string value i should get the error and i do but of course this is not the error that we're sending so that's something that we're going to work on in the upcoming videos and once we have set up the async wrapper next i want to work on catching the errors and we're gonna start our journey actually in the express documentation so go to express.js.com and then in search box just type error and first let's take a look at the default one and if you take a look at the first sentence express comes with built-in error handler that takes care of any errors that might be encountered in the app this default error handling middleware function is added at the end of the middleware function stack and if we pass in error to the next and you do not handle it in a custom error handler it will be handled by the built-in one why am i telling you this well because that answers this question where is this response coming from well that is coming from the default built-in error handler that's point number one i want to make otherwise you might be wondering well where are we getting this info second next correct that's why in the async wrapper we set up this next and error so we passed it to the next middleware but in our case of course we haven't set up that handler yet so therefore it was just eventually passed down to the built-in one and lastly if we go back and if we say here error so i'll search one more time and in this case we're looking for writing error handlers so this is what we're about to do we'll set up another set of middleware however in this case the middleware will handle errors and you can see that if we want to handle errors we just pass in four arguments and then the first one will be that error and then we want to place that at the very end of our route so let's just navigate back and of course in the example they showcase how they right away set up the middleware in the app.js in our case since we'll have more code essentially i want to create another file in the middleware so in here i'm just looking for new file and i'll call this error and then handler and inside of the file i just need to come up with the function and i'm going to go the long route where i'll say error handler middleware and that is equal to error again in this case we need to have four parameters request response and we also have next and as far as the logic we'll add more code once we set up our own custom error class but for time being we just want to go with return and res that status and if you remember that's exactly what we had previously e in the try catch block and i'm just going to go with 500 and we'll say json error and error is equal to error now if you want you can cancel log it of course but the result is going to be exactly the same where in here we'll have access to that error the one that is going to be coming in our case from this async wrapper and then we just need to decide what we want to do and i'll just start by setting error equal to error and you know actually i want to go with message is equal to error and now we simply want to go back to app.js where we have not found let's just copy and paste and now we just need to come up with a name and as you know naming is probably the hardest thing in programming so in my case i'm just going to call this error handler and then middleware and of course that one is coming from the file that we just set up the error handler and then we want to scroll all the way down and right after not found we're gonna go with app.use and of course we'll pass in the error handler middleware and once we save and we go back to the postman and try to send the same request meaning the request with a incomplete data then we should get a different response but we don't effectively it looks like i have a bug so let me check the error handler and yes of course i didn't export the function so let me go with module exports and that one is equal to a error handler one and of course if i test it out right now i should see the custom response and we can clearly see that because we have the message now like i already mentioned previously if you don't like these big massive error messages you can simply go back over here and instead of setting the message equal to an error you can just hard code some kind of message so you can go something along the lines of something something went wrong comma try again later this is what we'll see in postman again we send and now of course our message is shorter so essentially this is how we can set up a custom error handler in express where we add another piece of middleware and then in there we have four arguments and the first one is going to be the error and of course in our case the way we pass the errors down to this custom error handler is by using the async wrapper and there we have the next so as you remember from tutorial with next we pass it to the next middleware and previously we used the built in default one and now of course we have our own where effectively you can set up whatever logic you want if you want to send this as 200 nothing stops you from doing that but of course a more meaningful response would be with some kind of error code and with some kind of meaningful message whether that is hardcoded string or you can pass in the entire error object and right after we set up our custom error handler let's work on our 404 responses too and essentially i want to set up a custom error class which extends from the general javascript error class and that way we can handle all of our 404 responses in our newly created error handler as well and we're going to start by navigating back to the controllers and the routes or controllers that i'm looking for are following i want to work on update task here we send the 404 then the same is for deleting the task and of course getting the task and let's just start over here with getting the task and simply i want to showcase that we can create a new error object if we run the built in javascript error constructor and we go here with const and no surprise i'm going to call this error and that is equal to new and then we just go with error and here we pass in the message so i can say not found and then next line i'm just going to go with error so now i'm dealing with the object that i just created and i'll set another property on it and i'll say status so that's the name of the property and of course the value will be 404 so now if you want you can console log it here or what we can simply do is use next and pass this guy down to our custom error handler remember that's how it works we call next and then we pass in the error and of course in this case we are creating that error ourselves instead of getting it from the mongoose and the only thing that's missing right now is in our controller because we don't have the next so i want to go here with next and then we need to go with return again i already mentioned why we want to do that because we don't want javascript to keep reading the code now of course we have this one right now but hopefully you get to just where we need to go with return and then next and now of course i want to pass in my newly created error object and once i do that if we go back over here in the error handler and if we simply cancel log we should see our newly created error object so i'm going to go here with cancel log and i'll look for my error and now let me go back to the postman and essentially what i want to do i want to get all the tasks and then i'll look for one of the ideas but again i don't want to get that cast error so i still want to keep the same structure i just want to pass in the wrong value so i'll look for single task i'll copy and paste and then instead of three i'm gonna go with four so once we send of course we get our custom error message as vague as it currently is and then of course in console i can clearly see that i have not found so of course that is going to be my message and i understand that might be a bit confusing but effectively the idea is following where once we create this new error object that property is going to be on there so in order to access this string value we'll have to go over here and simply go with error and then that message and as far as the status well we can clearly see it here you can have 404 so now just for kicks what we can do is set up message is equal to error message like i said there's the property on that object and then as far as the status well i can simply change this one around where instead of 500 i'll pass in error and then status and don't worry of course there's more code coming and once i have applied these changes of course we can swing back to our postman and check it out now of course we have 404 and then the message is not found so that's pretty cool now of course we just need to go back to the tasks and set it up in such a way where we don't have to do this all the time manually and the idea is following where again we'll create a new class a new custom error class and we'll extend it from the javascript error and then we'll create a new instance and yada yada and effectively the way we want to do that we want to create a new folder and i'll call this errors pretty self-explanatory so we're going to go here with new folders and we're going to go with errors and inside of it i'm going to create another new file and in this case i'm going to call this custom and hyphen error and of course i'm going to add the js extension and then instead of my custom error now i want to extend from the error class now here's the deal in this case i'll just write out the code and then i'll go line by line of what's happening because i think that's going to be a bit more productive so let's go here with class and then we just need to come up with a name in my case i'm going to go with the long one i'm going to say custom api and then error now we need to use the extends keyword and since i want to extend from the error class i'm going to go here with error and as far as the functionality we want to go with constructor and here we'll pass in message and status code and then inside of the constructor we want to call super then pass in the message and right after i call super i'm going to go with this dot status code and i'll set that one equal to whatever i'm passing in the constructor so in here i'll pass e in the status code and as far as these few lines of code a constructor method is a special method we invoke when we create a new instance of a class and in our case we'll pass in two arguments an error message and a status code then since we're extending basically we're setting up a child class we need to call super method which in turn invokes a constructor of a parent class and in our case we pass in our message value as a result we'll have access to all the methods and properties of the parent so in our instance we'll have the message property and with this dot status code we create a status code property as well and that's how we can create our new custom error class and essentially if you want to create new instances you can simply go with custom and then api error and then pass in those two values the message and status code but i actually like to set up a new function that does that for me and here i'm going to go with const create custom and error and this function is going to be looking for two parameters a message and then a status code and what i'm going to do is from this function i'm going to return that new instance so i'm going to go to return new and then we're looking for custom api error and then of course we'll pass in the message here as well as the status code now of course if you want to keep the same parameter names you can definitely do so but in my case i'm purposely setting this up so you can see that this is coming from the function as far as the message and of course i pass e into my custom api error more specifically in the constructor as a message and then of course we just need to export this and we'll have to export both of them and you'll see in a second why so we're going to go with module exports is equal to an object and then we're looking for create custom error and then custom api error and once we have both once we have the class as well as the function and we're exporting both now of course we want to go to the tasks we just need to remember that of course we're exporting object so therefore we'll have to provide a specific name in our case i'm looking here for the function so i'm going to go with const i'll set up my curlys and i'll say create and then custom and error so of course that is my function set it equal to require i do need to go two levels up so in here we're looking for the errors and then more specifically i'm looking for the custom one and then i want to replace all of these three instances and of course i want to remove this manual code as well so start over here and then i'll keep this one for the second just because i want to reuse the same message and the idea is following where we go with return then next and then instead of the next we pass in create custom error and of course we want to pass in the message so that's why i'll just copy this one just because i want to speed this up and then the second thing is going to be my status code which of course is going to be 404 and now we can remove the second line and we just want to copy and paste so it's the same deal over here and the same in the update task as well and once we have all of this in place now we just want to go to error handler so our custom error handler and instead of looking for the function we're looking for the class because in here i want to check if the instance is equal to our customary one then of course i'll pass in the status code and the error message however if there's any other error then of course we'll just go with res.status 500 and whatever we had before so let me go at the top and i'm going to go with const again it is named import so we're looking for custom api and then error and that is equal to require and same deal we go two levels up we're looking for errors and more specific custom error and let's right away set up the default one and this one i'll set it back to 500 here and then as far as the json let's go with the same message i'm just going to say something went wrong please try again and above this return we're going to go with if and then we'll check if the error is the instance of our custom api error then of course i want to go with return and i want to pass in the res dot status and then that will be equal to a error dot status code because of course that's where the value is sitting in that property and then when it comes to the actual message same deal i'm gonna go with message and this will be equal to error and then we're looking for the message property and once we save let's go and test it out or essentially if i send it here from the postman of course i'll have no task with this id and if i'm going to mess with the syntax i should get the cast error which of course i do because i can clearly see that something went wrong please try again lastly let me just repeat one more time that error handling and validation is something we're going to return to later most likely in a separate project this is just a general setup just to get you comfortable with overall ideas and later we'll work on more complex validation and error handling approach nice i think we're done with error handling at least for now and now let's talk about deployment and right off the bat i want to say that we're not going to deploy this project simply because we have not covered authentication yet as well as extra packages for security and deploying the project where anyone can tinker with all the data is somewhat irresponsible and it actually can lead to a lot of headaches but with that said there is something deployment related i want to cover and that is our port variable you see hard-coded value like port 3000 or 6000 or 7000 is decent solution in our local environment but when it comes to deployment in many environments the host so the platform where the project is hosted on may want to independently set the port value to whatever makes sense to the platform because as you can imagine it needs to handle more than just one application at the time and in order to make that possible when it comes to port value instead of hard coding to 3000 6000 or whatever we'll have to use the port variable that is available in process.env instead and set up or operator just in case it's undefined and in order to set that up we need to go to our port variable that's why in this case we set it up as a variable and then before the 3000 we actually want to go with process and then dot env and then we're looking for the port variable so we go here with port and then if it is set then of course we'll use that value if not then we'll use the or operator and then of course we're gonna go with three thousand now of course in a local environment by default it's not gonna be set so always go back to the 3000 or once we deploy it's going to be a different scenario now if you want to test it out in local environment you can actually do so and we do that by stopping the server and then we want to go with a port and we set it equal to whatever value you want now my case i'm going to go with 5000 because i believe my final one is using that so i'm going to go with 6000 and then you want to go with node and then what is the name of the file you want to run of course it is app.js and now check it out in a console we should see 6 000. now of course i still see 3 000 because i didn't save the file my apologies let me stop the server just so you don't think that i'm messing with you and let me run the command one more time and now of course in the console i can see server is listening on port 6000 and one more times as far as our logic we just say set port to whatever is the environment variable by the name of port or 3000 if there's nothing there awesome congrats on completing the project and i'll see you next one
Info
Channel: Coding Addict
Views: 23,840
Rating: 4.9847617 out of 5
Keywords: node.js, node.js tutorial, express, express.js tutorial, node.js modules, node.js http, express.js router, callbacks, promises, async await, javascript, express.js controllers, express.js server, http server, http request, http, http response, http status codes, npm modules, package.json, nodemon
Id: jIsj0upCBAM
Channel Id: undefined
Length: 184min 9sec (11049 seconds)
Published: Fri Jun 11 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.