NestJS Crash Course

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
all right welcome back to a brand new video my name is anson and in this video you are all going to learn the basics of nest js so basically by the end of this video you'll learn everything about controllers providers middleware you'll learn about uh validation when you need to you know validate a request body you're going to basically learn how to build a web application okay so before we get started let's just give a little brief introduction with what exactly nest js is so nestjs is a web framework that allows you to build back-end applications specifically back-end in node.js many people in the node.js ecosystem tend to use express but over the years lots of frameworks have been developed inspired by express now nest js is actually built on top of express so many of the modules such as passport that you use with your express application actually works in sjs so you don't need to actually re-learn a whole new authentication mechanism or you don't need to relearn everything all over again a lot of those packages port very easily into an sjs and you'll learn all these things as we progress with our tutorial series we're not really going to cover authentication in this crash course we might we have enough time but this whole crash course is really just focused on the basics the fundamentals so without further ado let's go ahead and let's stop talking let's get right into tutorial so the very first thing that i need to mention is that if you are a fast learner um you can definitely visit the nest js docs or you can use an sjs docs and follow along with the tutorial if you prefer using both documentation and video tutorials but this is the website docs.ness.js.com and they have every the documentation on sgs is absolutely amazing everything that i've learned from sjs was literally from the docs they also have a discord server too i'll leave both of those links in the description and discord server they have very friendly and helpful people so you can always go there to grab help um yeah that's pretty much it so uh the first thing that we'll need to do is install the nest js cli so what you're going to do is you're going to go ahead and type in mpmi hyphen g at nest js cli and you're going to hit enter so let's just do that real quick and this should give you the latest version of the nest jscli and the cli tool is going to allow you to actually create a nest js project it's basically just going to generate all of the necessary files that you'll need to actually bootstrap your project in other words it basically scaffolds a ready nest js project so if i type nest hyphen v this will tell me the version of the cli tool and you'll see that it is version nine okay and if you just type nest it'll give you a table of things that you can run so for example you can do nest hyphen h to get additional help right and they'll tell you all the commands that you can run okay uh the most important one that we'll run right now is the one that will create ourselves a project so we're gonna do is we're going to run nest new and then the name of your project so i'm just going to call this an sjs crash course 2022. you can name it whatever you want it's up to you okay so then it's going to ask you which package manager would you love to use and you can either select npm yarn p npm i personally use yarn so i'm just going to select yarn but if you don't use yarn or if you use something else like npm or pnp you can just select that one so i'll go ahead and select yarn and then this is going to generate the necessary files for us it'll create a new directory and then generate the files in that directory okay and by default it's going to uh set up a typescript project now i should have also mentioned that in sjs typescript first and also fun fact while we're waiting for the installation of our project nest js is actually inspired by angular so if you come from an angular background a lot of the things a lot of the concepts in this case is very very very similar to angular okay so uh we just finished uh generating our projects so now we can cd into that directory so nest js hyphen crash hyphen course hyphen 2022 and let's just type ls and we can see all of our files in this directory now i'm going to open up visual studio code so i'm going to open this project in visual studio code right now and let me just move the project over here or the text editor and then we're good to go so now uh let's go ahead and actually run our project so uh if you look at the package.json file real quick uh you can see that we have a bunch of scripts okay i'm not gonna go through every single one of these but let me zoom in just a little bit but you'll see that the important ones that we'll need are nest start dev or start colon dev so this is going to run our application in development mode and essentially what that does is it allows us to make changes to our application and every single time we do it's going to auto reload the whole application so that way we don't have to manually restart okay this speeds up development when you're ready to start your app in production mode essentially what you can do is you just run start prod okay but you also want to make sure you build your application first we'll worry about these these concepts later on but for now let's just go ahead and run so i'll run yarn start calling dev but if you're using npm you'll do npm run start depth okay yarn start dev so that's going to run our api in watch mode and you're going to see then just a second right over here we're going to get some nice uh logging and one thing that i want you to pay attention to is what is being logged okay so you see that it says starting nest application app module depends initialize that's good that means everything's great and it says app controller okay that was initialized and it mapped the base route which is the slash so if we were to go into our api so let's go to localhost port 3000 because that's the default port you'll see that it says hello world okay so that means it actually works okay this is the route that we're visiting and the response is hello world pretty cool so now that we have our project up and running let's go ahead and just talk about the files real quick so the very base project when you first generate it it'll create one controller one module one service and then a a test file also known as the spec file so this right over here app.controller.spec.ts this is the uh this is the test file for the app controller okay so if you were to run this test it should succeed assuming that you have not made any changes but don't worry about this i'm going to go ahead and just delete this file because we are not going to use it okay and i'm also going to delete the controller as well because we're not going to be using this i'm going to show you how we can create our own okay and uh we're not going to delete the app.module.ts file because this is the main uh module because you can think of this as the root module okay so because we did delete the controller file i will have to remove this import line okay so this import app controller from dot slash app.controller we're going to delete that and i'm going to remove this reference over here because that no longer exists and i'm also going to delete the app.service.ts file so this is a service file over here and we'll explain a little bit more about this in just a second let me just delete that and i'm going to remove that import for the service file and it will remove the app service reference from the providers array okay great so let's go into the main.ts file so this main.ts file is basically the entry point to the application you can see that right over here we have this bootstrap function and all of the initialization like for example when you create the nest app when you listen to the port all that takes place inside this function and it calls that function okay and then it'll just run all the code inside here so if you want to register middleware if you want to configure libraries like passport sessions you would do that inside this bootstrap function okay you can see right over here that we are calling app.listen and then we're passing in port 3000 because that's the default port you can go ahead and change this to whatever port you want i usually uh set it to port 3001 so i'll just change it to that and then what i'll do is i'll just restart it oops i'll just restart the project real quick and then we should just be able to go to port 3001 although nothing will nothing will return because we don't have a controller you can see that it says cannot get and that's absolutely fine we're going to go ahead and create a controller right now okay so let's go back to our terminal and let's exit out the application and we're going to use nest cli and we're going to generate a controller so we're going to type nest generate controller okay now if you also want to get a list of all of the different schematics is what they call it that you can generate you can just type nest generate and it'll give you a list and let's generate help i think there we go so tell you all of these schematics that are available so you can generate controllers you can generate guards modules whatever you want okay so let's just generate a controller and we're going to call this controller actually you know what let me generate a module first so let's generate a module and what i'm going to call this module is i'll call this users module so we're going to create an endpoint that will return a bunch of users so we'll generate a module first and then inside that module we'll generate a controller so you can see that when we generate a module we have a subfolder inside the source folder that's great let me zoom in a little bit more and you can see that this users.module.ts file has been created okay and it has this class called users module and then it has this decorator module which tells uh it tells nest that this is a module okay that's what this annotation or decorator is for and then inside the app.module.ts file it will automatically import the module that you just created and then add that import reference inside the array for imports so it does everything automatically for you when you use the cli so you don't have to manually configure things yourself so now that we've created a module let's go ahead and generate a controller inside that module so we want to obviously group everything together we don't want all of our files scattered all over the place so we're going to generate a user's controller that's going to belong to the user's module so to do that we're going to go ahead and type nest generate controller and i'm going to pass in the path for the users module slash users okay and then i'm going to go ahead and generate a subfolder called controllers and then i think i'll do slash users so that should create a users controller inside the controllers folder so let's hit enter and let's see what happens now you can see that inside the users folder we have a subfolder called controllers okay now you might have other controllers inside this user's controls folder so it's good that it creates a subfolder inside controllers for the user's controller folder okay but you can also you know move these follow files around if you want to it's up to you okay but uh let's go ahead and look at the files that has been created so we have this users.control.ts file we have the users.controller.spec.ts file so every single controller that you will create will also create a spec file okay which is the test file as well as if you generate a service as well it'll also generate a test file as well okay we'll generate a service in uh later on in this course so let's go ahead and look at the controller real quick you can see that this controller is basically just a class and above this class it has the controller decorator which basically tells nest that this is a controller and the parameter that is passed into this decorator is users and this is basically going to be the uh the api or route okay so for example if we wanted to visit uh routes for this controller we would have to prefix them with slash users okay and you'll see that in just a second but one more thing that i do want to mention is that if we look inside our users module.ts file you can see that the user's controller was automatically imported because we use the cli to generate it and then the reference of that import was passed into this array for the controller's property so like i said when you use the cli tool it will do everything for you and because we are working everything inside the inside our module we don't even need to worry about uh you know modifying app.module.ts because everything that we configure inside users module will be reflected because we are already importing users module inside app.module.ts okay so now let's go ahead and handle our first get request so we're going to go inside user's controller and before we do anything else let's also just run our code okay so yarn start colon dev and you're gonna see that it says uh the uh the routes resolver okay it says users controller slash user's route was resolved so that's good that means that it is it works okay it's it's uh it's actually able to uh pick up requests okay um so we're gonna do is we're gonna go ahead and handle a get request so to handle get request the first thing that you're going to have to do inside your controller is define a method okay since we're inside a class so i'm going to go ahead and name my method let's call this get users so this will basically be a function that would typically return a list of users to the user consuming this endpoint so we have our function or i should say method because we're inside a class and now what we want to do is we want to use a decorator the get decorator specifically and the get decorator is imported from nest js common okay so we can just import that up top over here and then we're gonna basically invoke this function decorators are basically just functions okay so basically now uh the next thing that we uh could also do is we could also pass in an argument inside this uh get function right we can pass in an argument to define the route for this for this endpoint so for example the base endpoint the base url is slash users but if we wanted to do something more advanced such as you know fetch right in order for us to hit this specific endpoint we would have to visit users fetch but for now i'm just going to leave this alone and basically if it's empty that means that the base the base url will just be slash user and you'll see that in just a second so i'm going to return an object and i'll just say let's just go ahead and return a fake user we'll just say username anson email and send anson.com and let's go ahead and visit the endpoint so you're going to go ahead and see in the logs it'll say because we now have an endpoint defined inside our controller it'll go ahead and tell you map users so now that route can actually be visited okay so if i were to go to localhost port 3001 slash users i'm going to go ahead and get back json okay and it says username anson email antoinetteanson.com of course if i were to remove this entirely and save i would refresh and it's going to go ahead and say cannot get because we don't have an actual endpoint okay so that's good that's good we can actually handle get requests so let's go ahead and create another get request with a more explicit route so we'll go ahead and do something where it will be something like slash users and maybe the user might have posts okay so we can do something like slash users or not users uh something like slash posts and now you don't even need the slash so we can just remove that and we can just name this method get users posts okay and i'll just go ahead and just return an array and let me also fix this to an array as well because it's an array of users so this endpoint could also return maybe all the users including their posts right if you want to be more specific but again all everything that i'm showing you is just going to be um you know uh it's just going to be examples they're not going to be real uh life uh you know uh uh responses right they're just examples so treat them as examples okay so for example this user could have an array of posts and then we can just type you know a bunch of posts something like that again just an example okay so let's just save this and let's just visit the endpoint so we're going to have to visit slash users posts and you're going to see oops okay so you can see that now it returns an array of objects okay and we have our username and email and now we have our posts so this is how you can create more defined routes okay and you can also um again nesting routes is very simple if you wanted to create another route something like maybe users or not users posts slash let's do something like comments right you can retrieve all the comments of a post right we can go ahead and do something like get users posts comments and then we can return maybe the posts maybe we can return a single post with its with its comments so let me just return a post and comments okay and then let's just refresh or let's go to the slash comments route and there you go you have your nested route so i'm just showing this to you just as an example okay just so that you are aware of how you can actually nest routes okay so i encourage you to play around with this and try to create your own nested routes and think of ways that you can return data based on the uh the nested route that the user would visit all right so now that you know how to handle get requests let's go ahead and make this a little bit more complicated let's learn how to handle post requests so post requests basically are used for creating a resource on the backend server so for example if you were to create a register form right that registered form when the user submits their data it's supposed to make a post request to the server okay so to handle post requests that we would do the same thing with get request we would define a method so let's define a method called create user and what we'll do is we'll use a post decorator or the post decorator and that's also imported from nest js common package and this is also a decorator so we're going to invoke it remember because it's a function and similarly to the other routes we could also pass in an argument here which would represent the subroute or the nested route so for example if you want to do something like slash users slash posts you just name that endpoint posts so in order to make a post request that would invoke this method you would have to make a post request to slash users slash posts okay but we're just going to leave this alone and what we'll do is we'll send a request body to this endpoint but how do we handle request bodies well uh what we want to do is we want to use this rec decorator and it's just basically short for request okay so this is a function and then what we can do is we can name the argument request and the data type for this is actually going to be request okay and it's the interface that comes from the express package so remember how i said earlier that nest is built on top of express so a lot of the data types and interfaces and all those classes are going to be a lot of them are used from express so you want to make sure you type annotated from the interface that comes from express not from anything else so make sure you import it from express import request from express okay so what we can do now is we can go ahead and console.log the request body and i'll just return a response and because we're because we're actually passing in the request argument inside this method we do need to also get the response body as well so we can use the res decorator similar to the rec decorator but res is for response and then we'll name the argument response and then we type annotate it with the response interface that is imported from express as well okay so similar to express you would do response send and you can send whatever you want well i'll just send a string for now okay so now to test this i'm going to use postman you can use curl or you can use powershell i think it's invoke rest method for powershell but you can use whatever method you want to test this post request i'll just simply use postman all right so i'm on postman right now i'm going to go ahead and make sure i select post and i'm going to go ahead and type in the url so http localhost port 3001 let me zoom in a little bit more okay so localhost port 3001 and the endpoint is slash users okay just users okay and now let's go ahead and just click send and you'll see that we get a 201 created because it is a post request so by default nest actually handles that so it will send back a tool one by default okay and obviously we didn't pass in the request body but if you look at the console you'll see that it's an empty object okay and this also automatically takes care of parsing request bodies so you don't have to do that yourself uh you know compared to express okay so let's go over to the body tab and let's go ahead and pass in some json or the request body and i'll just go ahead and pass in a username and send let's do an email as well ansnet anson.com and let's click send and let's look at the logs and you'll see that we have our request body and it is also parsed into json which is perfect okay uh so that's good we know that we have the request body and it works perfectly so now you would be able to take this data and you could do whatever you want you can save the data to a database you can pass data to another api or another micro server you can do whatever you want okay so that's how you would handle post requests okay and of course again if you wanted to create like a nested route or like a subroute right uh you can just pass in an argument for the post method and then now if i were to make a request to slash users for post it would not work i would have to make it to slash users slash create and then it would work cool so that's how you handle post requests in sjs all right so it's great that you can actually get the request body from referencing request a body similar to express and you can also reference all the other properties such as the query parameters you can reference the route parameters headers similar to how you would do in express actually it's pretty much exact right but we don't want to do things the expressway because again nest is built on top of express but nest also does provide a lot of utilities and functionalities that makes the code not even look like express so i'm going to show you how we can actually handle request bodies the nest js way and the reason why we're going to do this is because one it's going to be a lot more cleaner it's going to make validating your data a lot more easier and when you want to unit test your code it's going to be much more simpler so let's go ahead and do that so instead of actually getting the request object argument right let's just go ahead and remove this whole thing real quick okay and what we're going to do instead is we're going to use the body decorator so this is also decorated that's imported from nest js common okay and then what we want to do is we want to name our parameter you can name it whatever you want you can name it something like user payload or user data right you can name it whatever you want okay now here's the next part we need to type annotate our argument but what exactly do we type annotate it with okay so what you would type annotate this with is what is called a data transfer object okay so basically data transfer objects represent a it's basically a schema that represents and defines how data will be sent over the network so to make things simple they basically are going to represent the request body okay so if the request body let's say if we're building a registration form we need to make sure the user provides a username password email and maybe their full name so what we would do is we would create a data transfer object that literally defines all the all those properties and their data types okay and then we would use that to type annotate our user data argument okay so let's go ahead and do that so what i'm going to do is i'm going to go ahead and do this i'm going to go ahead and create a folder called dtos inside the users module and i'll create a new file and i'll call this create user uh let's call it create user dto.ts okay and uh and then that's actually you know i'll call it createuser.dto.ts because that's what the nest js docs does and i want to be consistent with an sjs dock so let's do that and now what we're going to do is we're going to create a class called create user dtl okay and then we're going to define all of the uh properties that we'll need um so for example we'll need a username and the data tip is going to be a string and then we'll also need an email and the data type will be a string and you can add whatever fields or properties that you want okay so now that we're done all we're going to do all we're going to do now is we're going to type annotate this user data argument with that dtl class so create user dtl that's going to be imported from up top here and watch what happens when i come to log user data okay and let's just go ahead and return a an empty object so let's go ahead and call this endpoint with a post request so it's going to return an empty object and remember because it's a post request nest will handle the status code for us unless there was an error that happened right but if we look at the logs you can see that we have our object now this is nice because now i can actually reference the properties i have type i have type safety so i can actually reference the properties and i have intellisense over here okay whereas if we just reference request.body typescript wouldn't know what the actual data types are so that's good so now one thing that i will mention and we'll we will talk about this later on in the crash course uh if we were to omit properties from our request body there's no validation that is happening right now okay so by default it's not going to validate anything for you but later on in this course you'll learn how to validate your request bodies we're not going to worry about that right now okay but now you know how you can actually use the body decorator and type annotate your request body so you don't have to use the request object itself okay so let's go ahead and move on and let's just go ahead and talk about other things that you can do with the routes so for example if you wanted to work with route parameters the way that you would do it in nest is let's first let's just first define a method so i'll call this get user by id okay and i'm going to use the get decorator and what i'm going to do is i'm going to pass in the name of the parameter but we have to prefix it with a colon so uh we're going to prefix it with a colon id just like that okay so now we can actually pass a route parameter and nest would actually recognize that endpoint now the next question is how do we actually get the run parameter well again you can use the request object but again that would be doing things the expressway we want to do it the nest js way okay so for example if i were to just do rec request request and let me just go ahead and get the response object real quick and the console.log request uh params right i'm not going to send the response uh let me just do uh this slash users let's do one two three uh let's see what's going on here oh yeah i think we do need to send a response whoops okay let's do that real quick okay so you can see that right over here that the request.params object does give us the request parameters but again we want to do things the nest chase way so instead of doing that we would use the param decorator okay and that is also going to be imported from nestjs common and then inside the argument for the parameter we're just going to pass in the name of the route parameter in our case it's just going to be whatever we named it up here okay so it's just going to be id and then what we want to do is we want to type annotate the argument so uh it's going to be id string so now what i'll do and i'll console.log the id i'll just go ahead and return the id so let's go ahead and click send and you're going to see that's just going to return us whatever id that we specify as the value for the route parameter which is and that which is pretty cool and that's how you handle route parameters it's very similar to how you do it in express except for the way that you extract the parameter okay and of course you can also have nested uh you can have nested raw parameters as well so let's say we want to do something like uh slash id slash and then let's do uh post id just an example right and then i can extract that parameter as well so since i named it post id that's what i've to pass in and then post id and then it's going to be a string okay so now if i wanted to uh just send two raw parameters i could okay so let's do 300 and just do 400 and then you'll see that's what happens so that's how you can work with round parameters okay next thing that i'll talk about is query parameters and then we'll move on so uh with query parameters uh in express you would reference request dot query but in nashes we have a decorator called query and that allows you to extract the query parameters so let's say you know for example query parameters are best for whenever you want to do filtering um so things like you know filtering by the user's uh you know email or their username or when their account was created things like that right you would use query primers for that um so let's go ahead and let's do something like this let's create let's remove this raw primer over here and let's just remove this and let's also remove this so we'll just return back to only the id as a real parameter okay so the next thing that we'll talk about are query parameters so query parameters are best used for doing actions such as filtering so for example if you want to filter users based on uh what the first name what the first uh letter of the alphabet starts with you could do something like that if you want to sort by alphabetical order or you know which user was created first you could use query primers for that they're also good for pagination as well but what i'll do is i'll show you how we can handle query parameters so i'll use this get users route um so what i'll do is i'll go ahead and use the query parameter decorator that's also going to be imported from the nest js coming package and we're going to pass in the name of the queer parameter so in our case uh we'll just have something something let's do something like sort by right and then i'll just call the argument sort by and then i'll console.log sort by and i'll show you how we're going to work with this so let's go ahead and go to the get user route which is just the regular the base user's endpoint so let's go to here and you can see right over here if i uh make a request in the console it's just going to log undefined because we did not send that query parameter but if i go ahead and send it right now so if i do question mark sort by equals unless you do something like uh [Music] i don't know uh ascending order asc asc is short for sending so let's do that and if i look at logs you'll see that it says asc okay you could also add as many query parameters as you want okay similar to the raw parameters and then you can extract them however you want okay um so that's pretty cool that's how you can work with query parameters all right so now that we know how to work with get and post requests and we also know how to work with the query parameters as well as route parameters the next thing that we're going to move on to is validation validation is something that is very very very important when you're building web services because if you let your users send data to your server without validating it you're going to run into a lot of issues it could break your application it can make your application more vulnerable to malicious data being sent in the request body so it's very important that you validate all of your request bodies so i'll show you how to validate the uh the request body for our create user endpoint and then i'll also show you how we can validate other things such as query parameters as well as route parameters so let's work with just the uh let's just work with just the request body first so let's revisit our create endpoint so let's make a post request to slash users slash create so you'll see that our create user dto right we have two properties to find username and email but we're still able to send a request body without the email just fine okay that's not good because what if we want to create an application where we want users to sign up and they just don't send certain fields to the server okay you want to make sure you're validating the data and making sure that they actually send the required details the required fields so let's go ahead and actually validate our request body so in order to do this we're going to need to install an additional package so we're going to need to install class validator as well as class transformer and if you need a reference to using validation you can just go ahead and visit the sjs docs go over to techniques and then select the validation section it will tell you everything but let's just go ahead and install class validator and class transformer okay so once that's done let's just rerun our application again and then what we're going to do is we're going to go ahead and do this we're going to go into the create user dto okay and so so far right now nothing's happening right we install those packages nothing has happened okay just want to make sure let's go inside the dto and we're gonna go ahead and uh annotate our properties okay you don't have to annotate every single one but you should annotate the ones that you must have the user send to the server so in our case we're going to make both the username and email required uh fields that the user must send to our api so for the username we're going to use a decorator called is not empty okay so this comes from the class validator library okay there's lots of decorators that you can use so basically this just tells this just validates that the username property is not empty so let's save this okay and in order for this to work right let's say if i just omit this right now nothing will happen in order for this to actually work you need to actually register register the validation pipe for this endpoint so we can do that very easily by using the use pipes decorator so right on top of the method create user and then all we can do is just pass in a new instance of validation pipe like this whoops yep oops like that so let's save and let's go ahead and make a request and you're going to see now it's going to give you an error it gives you a 400 status code and it says username should not be empty that's good okay that means that it's actually validating the data so let's also validate the email as well so nice thing about class validator is it has lots of different decorators and as very specific ones too so one of the ones that i like to use a lot whenever i'm building applications for email where the user has to enter the email is i like using the is email decorator okay and then you can also pass in options too if you want to configure it but this will ensure that the em that the the email property is actually an email so let's save this and let's also make sure that it's not empty as well but even if the user were to send in an empty value for email uh it would automatically reject that because an empty value is not an email but let's just go ahead and send and you'll see that it's going to give you all of the errors right it says username should not be empty email should not be empty email must be an email okay so now let's just go ahead and actually pass in values and if i just hit send it's gonna oh wait let's send it again it's going to now give me an error for email but not for user name okay now of course if i were to uh remove that is not empty if i hit send it's going to complain saying email must be an email obviously because email is not fined right or whoops let me just fix that there we go see must be an email so you could add that is not empty if you want to let's just leave it like that for now so uh let's go ahead and just add an email so let's just say anson and notice how if i just hit enter right it's not going to work because it says email must be an email anson is not an email but if we use them like at right gmail.com then it will work right it's very very good i really like using this validator a lot okay so that's pretty much how you can validate post requests pretty cool so let's go ahead and validate other uh other things such as query parameters as well as um route parameters so let's say for example right if we look at our get users get user by id method over here you can see that by default all of the route parameters as well as query primers will be strings right but what if we want our route primer to actually be a number right what if we want the user to ensure that they are providing numeric values for the id right well they certainly will provide a numeric value but it will just be converted as a string right by default but what we can do is we can actually get it to automatically convert to the correct data type in our case we want to convert it to a numeric value so what we can do is as a second parameter or as a second argument for this parameter i can go ahead and pass in the parse int pipe okay and that's going to be imported up top over here from nestjs common package okay and so what this will do is it'll basically just parse this id into a numeric value so instead of type annotating as a string we will type annotate it as a number okay so let's go ahead and try to visit this route so let's make a get request to users slash one okay if we look at the logs it's going to go ahead and log one now if we did not parse this and not and if i were to just send this again you're going to see that now it sends it as quotes right and you can see that um the logs over here so in the terminal it'll actually it'll actually color code the numeric values you can see over here it's just a plain white value okay but uh if i were to change it back to parse into pipe if i were to click send you can see that now it sends back the id in a numeric value because it doesn't have quotes and in the terminal the color is yellow so that's a good indicator that it is working if i were to go ahead and just pass in like a string value it's going to throw an error it says validation failed numeric string is expected so that's good we know that we can validate our route parameters and this is good because if you're building apis that expects numeric ids which typically ids are usually they're most of the time they most of time are numeric assuming that you're using mysql then you can use parse and pipe to validate that which is good okay uh and of course if you wanted to uh if you wanted to do if you wanted to parse your query parameters you could also do that as well so let's go ahead and also parse query parameters as well so let's say if i wanted to have a query parameter be a boolean value i can use a parse wool pipe okay so i'm going to call this uh i'm going to call this a query parameter uh actually no i'm just going to remove this i'm going to change this to let's call this sort asc or sort desk for sort descending okay and then the data type for this will be boolean then we're going to use the parse bool pipe and that'll be imported up top there okay so just note that using this pipe will also ensure that you uh must pass that query parameter so if i were to make a request it's going to say validation failed so let's just do sort desk and if i were to pass on a string you're going to see it says validation failed because it's not a boolean value if i pass true then it's going to succeed if i pass false it looks it'll succeed if i pass 1 it won't work or zero yeah those won't work either so it must be an actual true or false value right true or false so that's how you can uh parse query parameters and again you can do the same thing uh if you want it to be a numeric value okay you would just use parts in pipe okay there's lots of different pipes so i encourage you to play around with it let's say if you want to validate files you could use the parse file pipe if you want to validate arrays you can do that many different pipes okay so i encourage you to play around with it okay so that's how you can do validation before we move on i also did want to mention something real quick if you wanted to use other http methods such as put delete patch right they have all of those decorators that you can import from nest js commons so you can see over here if you wanted to use the patch method you would just import that decorator if you wanted to use put all right you would use that decorator if you want to use delete you'd use that decorator so i figured i would mention that so you all are aware of those decorators i'm not going to cover those because it's just really the same thing as every other as the get and post decorators anyways everything that you would do when it comes to route parameters and query parameters and validation it's all the same okay so we're going to move on to the next topic so right now we're going to go ahead and talk about services and providers in nsjs so basically providers are a fundamental concept in nestle you need to understand what exactly they are but many many providers are just classes in nest and providers consist of things like services repositories factories and if you were to work with authentication things like strategy files um guards are also providers as well okay the thing that you must understand with providers are that providers are injected as a dependency so one of the things that you also should uh read up on is dependency injection we're not going to go in depth on dependency injection in this tutorial we'll talk about that maybe in a more in-depth tutorial later but nest js uses dependency injection and the whole point of dependency injection is to create one instance store that instance inside a container that the framework manages and anywhere in your application that you need the instance you inject it in the application in the part of the application instead of creating a new instance okay using up memory uh every single time you create a new instance so in order to take care of nest js's providers fundamental feature we are going to create our very own service okay so now that you understand what providers are let's go ahead and talk a little bit about services so services are responsible for taking care of uh work inside your application right you're probably wondering well can't i just do everything inside the controller right i've already taken in the request inside the controller can i just invoke a database or invoke some external api get the response and then return that to the user well you could right but the whole purpose in frameworks like nest js is to separate every single thing in its own responsible uh in its own responsible class right so typically controllers are responsible for handling the request such as taking the request extracting any necessary data such as query parameters route parameters request bodies validation which we've already done already right thanks to the validation pipe if you want to do additional things as well that are related to handling uh you know request bodies you would do that inside the controller okay and of course controls are also responsible for returning responses to the user okay but controllers typically should not contain any business logic related to what's supposed to happen uh underneath the hood such as fetching users the controller typically should not call a database directly that should be done uh in the service layer and the service layer uses something called a repository which we will talk about later okay but hopefully you understand that it's not good to have everything done at the control layer okay so what we're going to do is we're going to create a service and that service is going to just return a list of users okay and i'm going to show you how from the controllers we can invoke the service okay and of course everything that we're going to do we're not going to do anything with a database just yet we're only going to use fake data so let's go ahead and generate our service so we're going to go into our console and we're going to use an scli to do this so we're going to type nest generate now one thing that i should mention is that if you just do nest g that'll be uh g is short for generate okay and if you want to generate a service you just type service or you can type s for short okay so nest gs which is basically stands for nest generate service okay and then what we can do is we can pass the path similar to what we did with the controller so the path to the users module we'll create a new folder called services and then i'll quality service users okay so let's just hit enter and you're going to see that it's going to create a services folder inside the user's module folder right over here okay so inside the service folder it created a user's folder and we have the service file which is a class and then we have the service.spec.ts file which is the test file for the service okay so every single service that you generate will have a test file okay and you can see that inside the users.module.ts file it also automatically imported the user service and added that user service reference inside the array for the providers okay so now that we have our user service what we're going to do is we're going to go ahead and actually mention a couple things so you'll notice that our user service is a class and you'll also notice that on top of the class it has this injectable annotation or decorator i should say right this is very important because every single provider must have this injectable decorator and that basically just means that this class is a provider and that you can actually use dependency injection nest will be able to use dependency injection to inject this service anywhere in your application that needs it okay so later on like for example if we were to create another uh controller that needs the user service instead of creating a new instance of user service it would actually take the already created instance that is managed by the by the ioc container which stands for inversion of control container right is going to be managed by the container and it's going to take that instance from the container and inject it into the controller that needs it or anywhere else you need it right anywhere in your application other services might also need to inject other services so that's also something to mention as well okay but right now our controller needs our users service so let's go ahead and inject it inside the user's controller so the way that you inject your dependency is you go ahead and you uh implement a constructor for the class for your controller and it's similar for services too so if you were to inject a service in another service class you would also do it in the constructor as well so what we want to do is we want to do private which is the keyword right private and then the name of the user service so user service like this and we want to type annotate this variable as user's service okay so what's going to happen is it's going to use dependency injection to inject this user service into our controller okay now right now we actually don't even have any methods defined inside user service let's go ahead and define some so remember our service class typically is responsible for handling business logic so business logic can consist of literally anything that your application needs to do so in our case our business logic would be something like fetch all users right so we're going to go ahead and create a method called fetch users and it's just going to return a fake array or fake data like i said it's going to return fake data but the whole point is to uh separate all of your responsibilities down to its corresponding layer okay so we're in the service layer right now the service layer like i said we can pretend like it's calling a database right it's calling mysql or mongodb and then we're going to return whatever that is so i'll actually just define a property called fake users and then i'll just go ahead and ascend the array and then we'll just return the array like this oh that's x has to be this not fake users there we go whoops okay so let's go ahead and now let me also remove this query parameter because i don't really need it let me go ahead and just uh return so we're going to go ahead and call this dot user service dot fetch users and let's save and let's go ahead and start up our application again and let's see how everything works okay so i'm going to go ahead and call the slash user's endpoint and you're going to see it's going to return our fake data right so what happened was we called our our user service dot fetch users method okay and that method returns our fake users that's really all it does okay and again like i said you could pretend that this calls some kind of database but later on i'll show you how we can set up databases don't worry about that okay so let's just create some other users let's create corey cory let's create one more let's do something like uh let's do greg save and let's make an api call and you can see we have our users okay again again again we're pretending that they're from a database okay and of course we can also uh define other methods for service right so if our service uh so for example if our controller has an endpoint to create users our service should also have a method that takes care of actually creating the user itself so you can imagine that the service would actually need to take care of creating the record in the database so let's create a method let's create a method called create user okay and uh what we're gonna do is inside our controller we will go ahead and call this.user.createuser okay and like i said because we are already validating the data we know that user data will be sanitized and it's valid data so we could we could just actually directly just pass this data as is like that okay now something that you could also additionally do is you create a custom type for the user data because you don't really want to reuse the dto but just to make things just to simplify things i'll go ahead and reuse the dto the reason why i say this is because not every single property that is defined inside the dto is actually what you're going to pass in to the create user method right because some properties are just used just for like you know uh do like handling conditions uh you know checking certain things so that's why i'm saying that you should create a custom type um somewhere in your application and then use that so for example what i would do is i would do something like this i would create a new folder called utils create file called types and then assuming that's let me do this assuming that our data has been validated and we are only using specific pieces of information for the data i would do something like export type create user type and then i'll do some like username string email string okay and then what you can do is you can just go ahead and do user data user details right and you can type annotate this as create user type okay i'm saying this because you shouldn't really use reuse the detail but you could if you want to in our case we definitely could okay but i'll leave it like this for now okay even though they are the same properties so i'm just going to go ahead and pass in user data and we can't because crease or dto and crazy type are exactly the same okay but in case in your request body you might need to take out some properties right and then pass it into create user uh then you would have to create a custom type like we did over here so let's just move on so what i'll do is i'll just go ahead and do this i'll do this users.push user details okay and then i'll go ahead and return i'll just return nothing i guess indicating that it succeeded and then um we can just return whatever create user returns and so by default it'll create a tool one if there's any error that happens nest will handle that for us and it'll just return to 400 for us so let's make a post request now so we have our request body let's click on send let's see what's going on here oh slash create there we go so we have a 201 so let's make a get request again and we should see that new user over here perfect okay so we know that it works let's go ahead and send some more uh data so let's make another user oh it's slash create keep forgetting and now let's go to the user's endpoint and you can see that we have the new users in the array and again like i said pretend that it is inserting it into the database which is what the servers should be doing and again it's the same thing if we were to fetch user but id right we would create another method in the user service so fetch user by id and then this method would expect an id right so let's get the numeric number and then uh you would need to call your database search the database by the id search for the user by its id and then return that user i'll just return a fake user just like this and let's just do email like that right uh actually i'll just return whatever the user passes in for the id okay so let's go ahead and call this now so let's do return this dot user service set user by id and then we'll pass in the id okay so our controller has already taken care of validating the route parameter and we're just going to take that data that route parameter and pass it into the service and let the service do whatever it needs to do and then we'll return whatever the service returns okay uh so let's go ahead and go to postman and let's just hit that endpoint with the route parameter and you can see that it's just going to give me the user with the id with whatever we specify as the route parameter okay and of course in a real application if the user was not found by its id you would have to do a check such as you know if use if if the user is null then you would return null and then you could just uh in the controller you would do something like this right i'll show you an example real quick so let's just say for example right um let's do something like this um let's return null okay and let's just store this return value in a variable called user right so if user was not found so let's do if no user we can actually throw an error we can actually throw an http exception and you can pass in a response we can just say user not found and you can pass in a status and that's just we can use the http status enum and then we can do bad requests which i think is 400 i think yeah 400. so if the user's not found you can just throw an exception and nest will handle that exception underneath hood for you if the user is found then you can just return the user like that okay so let me show you how this works you can see that over here it sends us back a 400 because the user was not found right now let's go ahead and actually send something back and you can see that it'll send us back the user so that's how you can actually handle exceptions if you ever need to okay but like i said nest js it handles a lot of stuff for you and the controller is where you do things that the controller should take care of right so for example if you wanted to check if the user uh if you wanted to check if the return value was null and then do something after that you could do that inside the controller all right so the next thing that we'll talk about is middleware so middleware is basically just a function that is called before the actual route handler so let's say for example before uh create user p4 getuser id before getusers let's say i want to perform some kind of task before we actually hit this function before we actually call this function right maybe you want to make sure that users are authenticated maybe you want to make sure that the user passed in a correct bearer token or authorization token right you typically want to do those things inside a middleware function okay the middleware function has access to the request and response object and that's how you can actually you know modify those objects so for example if you wanted to check what the headers are in the middleware you would use the request object and additionally it also has the next mirror function which just basically allows you to call the next middleware it's really similar to how you use middleware in express okay the next function invoke the next function quite literally so if you have other middleware it would invoke the next middleware if you don't it will just invoke the next uh the next route handler or the route handle after okay so um what we're going to do is we're going to go ahead and set up a very simple middleware so what i'll do is i'll go ahead and inside our user's folder i'll create a new folder called middlewares and then we're going to have to create this manually you could actually just use the nest cli to do this i think i think if you do nest generate help i think you could actually use the cli tool yeah we can actually use the cli tool so i'll do that real quick so uh since i recreated the folder let me just do nest g for generate m for middleware actually i'll do a middleware because there's there's two schematics that start with m so we'll do middleware or actually you could it would be lbmi so am i from middleware and then we're going to pass in the path so slash users slash middlewares and then we'll call this middleware uh example middle i don't really know what we're going to do with this middleware but i'll just show you how it works at least so you could do something else yourself so this is going to generate the middleware and you can see that it generated inside this folder because we passed in the path so here's the middleware class you can see that it has the injectable annotate the injectable decorator annotated on top of the class which means that we can literally inject this anywhere in our application okay so in order for us to actually register our middleware the first thing i'll do is i'll just go ahead and console.log examplemiddleware just so that we know that it's going to work and we're going to go inside users module now to register our middleware we actually don't add it as a provider we actually need to configure it okay so for our users module class we're going to implement the nest module interface okay so that's going to be imported from nest js common and then we're going to go ahead and implement the configure method okay and then the argument that this configure method takes is a consumer which is a middleware consumer and what we're going to do is we're going to reference this consumer and we're going to go ahead and call the apply method and we basically want to pass in that middleware class as an argument so this example middleware so example middleware and then we want to specify what routes we want this middleware to work for so i'm going to specify for the routes i'm going to go ahead and pass in the user's route like that okay so watch this we're going to restart our application and then now every single time we visit any of our users routes it's going to uh it's going to go ahead and call that middleware function for us so let's go ahead and go to just slash users it gives us back our fake users and if we look at the console it says example middleware okay if i were to visit the endpoint slash post create and i click send it's going to go ahead and log example middleware um if i were to visit slash get and then the id so that's the route parameter right it's going to also log example middleware so we know that that's our middleware function working so if you also wanted to instead of just passing in the route itself like the hard coded route uh you could also make it uh you could also just pass in i think the controller you should be able to just pass in um the controller i think so you could do something like this um you could do something like users controller and that should work as well so let's test this out see how it logs example middleware perfect you could also exclude routes if you want to okay and if you didn't want it to work for every single route if you want if you want it to be a little bit more explicit you could pass in options right and you can specify the path um and you can also specify the method that you wanted to only work for so example if i want the path to be something like let me see uh yeah so this is supposed to be i believe a string so let's just do users and then you want the method you only want it to work for get requests so we're going to import request method and then we're going to reference dot get so this would only work for all routes and users for get request only so it would not work for post requests so if i were to go to this route um let's see what's going on here okay so actually um because we actually specified only um the user's route right it would only actually work if we visited the user's route you can see the middleware being logged right now but if i visit any other route such as create the middleware will not be invoked as you can see over here okay but um if i wanted to additionally add more routes i could you can see that if you look at the type it's literally just an array so i can just add more routes if i want to so let's copy that and let's paste it here and i can do users slash colon id and save so now if i were to visit the slash users id route with a get request you're going to see that it logs the middleware or it executes the middleware function because it's logging example middleware if i were to make a post request okay it's not going to it's not going to do anything okay so that's how you can play around with middleware you can pass in the entire controller if you want to work for the whole controller you can be explicit with the paths you can do whatever you want okay so that is uh uh pretty much it when it comes to configuring the middleware one more thing that i will also mention is that if you want to actually perform more logic inside the middleware again i'm not sure why it generated this function with any it should really just be request because it is a the data type is actually the request same thing with the response as well so let's do that and the function should actually be i annotated as next function like that okay so again you can literally reference all the properties right so you can reference request.body you can reference request.query typically for middlewares you should do things such as checking the headers right for example request the headers so i can do something like request.headers i can check what the authorization header is um so let me just log that real quick so let me make a get request real quick oops see that okay so you can see that it's undefined so let's go ahead and pass in an authorization header so what i'll do is inside headers we'll pass in authorization like that i'll just pass in a random string okay so now you can see that in the console it logs the actual value so we could do something like this right i can go ahead and say let's let's get the authorization property from request.headers and i can say something like if authorization is equal to this well let me actually do this instead let's do this if no authorization throw new http and we can actually throw an exception similar to how we did in the controller in the previous part of this video and i can throw a i can throw an http exception and the response can be uh no authorization token and then i can go or i can just say something like invalid authorizations we can and for the status i want it to be a forbidden which just means it's going to send back a 403 so if the authorization token is in fact defined we want to compare it to the correct value and like as i said this would be any value i'm just going to put a hard-coded string just for example so if it is equal then what i'll do is i'll call next okay um cool so um now if it isn't if it isn't i'll throw another error and i'll say uh invalid authorization token okay so basically now our middleware has has flow right so we need to make sure we pass in the correct authorization uh header so watch this so i'm going to go ahead and not pass an authorization token and it's going to give me a 403 and that's coming from the middleware if i pass in the authorization header but if i pass in an invalid value it's going to say invalid authorization token if i pass in the correct one it's going to call the next function and that next function is basically just going to invoke um the next the next function right that's what it is and the next function in our case is really just the uh the route handler now one more thing that i will also mention is that if you wanted to apply more middlewares because sometimes you might have a lot of different middlewares that you want to apply before actually uh calling the route handler right you can you can also do that right you can basically just call apply as many times as you want so let's go ahead and just create another middleware real quick so let's just do nest g mi so i might show it for middleware and i'll call this uh i'll call this uh just i'll just call it whatever so let me pass in the path so we want this to go inside the slash users slash middlewares folder and then i'll just call this middleware another middleware again you can call it whatever you want but it's just an example so it's just going to create the middleware file and it's test file okay and what we'll do is i'll just write as a blog and i'll just say console.log another middleware and again you could perform whatever you want in here similar to what we did in the example middleware we checked the authorization token maybe this middleware could check some kind of signature let's say for example if you're working with webhooks webhooks web hooks typically have you know like a webhook secret or a signature that you want to make sure you validate so you can do that inside here for example but i'll just console.log something and then we'll just call the next function okay and then what you want to do is inside the users module right after we had applied our first middleware and then after we called for routes right we want to go ahead and call apply again we want to pass in that that another middleware so we want to import that up top over here and then we want to specify the routes of course because we're not done yet so for routes and then again you can have this you can just pass in the whole controller to have it work for every single controller or you can be explicit and have it work for every s or have it work for only specific routes so what i'll do is i'll just copy and paste this and paste this in here so literally the same exact routes okay so what i'll do is i'll go ahead and now let's pay close attention to the logs so if i go ahead and visit the get user's endpoint it's going to get me all the users and watch what happens it logs example middleware it logs the authorization header and then it logs under the middle where you see how the order of it is actually is that it's in order right it's basically in the order that we apply the middleware if we were to apply the another middleware first before example middleware then that function would be called first right so for example if i were to just take this move this down here and if i save and then hit send you'll see that now it logs under the middleware and then example middleware see how that works pretty simple it's pretty pretty straightforward but yeah that's pretty much it when it comes to middleware okay and finally if i were to just call the create endpoint you'll notice that it doesn't invoke the middleware at all well actually let me save this again because i think those logs were from previous call you'll see that it does not invoke the middleware at all because we did not specify that path okay so that is pretty much uh most of the things that you'll need to know when it comes to middleware if you need to know more about the additional things that you can do with middleware just visit the nest js docs there's a section under overview and just click on middleware and they'll tell you everything that you need to know but this is the most basic things that you would need to know when it comes to middleware all right so i want to go ahead and talk about pipes in sjs now i know earlier we did get a little brief introduction to pipes but we only really used them but never really understood uh everything about it so i want to talk about pipes a little bit and i'll show you an example of how we can actually create a custom pipe but before we do that you need to understand what exactly uh pipes are really used for so it has two typical use cases the first one is transformation so if you wanted to transform a certain properties from like you know a string to an integer or integer to string or let's say if the value happens is supposed to be a boolean but it is a string data type you can convert it from a string to a boolean and uh you can also use pipes for validation which is what we actually did earlier right we used the validation pipe to validate if the request body uh was valid if the route parameter was an actual numeric value okay and they will throw an error if the data is incorrect okay uh so we already we already mostly handled validation but i'm gonna go ahead and show you how we can actually uh use transformation with pipes and i'll also show an example of why you would want to do this so first thing that i'll do is i'm going to go inside my create user dto class and i'll define another property and what i'll do is i'll call this property age so the age of the user and i'll use the is not empty uh is not empty uh decorator now there is actually decorator called is number but if i use that that will defeat the whole purpose of this whole tutorial so i'm going to show you uh what's going to happen okay so we have our age property uh type annotated as a numeric value a number and let's go inside our controller now so let's go ahead and console.log user data okay so what i'll do is inside postman i'm going to go ahead and pass in the age property and i'll pass in a number so you see that it gives me a 201 everything worked fine and if you look at the logs you can see that it is actually a number there's no quotes okay and the color is yellow which means that well in our case because i'm using uh powershell i'm not sure if it's going to be different in other terminals but you can see that it's a number okay now there would be no issue if i were to reference userdata dot age right i could go ahead and do whatever i want with this right i could call to fix to precision right if i were to go ahead and call is nan this should give me false because it is uh it is a number right is noun will return true if it's not a number but in this case it is a number okay so that's good we can actually send uh numeric values that's great but what if i were to actually quote this number okay and if i click send what would happen then it gives us back a tool one okay but see how right now it still says false but let's go ahead and do this right because isn't it i think it does convert a string into a number before it does uh the before it actually um calls function i think but watch this right if i were to reference userdata.age and then if i were to set the type of this or if i were to use the type of operator and if i were to click send notice how the data type it says string right if i change it to a numeric value the data type is number so although typescript knows that this is a number or treats it as a number it's actually not a number right if i were to actually call let's do something like 2 precision which i think is a method only on numbers all right if i click send it it would work or actually what's going on oops remove type of let me click send it would work right but what if i quote this and then if i click send it's going to give me a 500 and you'll see that it says userdata.age.2precision is not a function and that makes sense because the actual data type of this is a string now obviously you could easily you could very easily fix this by just using the using the is number decorator and that would literally fix everything for you right if i just click send it would tell me age must be a number conforming to the specified constraints right but in some cases you might need to transform the data and that's the whole purpose of this section so that's why i'm opting out of using that is number decorator so i'm going to show you how we can create a custom pipe and transform that number data type so that way or not not not the number data the age property so that way it's always going to be a number no matter what so here's what we're going to do i'm going to create i'm going to go ahead and do this i am going to go ahead into the nest cli tool and let me just type nest g hyphen h and we're going to generate a pipe so i'll type nest g uh pipe you can do pi for short pipe and it's going to be long inside the users folder slash pipes and we'll just call this uh validate create user so that's going to go ahead and create that pipes folder and you can see that it created our pipe for us and you can see that it creates this class validate create user pipe which implements pipe transform which is an interface and we need to implement the transform method okay so this transform method takes in two arguments value and metadata okay so value is actually going to give you uh whatever uh whatever value that it is that you need right so for example if you're working with a request body it's going to give you the request body so i'll show you that real quick so let's do console log value and to actually use this pipe what we'll do is this i'm going to go right over here so inside the uh the body decorator right over here we're going to basically just pass in the pipe right here so validate create user pipe we'll pass in here we're going to have to import that of course okay so then it's going to go ahead and invoke this uh transform method so i'll go ahead and write an additional console.log inside validate user type okay so i'll log value and i'll also log metadata just so that you can see what these uh these two arguments show so let's go ahead inside uh postman and let's make a request okay um so right now it's obviously throwing an error and that's fine because we are still trying to call that uh to precision function okay because it treats this as a number even though it's a string but pay close attention to the logs right over here so this right over here comes from i believe uh value yeah so let's just go here so you can see it says inside validate create user pipe and then this is the this is the value of the value argument from the transform method and then if we look at metadata metadata basically tells you what type of uh what type of data this is right so in our case this is actually a request body okay you can keep in mind that you could use pipes for query parameters as well as route parameters as well okay but in our case we're using it for a request body so now what we would want to do inside this pipe is we want to transform we want to transform the the age property so we want to make sure that it's an actual string okay so watch this so we're going to take uh the metadata nominated we're going to take the value okay and actually one thing that i should also mention is that um we can actually just type annotate value as the dto right over here okay like this the reason why is because it's actually going to hit the validation pipe first before it actually goes into uh your validate crew user pipe and to prove that watch this if i were to omit uh this age property it's going to tell you h should not be empty okay so by the time we are making the request right it's going to go through the validation pipe and it's going to go to the transformation pipe and so that's why we can type annotate value as create user dtl okay so that means we can get some intellisense but what i'll do is i'll go ahead and do this parse age tube int and i'll do this i'll call parseint on value dot age and what i'll do uh what's going on here number is not assignable okay so uh okay so i think it's because it says parse ins okay let me call tostring and again this is just an example okay the way that you would do uh things you might you might do things differently right but this is just an example so it treats age as a string but what i'll do is i'll convert it to a string okay and then what i'll do is um if if parse age to ins or actually we'll use the is nand function so if parse h to ins is not a number right so for example if the user passed in you know a b c d right that's obviously not a number so this function will return true but if the user passes it passes a quoted numeric value like quote 24 for example right like what we did here then this would return false because it's still a number but it's just in it's just in string format so what i'll do is i'll just console log and i'll say pars2 i'll just say value dot uh age let me do this basically not a number okay and if it is a number uh well actually before we do that let me throw an error through a new http exception and like i said anywhere you throw an exception nest has an exception handle or layer it'll handle all the exceptions for you so you don't have to even do it yourself so say invalid uh invalid uh data type number or property age expected number and then we'll set the http status to bad requests so that will return to 400. so if it is not a number right then we'll through this error whoops okay if it is a number then what we'll do is well we already converted uh this to a number so we can just literally do this we can just return uh we do this we can return value we can we can return everything and we can override the uh the age property to parse age two it's like that we could do that let me also remove these braces because we don't need that um and we actually don't even need this else case because it'll throw a new error so we'll never go into this return it will never hit this return all right so let's test this out okay so um let's do this um is a number it's good to write a lot of logs so you all see what's going on so let's go ahead and click send and see how the error does not happen anymore so in the controller we're still trying to call to precision and it works right it works because this is an actual number now okay because we transformed it originally it was a string because that's what we passed in but we transformed it to an actual numeric value so when it went back to this method userdata.age is actually a number even though we pass in a string okay you can see that it is uh being called over here 24 it's uh two positions right over there see it works and if you see in the logs we can see that it says 24 is a number returning okay even though it's a string if i pass in like you know a non-valid by passing a non-valid string uh what happens here uh why is it saying oh you know what it is i think what happens is it actually get get gets rid of the rest of the um i think i think it trims all the non-numeric characters yeah after 24. okay see i think it parsed this first and then it got rid of this but if i add values in front of it you're going to see that it says invalidated type of property h expect a number and it throws that error okay that's and that's all coming from the pipe so that's how we can use pipes to transform data and again you can use this to transform any property you want right you can transform you know a string to a number a number to a string you can do whatever you want okay so that's how you can use pipes so um that is going to be pretty much it for pipes i just wanted to you know include this so that way you all at least know what you can use pipes for aside from just you know validation you can use it for transformation as well all right so we're going to move on to the next topic and we're going to go ahead and talk about guards so guards are pretty much just a class that have a single responsibility and all they do is they just determine whether the incoming request can be handled by the controller's route handler okay so it's kind of like you know it depends on certain conditions right the most easiest example that i could give you is when it comes to authorization or authentication right if the user is not authenticated you'll use something like a guard to prevent the user from accessing an endpoint because they are not authenticated or let's say they are authenticated but they are missing certain permissions or they don't have a specific rule then you would use a guard to protect that endpoint from that user because they don't have the necessary permissions or rules okay so guards are really great in sjs because you can use that to implement authorization and authentication at the same time okay so uh what we're going to do is we're going to go ahead and implement a guard so i'll show you how we can do that so i'm going to go inside uh my cli my terminal and i'll go ahead and generate a guard so we can do that with the nest cli so we'll do nest g guard and then we're gonna pass in the relative path so we want this to go inside the users folder the user's module so slash users slash guard so that folder will be created inside users and i'll just call this um off guard i don't know i don't really know what a good name to call it so i'll just call off guard so that's going to create that so let's look in the folder and we can see that we now have this guards folder and it creates the guard file and it also creates the spec file which is good okay so now you can see that when we look in the guard file we see that we have a class and it's also annotated with the injectable decorator okay because we can inject the guard wherever we want in our application we can use in any controller we want so this got this uh off guard class implements the can activate interface okay and we need to implement the can activate method okay so essentially this method is responsible for returning a boolean value okay and uh right now it returns true by default right that's what it does but of course the most common use case is we want to use the context right the execution context gives you information about a lot of different things and one of the things that it gives you is the uh is the request right so for example if you wanted to get the actual request object what you would do is you would switch you would call the switch to http method and then you can just call get request like this okay and um the data type should actually be request so what i can do is this cons quest equals and then i'll type annotate this as request okay and also console.log request uh headers as well and i'll we can console whatever we want so what we're going to do here is we're going to go ahead and uh we're gonna i'm gonna show you a good example of how we can use this card but essentially right now it's just going to return true okay so it's really just going to work every single time but it returns false it'll deny the quest so let me show you how this works so let's go to auth guard and we're going to go ahead and use our guard so the way we do this is we go to our route um so if you want the guard to work for the whole entire controller you would use the used guards decorator and then you would pass in off guard like this and you do that for you would do that on top of the clasp itself if you only want it to work for a single endpoint then you would only do that for the specific endpoint okay so um it depends on your situation right maybe you want to protect every single route maybe you don't it's up to you but let's go ahead and visit the get users endpoint so that's going to be slash get slash users or not get slash users so it's going to give us back our response just fine but you can see that the guard the the can activate method was invoked because we are logging the headers right you can see authorization token content type a sample of all these things right in an actual application um where you have like you know sessions and the user logged in right which we're not gonna uh we're not gonna uh you know talk about that in this crash course that'll be for a separate crash course um which i will make but typically what you would do is you would you know get the request object you would reference the user property if you're using sessions right and then what you could do is you could check to see if the user has a specific role and that's assuming that the user is actually logged in if you check that the user has a role and if the user does have the role then you can return true if it doesn't then you would return false with another request right so let me show you something real quick let's say if i were to return false okay and if i were to access this you're going to see that it now says forbidden resource right for whatever reason it returns false whether you don't have the role whether you are missing permissions whatever it is right um that's what that that's what this auth card does okay but like i said don't worry so much about the auth guard right now because it really works well when you are using you know uh when you actually have authentication authorization in your application but we'll save that for another tutorial where we talk mostly where we all talk about authentication and authorization okay but yeah hopefully you understand guards and if you want to learn more about guards you can just go over to the docs and they have a bunch of documentation that teaches you how to use this okay you can see that right over here in this example they switch the context to http and then they call the get request method and then what they do is they uh let's see what they do here they actually get the user object and then they are trying to match the roles okay and yeah basically it just matches the roles uh that are required versus the roles the user has okay and um yeah that's pretty much it when it comes to guards so that is going to conclude our nest js crash course i hope you all enjoyed this whole crash course because i absolutely had so much fun creating this crash course nestjace is my favorite framework for building node applications it's definitely the one that i use all the time whenever i build uh large applications even small applications too i just love the whole structure and everything but um unfortunately i'm gonna have to end the video right here because we are at an hour and a half already a little bit more than that there's a lot of different things that we have not even covered such as sessions cookies caching we haven't covered databases we haven't even covered authentication we haven't covered authorization there are so many things that you can learn with nest js and i am so excited to make more videos on sjs i hope you all love this video if you did feel free to check out my other videos on my channel i do have separate individual videos for each topic on sjs including unit testing and end-to-end testing so feel free to check those out on my channel but um what next well the next thing that you'll look forward to is learning how to configure authorization and authentication using passport and sessions but that will be its own crash course in another video but um what i'll do is i'll also put all the code in a github repository and i'll provide the link in the description if you need additional help with nesjs i do have a discord server the link will also be in the description feel free to join stop by say hi if you have any questions need help with code there are channels where you can ask questions and ask for help but that is going to be pretty much it for this video thanks so much for watching my name is hanson and i'll see you all in my next episode peace out
Info
Channel: Anson the Developer
Views: 132,612
Rating: undefined out of 5
Keywords: nestjs, nest, nest tutorial, nest framework, nestjs tutorial, nest.js tutorial, node, nestjs crash course, nest js
Id: xzu3QXwo1BU
Channel Id: undefined
Length: 100min 6sec (6006 seconds)
Published: Thu Aug 11 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.