NestJS Crash Course: Everything you need to know! | NodeJS Tutorial 2021

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
http 418 i'm a teapot whatever whatever that means you know if you wanted to do that you can [Music] hey welcome back to the channel today we're going to talk about naturally as fundamentals this is the absolute crash course that you need if you're a complete beginner or maybe you're just trying to get a refresher uh we're going to cover quite a bit of topics here first of all we're going to cover how to create an application from scratch we're going to talk about the three-layer architecture that sjs sort of promotes and dependency injection we'll talk about how to create modules controllers all that stuff from scratch as well as how we can utilize the next jscli to auto generate a lot of that stuff for you we'll talk about swagger docs you know open api documentation for your api we'll cover how to parse and validate the request body as well as query params url params uh we'll cover error handling http exceptions we'll cover pipes those are really useful and then finally we'll also cover how to build a crud from scratch you know no extra libraries we're just gonna do you know fundamental base how do you do things in next js so stick around make sure to like and subscribe and let's get started alright so first thing i'm gonna do here is i'm going to pull up a terminal and with every nest js applications you absolutely should install the cli if you haven't done this already that the script is on the screen just type that out in your terminal hit enter and then it will install the cli for you i've already done that so i'm just going to delete this and then once you have the cli the next thing you're going to do wherever you want to create your project so in my case for tutorials i usually just put mine in the desktop so i change directory there and then you can run this command nest new and then you're gonna provide the name of your application i'm gonna call my nest crash course when you hit enter there it's going to ask you what package manager you want to use i usually go with npm just because i'm comfortable with that you can also do yarn so i'm going to hit enter here and it's immediately going to start installing for you the stuff that you need so that's going to take you know maybe a minute or two all right next after that's done installing you can just change directory into that so i said that that was nest crash course and then from here i'm just going to open up vs code all right first let's take a look at what that command generated for us you'll see that there should be an src folder that has these files and there's also a package.json down here that's going to include the scripts that you can run so why don't we go ahead and actually just run the start dev script and then we'll look at the code and see uh what are all the things that are in here so i'm gonna go in my terminal i'm gonna write npm run start column dev now when you go to your browser and go to localhost 3000 you should be able to see a hello world there now let's go take a look at what's generating that from the initial code so within the src folder you should see a main ts to think of this as sort of the the very root entry point of your application we'll revisit this a little bit later and add to it but you can see that it just says that it's creating an app and then it's listening on 3000 so that's how you know that you're supposed to go to localhost 3000. from here you can see that it's creating out of this root app module if we go into that the root app module has a control a controller and a provider called app service now before we get any deeper let's first talk about architecture so one of the big things with sjs is it tries to promote a specific convention or architecture that you should follow and a lot of people would probably know this as the three layer architecture there's actually a good article called bulletproof node.js project architecture by sam quinn that i recommend reading but there's a section here where it talks about the three layer architecture and i pulled this up because i think the the diagram is nice to look at so basically the idea is there's these three core parts um to handling api requests there's the controller there's the service layer and then there's the data access layer so as you see in the code this directly maps to that idea there is a controller app controller and then there is a service layer that the controller uses so if you if we open up the app controller you'll notice that there is a app service being passed into the constructor here and within the methods it's using that app service so it's kind of going down this chart and then within the app service there's nothing here yet but in the future if you were for example to incorporate a database connection that's where your data layer will be there will be a you know a repository that connects your database and that's what the app service is going to do so i'm not going to go into too much detail about this architecture the only the only thing you really need to understand is that nest by default kind of has this architecture it kind of promotes a pattern where there are specific things that are in charge of uh specific topics right separation of concerns is what i'm what i'm trying to say there so you got the controller that's really in charge of things like anything related to http write your urls your endpoints http verbs like get post put http exception handling like you know when your api responds success 200 404 not found internal server error 500 you know stuff like that that's usually things that the controller would be doing the service layer is going to have a lot of your business logic you know so any logic that happens between all of that http stuff as well as before it gets you know saved or updated in your database and then obviously the data access layer is your your database logic a lot of the querying it's going to be handled by that now in this tutorial i'm not going to go into the details of how to connect to a database i do have a i think my last video was on type orm which is a really good data access layer for that you can use with with sjs so if that's something you're interested in make sure to check that out probably after this video all right so kind of going back to what we have right remember when you go to localhost you get a hello world how is that happening well if we go into the app controller if we kind of follow this code you'll notice that we have this kind of base get hello which calls app service that gets hello which if we go into that it just returns hello world right and a couple of things to notice here notice that there is um decorators everywhere and you'll see this a lot in sjs there's a heavy emphasis on sort of configuring things via decorators which i actually like a lot so there's a couple things you can do here this controller decorator actually accepts a string so for example i can make this app and that defines the kind of the base path where this controller sort of starts handling routes so if i refresh my application on the right for example now it's going to tell me 404 status not found because i've moved the hello world to slash app okay so when i go to slash app it's working again then next within the method decorator so for example in our case here we have a get that also accepts a string so for example i can add hello here and when i refresh the application again on the right we're gonna get another 404 because i've moved that into flash hello right so it kind of the decorators kind of tells you what it is and then it gives you the opportunity to kind of configure uh what path is it working for and again you can see that you know we've got that separation of concerns we got the controller doing a lot of this stuff kind of dealing with um the urls and the paths and what that is and then it kind of delegates to the service to do whatever logic that it wants to do all right so that's a really quick intro to sort of what controllers are what services are we'll get to into a little bit more details as we go to provide a more realistic example why don't we go ahead and create a new endpoint maybe for let's say we want a user's endpoint to be able to get the users of our application so what i'm going to do first is i'm going to open a new terminal here and remember in the beginning of the video we installed an scli that cli is not just for creating new applications it's also for generating stuff for you and the code so for example let's go ahead and create a new module we're going to do nest generate module and then we're going to provide a name here we're going to call users you can think of modules in sjs as sort of just a grouping entity uh you know you kind of will likely have different domains in your application right so for example a a pet store api might have a module for dogs it might also have a module for cats and so on so the might have a module for owners so the different think about the different domains that you might have you likely will have a module for that so in our case we just created a new module for users and you'll notice that this automatically the root app module automatically got updated it now has this imports in it of users module so that's another reason why you want to use the cli to kind of create your files because it's going to auto wire up for things for you so another example if we go into users module right it's it's empty right now but i want to kind of do this same thing where i will have a user's controller and a user service and again this is a pattern that you're going to see throughout this tutorial is that you know every module will almost always have you know it's one too many controllers one-to-many services so back in the terminal i'm gonna do nest generate or you can also just do an sg as a shorthand for generate nest g controller users and again you'll notice that it updated i created these new files we now have a users.controller.t and it also updated the module right so the the modules is kind of the the source of truth of uh which of the code is actually you know quote unquote registered with the entire nesjs application right so you see there's now a controllers here with our new users controller and then same thing i'm going to do nest service users to create our initial user service from scratch all right so let's take a look at what we have here let's go to the users controller so right now it's just an empty class that automatically has that user's path in it that means that when you go to localhost slash look at those three thousand slash users it's gonna go to this controller this controller will handle anything uh that has slash users in it so why don't we go ahead and add a new method here perhaps we want to do a get users which let's just make this a returns any for now because we haven't really set anything up yet so let's just return a dummy array maybe there's an array with an id with an object there within a d0 and remember to kind of register this as an actual route handler we need to do get and notice that it got imported up here if you keep it empty if you remember that means it's just gonna do slash users so if we go into our application right now and go to slash users localhost 3000 slash users what i expect to get back is this kind of dummy array that i have all right so where do we go from here just to kind of demo for you guys how to add other routes right maybe we want to do a get user by id right typically in a restful api you might want to do something like slash users you know slash id like this and then you want to be able to get the user with the id one so let's first figure out how can we route this request into this method so what we're going to do here is add a get and then we're going to add a string which represents the id the colon here kind of marks the id as something that is a dynamic value so it's basically in a url parameter if you can think of it that way and i forgot parentheses here so what we want to be able to do is we want to be able to parse that id out of the url and then provide it to our service later on down here so to do that we're going to introduce another decorator which you can use in the arguments here called param and in the url there could be one-to-many uh parameters in in that url so you want to provide a key here because we want to extract specifically id and we'll provide that variable a name and a type and then why don't we just return an object here that has that id okay now when i refresh this on the right what i expect to get is an object with id one and that's another thing to kind of catch here notice that because it's parsing it out of the url it's always going to be a string there is a way to auto translate that into something else that i'll show you in a little bit but if you want to you can also do something like this you know if you're maybe in your database you have number ids you can simply cast that so you notice that it's now in a number but nestjs has a way to do that automatically using pipes that i'm going to show in a little bit here but i don't want to jump ahead too far all right so that's kind of a really basic intro to setting up your controller uh but there's uh there's a core missing piece here right we said that we want to utilize separation of concerns and that ideally the logic specifically the querying logic should live in the user service so why don't we go ahead and have a constructor here and i'm going to do private user service which has a type of users service which remember we just made recently now let me explain this a little bit real quick so what's happening here is that um sjs is utilizing what's called as dependent dependency injection which the basic idea for that is just that um nest will automatically kind of instantiate classes for you and it's going to end it's going to sort of manage the references to those classes and then it'll auto inject those ref those classes into whoever needs it injected so for example our users controller in this case is saying i want the user service to be automatically injected into this controller and nest is going to do that for you in the background right we're not doing we're not kind of imp we're not importing user service and doing you know new user service ourselves nest js is doing that for us in the background so that's kind of a very well i would say that's a terrible explanation of what dependency injection is but i highly recommend you read up a little bit on it it might help you understand this better but in in our case you just need to know that whatever you provide in the constructor is kind of it's going to be automatically injected into our application and nest uses the type that you provide here to figure out which class do i need to instantiate for you behind the scenes so within our user service what we're going to do here is we're gonna try to maybe simulate a uh maybe like a fake database so we're just gonna add a private users and we'll just mark this as any for now and this starts out as the array that we have here you know maybe we just have an initial array of something like that and maybe let's add a name property give it my name and then let's uh implement some of the methods that we're supposed to already have at this point so we said that we we want to do like a get users so we'll do let's do let's call this find all and what this is going to do is simply return our array this dot users and then we also said we want to do a find by id so we probably want to ask for a user id of type number and this returns it's going to try and find that user within our array so we're going to do this.users.find for each user if user.id equals equals user id which is the one we passed in and we're gonna return that so if you're familiar with defined method if it doesn't find that match then it's just gonna return undefined right so now we can replace our implementation here to be this dot user service actually let me rename this to [Music] users service just to be consistent we're gonna do find all and then we're gonna replace this guy with this dot user service dot find by id and we're going to pass in that id and remember that needs to be a number right and i said that there's a way that nest can auto do that parsing for you so we'll come back here all right so back in our application in the browser if i go back to slash users and refresh we'll get back that same array and if i put in 0 here i expect that i get back just that one object what do we want to do from here maybe we want to be able to add new users what you usually want to do is you want to first implement the service method for that so let's go ahead and add a create user and perhaps to create a user the only thing we expect to provide is maybe an initial name next we want to be able to generate an id for that right and if you were doing this with a database you can do like auto incrementing ids or maybe if you like uuids um you can do whatever you want but in our case we just have a simple array here so for us to create a new user we're just going to have an object that has an id of um maybe we can do sorry date that now which gives us sort of a timestamp number uh so that's always going to be different every time you call it and then we're going to do name here and then we're just going to manipulate our straight our array the set users.push new user and then we're going to return the new user that got created all right and again i want to repeat that this is not typical development right in a in a real application what you want to do is introduce something like type orm which will connect to your database and then you can use typeorm to do the querying for you sort of like how we're doing find and then you're gonna have that be injected in here as the data layer now in our case we're just keeping it simple we're just gonna work with a simple in memory array if you're interested in the database stuff like i said i do have a video for that that i'll link up up here somewhere all right now let's take a look at how we can utilize this new create user method in the service back in our controller so typically with crud you want to use a post [Music] for creating so we're going to do post create user and we're gonna do return this.userservice.createuser and notice that it's got the squiggly because it's looking for a name but we don't have a name so this is probably a good opportunity to introduce you to the body decorator if you've ever done express development for example you know you usually have like a body parser um just think of it that in nest it's kind of built and you just got to use this this decorator so we can add a variable name here and then we need to provide a type so i just have this as any right now but um just think of it as whatever type you provide here represents the shape of your request body now we obviously don't want to keep using any everywhere here right this is not good practice the whole point of using typescript is to kind of provide you uh you know the shape of things the types of things so let's go ahead and kind of improve this in our users folder i'm going to create a new folder called dto and within that folder i'm going to create a create user.dto.ts and real quick about the names by the way you'll notice that in nest it kind of has this convention where it has a kebab case name and then followed by dot and then the type of what that is so you'll notice that there's a dot dto.controller.module.service so those represents kind of what is that that class you know and then followed by.ts so to create our dto and if you don't know what dtos are they're basically uh so dto stands for data transfer object just think of them as just a schema representation of whatever object you want to use as an intermediary way to transfer information right and it'll make more sense as i start typing this up so within our file here i'm going to do export class create user dto so this class is going to represent the fields that we expect the the client to provide us as they create a new user so we said initially we're going to want to ask for a name now we can use this type as our type for our body here so we're going to know that the body is going to have a name property in there and i want to make sure that i import that so we can then do body dot name and actually what i often like to do is i just pass the the whole dto into the service so i'm actually just gonna do i'm just gonna pass the body here and then i'm going to update create user to have a create user dto of type create user dto and then here you need to update this to create user dot name and in likelihood in other cases you probably just want to do you know you might just want to spread it out because in the future we might add to this dto for different fields like you know maybe we want to do first name last name age you know stuff like that email all right so while we're at it we might as well create our type for the user entity itself for so back in the users folder i'm going to create another folder called entities and within that i'm going to create a new user dot entity dot yes similar thing right this is the um the class which represents the shape of our user object so we said that it has an id which is a number and a name which is a string and in the future if you get into database connections this entity class will also represent your your database table right so your your entities usually map one to one to your database tables now that we have that we can replace all of these any's with a proper type so this is going to be a collection of users the get by id only returns a single user and the create also returns the created user i'm also going to fix our user service to have now this array is gonna be a collection of users and we're also gonna return that here and also updating the return types for these methods providing return types like this is very good practice because you know it'll help you catch bugs so for example maybe i forgot to add this uh spreading here and it's only returning the id right now it's gonna start complaining to me because i'm trying to create a user without a name because in our user entity we said that the name is required right we don't have a question mark here making it optional so i'm going to fix that again but in general right the whole purpose with typescript is to kind of help you with these things to catch bugs early so make sure you're utilizing types as much as you can all right now that we've done that clean up where do we go from here so we probably want to be able to test this that this post this great user is working right now there's a couple different ways you can achieve this you can use postman if you've ever used that postman is a client that can uh let you change what http verb you're using for making requests there's also i believe insomnia is another good one now what i like to do with an sjs app is i actually just what are you doing now what i like to do with an sjs app is actually just introduce swagger documentation which kind of acts not only as documentation but it also gives you a way to test your api in the same way that you would use postman to test your api so let's go ahead and do that next so in a new terminal we're going to install a couple things here we're going to do npm install that save we're going to do an sjs slash swagger and then we're gonna do swagger swagger dash ui dash express and hit enter there quick note about that notice that we're using something that was meant for express and the nice thing with nest is behind the scenes under the hood by default it uses express so that means a lot of things that you might have used before in express are generally compatible with nest so that's uh that's a really nice thing about nest is you can kind of take advantage of that existing ecosystem so really nest is kind of just a if you think about it as a sort of an opinionated layer on top of express right express is a very minimalist tells you to do whatever you want nest kind of just adds a light layer that says here's how you should do these things follow my conventions all right after that installs the next thing we're going to do is go into our main.ts and within here we're going to add a little bit of configuration to enable our swagger docs so i'm going to do const config equals new document builder from sjswagger i hit enter there to auto import for me or sorry tab i hit tab to usually do auto imports and then i'm going to add a title and we'll just call this i don't know nest api you can call it whatever you want for your case you can add a description here if you want right so there's a couple of different things you can add here you can add version gonna do maybe 1.0 and then finally you need to add a build right because it's a builder next we're going to do document swagger module dot create document and we need to pass in our app which what is what we have here and then we need to pass our config so it's kind of just tying the application and the configuration together and from there you can do the setup like this so swag module.setup accepts a path as the first argument we're going to just do slash here and then it also takes app and the document that we just made and that's it the path that you provide here is where your documentation is gonna live so if we take a look at what we have in the browser if i go back to my local host just a base path like that right which is equivalent to the path that we provided all of a sudden we got our auto-generated swagger docs right so it's got the title it's got the version here it's got the description and then it automatically documents all the things that we've done so far so that's really cool another big thing that i really like about nest you know it takes advantage of all of these decorators and stuff and kind of auto figures out all right what's the documentation now there's a couple things we can improve upon here so for example maybe i want to have the users be in its own section so i can go into the users controller and add api tags users and when i refresh the documentation now all the stuff in the user's controller are in this user section so that's pretty cool so like i was saying the the swagger docs kind of acts as your not only your documentation but also your way to test your application in the same way that you would use postman so let's go ahead and test the the post create user that we made we said that this takes a request body that has name in it and then you can provide some kind of value there right uh maybe we'd say dustin and then i'm gonna hit execute you'll see that it ran post on slash users and it gave me back a new object that has that generated id and then the name dustin now just to kind of for sanity's sake let's go ahead and do a get slash users and see and double check that we now have two users in there we got marius we got dustin now while this is kind of cool it's still missing some pretty important information right so for example it doesn't really tell me what the shape of the request body should be right documentation should tell you that it also doesn't tell me the shape of the thing that's getting returned again if you have good documentation it should tell you that now the nice thing is with nest and the swagger module you can add decorators to provide that information so for example in our create user dto we can add at api property here and let's take a look at what that does if i refresh the documentation on post slash users now it has a schema for that dto right it says that there's there's a name here that is required perhaps you also have an optional property here of i don't know let's say age i'm going to add api property again api property the thing to kind of catch here is that it doesn't automatically know that it's it's optional just from this question mark so you need to add um required false so let's take a look at what that looks like if i refresh now it shows that there is a an h property but the schema says that it's not necessarily required right it doesn't have that that red star all right next we want to be able to represent the schema for our response how do we do that if we go to our controller we can tell it that the post has a api created response of type user so this is telling that on a post it's going to respond with a 201 of with type user and within that user we we also need to add our api property decorators so don't forget that and back in the create dto i'm actually just going to delete this too i want to keep it simple for the rest of this tutorial they just have idea name so now that we have these decorators on a user entity and we're seeing on this method it will do a created response of type user if we go back to the documentation and refresh it's going to say that response it will probably give a 201 with a shape like this so i'm not going to cover everything that you can do with swagger but if you check the documentation just know that there's a bunch of these very useful decorators that allow you to enhance your documentation right so for example maybe we will also want to say that the get users responds a api okay response of type user and we have to say that this is an array and our get by id responds in api okay response also of type user but it's not an array all right let's very quickly take a look at what that gave us refresh on localhost 3000 if we go to open up our slash users get same thing it has a 200 response code with this type of shape right and the idea here is that you want to be able to communicate to your users your api consumers um what your api returns even before they call it that's really nice same thing with the get buy id you got a 200 and then just returns an object an object of this shape right and there's a bunch of other things you can configure on here that up i just don't have time to cover everything but if you'll take a look at these classes right you can see that there's an api response option so you can pass in and if you take a look at that you'll see that it's a type of this you know you can keep kind of digging into the type and kind of see or what are the different things you can pass in here so for example maybe you want to provide a description right um you know like this the user i don't know and when i refresh this again you know there's the description there so lots of things you can kind of configure and manipulate there all right so that was kind of a side deviation from the work that we were doing but i really think this swagger stuff the fact that it can do for you this stuff almost automatically right with just a little bit of uh decorating things it's it's very nice if you if you have seen how you do this in an express app for example it's it's a lot more painful you have to kind of type out the open api specs manually a lot of the times it's not a good experience all right so what else can we add here um we covered how to do request bodies and we covered how to do url params we did not cover how to do uh query parameters you know like search queries so let's think about this for example we have a slash user's endpoint right i'm able to do slash users and it returns me my array and by the way because our array is in memory every time our our application restarts you know it goes back to our initial array but anyways what if we want to do something like i want to be able to get just the persons the users that has the name bob or in my case just all the people that has the same name as me um how do we implement something like that so you want to be able to parse out this query param alright so how do we do that kind of similar thing that we've done here right there is also a method decorator called query and same thing you want to pass in here the uh the key for the query that you want to use because if you understand query params well right you know that you can provide multiple right like maybe you have name and age equals i don't know 50 right so you can have multiple key value pairs in a query param so here you want to provide the key of the thing you specifically want to parse out of the url so in our case we want to get the name provide the variable name or just keep it name as well and then the type right so then we can pat we can take that name um and we can pass it down to our find all now let's go into our find all and say that this now accepts an optional name of type string and we can do something like if there is a name provided return the filtered array this.users.filter for each user only return them if their name equals the name that got passed in and just so when we test this out i'm going to add a couple extra initial users here i'm going to add another person with the same name as me what has id one and then i'll add dustin buck in here name two all right so just imagine that we have a user database and it initially has these three rows um so let's go to our swagger docs and see what this looks like so in our get slash users automatically you'll notice that there is a query field here that it automatically got added you can provide a name there's a cache here though you'll notice that it thinks by default it's required so this prevents me from doing just slash users without a query parameter so to further configure that we're going to add api query and for the one that has name name we want to say that that is required false right again kind of similar to the entities it it's not able to just see that it's a an optional parameter you kind of have to tell it so that's that's a once downside but it's not horrible so back in our documentation let me refresh and now the red star is gone and i can do execute and i'll just do my get all but now if i provide a name and maybe i just want to call i i'm gonna get just the users that has named dustin i'm gonna execute that and i just get dustin if i switch my name i'm gonna do should return the two users that have my name all right so that's how you do query parameters all right so that's that's pretty much the core things you need to understand with uh writing controllers there's one other thing that is probably good to know about which is how do you handle errors in sjs so let's think about what are the different scenarios where you might have an error in what we have so far so one of them is if you're trying to you find a user by id but what if that user doesn't exist how does it respond so let's just say that we want to respond with a 404 not found http error uh if if the user wasn't found so what we're going to do here is we're going to extract this user call into a variable i'm going to turn user and then we're going to add a little bit of logic here of if user was not found we're gonna throw new uh not found exception and you can also add this in your documentation if you want so let's go ahead and do that we can do api not found response this just tells our swagger documentation that it's possible to get a 404 response from this call so let's go take a look so when i refresh on the get user by id you'll notice that response there is now a 404 there actually let me show you if i delete this and refresh again if we were to do let's test out if our 404 is working right if i put a crazy number here we know we're not going to find that and execute notice that our exception is being thrown we're getting 404 not found and then also notice that it says undocumented so this is a good way for you to kind of figure out oh what else can i add to my documentation right and that's what the the thing we just deleted was and you also saw that this worked right it didn't find that user and it through this exception and there's a bunch of these kind of built-in exceptions in sjs that you can use so for example there's one like um you know there's a bad request exception right this is a http i believe 400 like you can throw that on maybe validation errors there's a you know there's a internal server error exception you know which is usually like the 500 so basically nest has its own built-in error handler and let me bring this back where you for the most part you can just throw a lot of these classes and it's automatically going to respond with a special object that represents that error right and you can usually customize it further to have like custom messages and stuff like that so that's very useful to know so first of all you need to have kind of base fundamentals with api development what http status codes there are right so right so if you google http status codes right there's a bunch of different ones in here but there's several that you but there's several ones that you should just know by heart right so for example http 200 is okay we saw an example of 201 created right we have the api response created uh we did i showed you bad request and then there's the 404 not found there's 403 and 401 that's usually for authentication and authorization so a lot of those main ones are typically built into nest js actually here's the documentation it shows you all of the built-in built-in ones right it's got all of these guys so um take make sure you use that you know for your own error handling and you can also build custom ones if you wanted to like like this you know for example maybe you didn't know that there is a pretty sure there's a teapot one right http 418 i'm a teapot whatever whatever that means you know if you wanted to do that you can you know you do use the custom one right so that's a big that's a big feature of of nest as well is that it's got this built-in error handler for you if you've ever used express you would know that you you usually have to do that from scratch all right next thing i want to cover are what nesjs calls pipes now we said that we're going to come back to this we're going to auto parse the id in sjs pipes are things that you can kind of think of them as middleware that specifically is for two use cases here either transforming data or validating it right so let's let's take a look at a real quick example of transformation so you'll notice that they have a built-in parse in pipe that you can provide like that so let's see if we can replace this we're going to do parse and pipe in our param here import the dependency and then now this is going to be a number and it means that i no longer have to typecast it myself right and just for sanity let's do console.log dot type of id and when i go to slash users slash one two three we're gonna get a 404 but in our docs you'll see that the type is now automatically a number right so that's one of the things that the parseint pipe does is it automatically transformed what was a string into an integer a number right and because it's coming from the url of the request it's always going to be string so that's why this is really useful to to know about all right what else can we do with pipes so we said that the second use case for it is validation right validation is very important so another thing that sjs kind of has built in is this validation pipe so what we're going to do is so real quick pipes are something that you can add to controllers it's something you can add to controller methods it's also something that you can just add globally so maybe you want a pipe to run on every request right so you can again you can kind of see pipes as um as a middleware that is specific to these two use cases so for validation specifically i want validation to run on everything in my application so it would make sense for me to define a validation pipe on the whole application so to do that i'm going to switch over to my main.ts file and within here i'm going to do app dot use global pipes and i'm going to do new validation pipe and you'll notice in the terminal that it says class validator package is missing and the validation pipe needs that so i'm going to go ahead and install class validator um and i believe we also need class transformer so i'm just gonna do that as well now while that's installing let's take a look at the documentation for class validator what is this class validator basically allows you to provide decorators that specify the validation that you want to run on a class uh field right so for example uh there's a section here where it says validation decorators and it pretty much gives you a summary of everything you can do right so for example um maybe you have a number field and you want to do various validation on that like maybe it's a minimum or a maximum value is it positive um you can do it on date fields uh the string ones are very useful so for example maybe you want to validate that it can train or contains a substring maybe you want to validate that it's only letters and doesn't have numbers or maybe you want to do alphanumeric you just wanted letters and numbers but no special characters so let's let's give that a try and let's copy is alphanumeric and we'll see that back in our terminal that is finished installing i'm going to go into our users dto so you usually add these decorators in your dto so maybe i want to add a validation here it's saying that this needs to be alphanumeric i'm going to ins i'm going to import that from class validator and then just for fun let's add so max length is a good one right if you're doing var charts in a database it's usually it sometimes has a limit right um so maybe we want to do a max of i don't know 10 characters import that as well back in my swagger documentation i'm going to try to create a user that makes that validation error out so if we said that we had alphanumeric right if we just did like special characters here i expect that this is gonna error out for me you'll see that now it's got status 400 undocumented because we didn't document it bad request so this is kind of your automatic um error handling with nest just happening for you automatically it's very nice and it says that status goes 400 because the name has to be shorter or equal to 10 characters and it only has to be letters and numbers right so how many characters did i have here so i actually have more than 10 characters here which i didn't even i wasn't intending to do but if we just do these guys right execute now it just tells me only the alphanumeric validation ran so it tells you basically all the things that it kind of is having a problem with but if i switch back to you know letters and numbers and execute the one we have provided and you can see the validation is working and just to be kind of complete here right you can also in our documentation add the api bad request response here just to update our documentation to inform our api consumers that hey there is some document there is some validation that's going to happen here um so if you notice earlier it said 400 undocumented if i refresh that now we have um you know possible responses either a 201 got created or a 400. now it doesn't have any more information here i'm sure you can further add you know an options object in here as well but you know i'll leave that for you to explore all right so we covered a lot of stuff there right we we went from you know no nothing to creating a new users module a new users controller and service we covered swagger documentation we covered validation we did body query and params and you can see that nest has a lot of these very useful things kind of ready to use for you a lot of the things that you would need in a tip in a typical rest api is here so that's that's something that i really like about an sjs is just it seems to just know 90 of the things that you would need anyway so you don't have to build it from scratch or you don't need to install another thing now one thing that i would probably understand that people would not like is the kind of this boiler plate that you have to do to create a new controller right you gotta you likely will need to create a new module you need the new service and then your controller and then you're gonna define all of these methods in every controller well guess what in the next cli you can auto generate a lot of this stuff if you wanted to so as an example let's say that we're trying to to add a feature to our application you know maybe we want our api to manage a to-do list right in the terminal i can do nest g resource and then the name to use and when i hit enter there it's going to give me a couple different options here of what do you want to generate in our case we we're going to do rest api here so i'm going to hit enter real quick side note the graphql one i do have another video for that so if that's something you're interested in take a look at my channel but let's hit enter on rest api here and it's going to ask me do you want to generate the crud entry points and i'm going to hit yes here hit enter and then take a look at what all these things are it created me a controller a module a service and dtos if we go into our users module right it made kind of that same structure that we had as a user's module which it has its own to-do's controller and when you look it's got your crud automate for you you've got your create post you've got your two different gets and then you've got your your update patch so people like to use put here um and then you've got your delete right and it's already the structure is already there it's you've got your your bodies your params your queries and it's got the dtos also auto made for you right so if you look here it's got create dto update dto and the only thing you need to provide is the implementation right you just need to provide the fields that you that your classes need to have for your dtos it's also got a to-do entity right you so you just need to provide the definition and then if you take a look at the service it also by default has these methods created for you that already has the proper arguments right passing into dtos and such and then it's just up to you how you implement the underlying logic right so you could do if you were just doing this you're if you're following along on your computer you could do the same thing where we just do something in memory or you can add a database connection and maybe this is where you write your queries i have another video on that again on typo rm where i show how to do this crud using typo rm and how to do that with a database so a if you really like this video an action step that you can do is go watch that next video on typo rm and then implement your api for real to talk to a real database to do real queries and then basically you've got yourself a fully functional rest api and you've just got quite a little bit of things to configure and it's very very fast and the underlying details of the implementation is is up to you for to decide all right so i'm not going to do the implementation here i think will really cover the underlying fundamentals if you know all the things are covered well that's pretty much most of what you need to know to build your first api there are a couple different other topics that i just don't have the time to cover right now but there are there are guards so similar to how you have pipes you also have guards so if you've if you've ever used express for example you know that they have they use middleware for everything right they use middleware for for authentication they use middleware for our back they use middlewares for validation in sjs they also have middlewares but in addition to that they have uh kind of think of them as middlewares that are that have a specific job right so guards pipes and interceptors are really middlewares that are specific to doing something right recovered pipes is effectively a middleware that does specifically transformation and validation guards are what you're going to use for authentication and authorization right i'm probably going to do that in a separate video because there is so much to cover on that on that topic alone but just know that if you're trying to do authentication and authorization that's what guards are for and then there's interceptors which are exactly what they sound like if you're trying to kind of add you know custom logic to happen before before or after your controller gets executed um that's what it's for and then you of course have your kind of generic middleware for everything else and that that also means that most middleware that you might have used in express js are probably usable here because again this is just kind of nest adding their own flavor to it they're saying here's how you do middlewares but it's up to you what you put inside that so you can very easily most of the time use an existing express middleware and kind of use it in the nest ecosystem all right so that's it for today folks that was a lot to cover and honestly there's so much more to cover that i just cannot cover in one video but i believe i covered everything that you truly need to know you know as an actual crash course for api development with nesjs again take a look at my channel for more i've got a couple of different nesgas content there and i'll be making more node.js and react full stack content so if that's something that you're interested in and you like about the way that i teach you know make sure you subscribe and hit the like button on this video if you find value in it and that's it thank you for watching and i'll see you on the next one you
Info
Channel: Marius Espejo
Views: 23,676
Rating: 4.9828877 out of 5
Keywords: learn to code, coding, web development, nestjs, nestjs tutorial, javascript, typescript, nestjs graphql, nestjs typeorm, nestjs microservices, nestjs authentication, nestjs pipes, how to learn to code, node js, node js tutorial, nestjs cli, nestjs nodejs, nestjs vs express, expressjs, node js express, nodejs nestjs, nestjs vs nextjs, nestjs cache, nest.js, nest.js tutorial, how to learn to code for beginners, how to code, coding for beginners, javascript tutorial
Id: 2n3xS89TJMI
Channel Id: undefined
Length: 65min 23sec (3923 seconds)
Published: Sun Mar 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.