Learn NestJS | Full Course | Building scalable Node.js apps

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so what is nest js sjs is a framework to build scalable node.js applications nest js is built with typescript and you can write your applications with that javascript superset js can be configured to use express or fastify as the http server framework but providing a higher level of abstractions above those frameworks nest provides an out-of-the-box application architecture making it easier to create applications with all these great characteristics such as loose coupling high scalability good maintainability and so on if you have experience with angular 2 plus and or typescript is going to be easier for you to learn this framework not only because it's highly encouraged to use typescript to implement nest js applications but also because there are some other concepts that are similar to the angular concepts such as dependence injection by using the injectable decorator or annotation and providers and some other concepts some of the patterns and techniques that nest implements are model b controller dependency injection we're going to see more details about dependency injection in the next slide data transfer object a data transfer object is going to represent the structure of the request body decorators also known as annotations some examples are at get or add post to implement endpoints for those http verbs in a controller some other elements provided by nest are pipes for data validation or data transformation in sjs we also have filters and we can do exception handling there for example we can create an add cache decorator or annotation to implement an exception filter to centralize the management of a specific exception and we can return any specific json response to that exception in sjs we also have chords to implement for example role-based authentication and we can also implement aspect-oriented programming by using interceptors this is the nest js out-of-the-box application architecture where we can see some of the core fundamentals of the framework when we receive a post request that includes that payload we are going to create a controller with a decorator to handle that post http bar then we are going to use a data transfer object or dto to represent the structure of that json payload in this case a show bto after that we are going to use dependence injection in two cases where we are going to inject the shop service in our shop controller and we are going to reject the data access object within the show service then we have our short class that represents the model and if we use for example we're going to use the shop schema class and we can use the model class from mongoose and finally the controller is going to call the create method from the shop service and the shop service is going to use mongoose to insert a new job in the database okay remember to like and subscribe to the channel and let's jump into visual studio okay let's get started by installing the nest js cli so let's run npm install minus g at nest js slash cli okay and now let's create a new application let's run nest new shops api and this is going to create a bunch of files for example as you can see here is going to install bts config if you want to understand what are the contents on that file or what are the settings on that file please check out the typescript video i uploaded an entire video about that topic and it also creates a default controller here a default test spec for that controller a module a service a main file and now we can select which package manager we are going to use we are going to select npm okay and now let's move on to the application folder jobs api sorry shops api and here we can create a new controller so in order to do that we need to execute nest generate or nest g controller and the name of the controller that in this case we're going to create a shops api so let's call it shops okay and this created a folder within the source folder called shops with um shops controller and the test spec for that controller and it also included that controller as part of the main module of the application so now let's go to the visual studio code and we're gonna see that within the shops folder we have our controller that is empty and we are going to start adding the different endpoints for our api and if we go to the app module we're gonna see that we have our controller here this one this import is actually our the controller that we just created so that's automatically import when we create our controller using the nest js cli command and this is a default service that is created by default when we initialize the application the same with this module and the same with this controller that is going to call this a get hello method from the service so here you can see the basically the architecture that is provided out of the box by nest js the entry the entry point is going to be this controller and it's going to inject this service here it's going to show me the service here through this um constructor and if we go to the service we're going to see that the service this app service it's going to have this injectable decorator or annotation that will allow us to inject this service in this case within this controller and we are going to follow the same approach the same architecture and the same structure in our shops api and if we want to let me close this and if you want to run the server in the dev environment let's go to the package.json this is going to generate a bunch of scripts to build the application to format the the code of the application to start the application in production in development here in production in developer management to debug the application etc so we can run this script to run the application on the environment so we can do npm run start column okay now the application is running and if we go to the main file we're gonna see that here we can set up the port where the application is going to listen by default the application is going to use express as the http server framework so let's test localhost on that port comport 3000 and if we execute the get here okay we're gonna get the hello world that is actually the string that is returning this default service okay and now what we're going to create is the slash shops resource or endpoint so let's get started by creating that endpoint so we're going to add a decorator or annotation but first we need to import that decorator from the nest js common library so we need to put get like that and here we can add the decorator or annotation at get and here we can define our endpoint let's call it this endpoint this method actually find all and here we can let's say that we are going to return a string just to check that it works as we expect really really quickly and return fine i forgot to add that okay and now i don't know why he's throwing an error it should be a single quotes okay some records and now we should be fine okay now i'm going to execute the get on localhost for 3000 slash shops and i should get that stream final okay and i'm going to add some other endpoints here get for reading a shop resource post first i need to yeah i forgot to import it i want to report all of them at once get post root and delete these are before http verbs that are actually the four decorators that we are going to use to define our endpoints so it's going to be post let's call it create and just to test it really quickly we're going to return the name of the method and we're going to do the same with add put update i'm going to run my stream and we're going to return the name of the method and the same with the delete endpoint we put the delete decorator i always forgot to add this okay let's save this and let's test the post meta for example i'm going to create a new tab for that post let me copy this url and let's say that we're going to use row and we're going to send a json payload so let's say that you want to create a new job let's pass a title let's say java developer and let's pass a salary salary let's say six thousand okay and if i send this request i should receive the name of the method yes create and the same should happen with the put method actually update yes and the same if i execute the delete method in this case i should pass some parameter to yeah in the update as well right for the update for the put method i should pass some identifier here and the same for the delete method but for now we just we're just testing that our endpoints are responding and are up and running so if we run this we should receive okay yeah i'm going to remove this because we are not defining a parameter let's do that right now so here we should receive an id like this and the same for the delete endpoint let's save this and let's go back to postman and now if i enter an identifier there i should get the name of the method yes now it's able to handle it and the same with the put method but if i execute if i leave this parameter this identifier in the url and if i if i call the get method i should get an error a 404 yeah correct because we are not specifying any parameters on the get method i should add that amplifier on the get endpoint as well so i'm going to do that i'm going to save this let's go back to postman and if we run this yes i get the final that is the name of the method here okay okay so now let's create a service so let's close this and to create the service we can run npm sorry a nest g g remember is a shorthand for generate service jobs okay and now we have our shop service here this one and by default it's going to generate this service with the injectable decorator or annotation and we can pass that object to our controller in the constructor so structure first let's import that service import shops service from this is in the same directory so this is going to be shops shops.service and in the constructor we can pass that dependency and inject that dependency in this controller so this is going to be private read-only shops service shops service and this is going to be the shop service that we just imported and here you can see that automatically we have this shop service to to select so this is basically one of the features that comes with the typescript we get autocompletion using the ide because we have strong typing and that's something that is one of the features of typescript okay so let's go to the shop's service and here what we're going to do is we're going to create all the methods that we need to access our database so in this case we are going to keep it really simple we are going to just inject within this shop service model we are going to use mongoose to connect with a database before adding anything here within this shop's service class we are going to create a module within this shops folder so we can encapsulate and import the service the controller and we're going to need to import some other classes to interact with the database as well so let's create a new file here it's going to be shops that module dot ts and this is and this module is gonna be pretty similar to this one so let's grab all this and we're gonna need to make some changes we are not going to include any of this and we are going to build this one and this one that are within the same folder the shops controller and the shop service and we are going to remove this and this one okay and now and let's rename this as shop's module and let's now let's go back to the shop's service and here what we need to do is we need to create an interface so we can interact with the database so the shop service is going to be pretty simple we are going to pass a model class from mongoose and a shop interface to access the database and we are going to pass that model in in the constructor here so first let's create our shops interface so let's create a new folder let's call it interfaces and here we are going to create a new file that's going to be jobs dot interface dot ts and here we're going to export interface this is going to be the shop interface and here we are going to include an identifier that is going to be optional because we are not going to pass an identifier when we create a new job in the database for example so that's why it's optional so it's going to be a string then we're going to have a title for the job there is going to be a string as well and then we're going to have the salary that is going to be a number okay and here is this and i'm going to rename this and i'm going to remove yes it's going to be just sharp another thing that we need to interact with mongodb besides this shop interface is a schema so let's create the shop schema for mongodb so i'm going to create a new folder and actually i need to move this here within the jobs yes let's move yeah and here i need to create a new a new folder [Music] it's going to be schemas and here we're going to create a new file that is going to be shop.schema.ts and here we need to import mongoose let's say import asks mongoose from mongoose and now let's create the schema so export const shop schema equals new mongoose dot schema and here we're going to find the fields of the document and we're gonna have a title it's gonna be a string and salary that's gonna be a number okay probably i need to install mongoose right npm install mongoose okay now we have mobus so now we don't have any any errors here and now let's go back to the shop module and here what we need to import is the modbus module let's send it here import [Music] she yes slash we probably need to install that yeah so let's install this npa npm install okay now we have that dependency installed we need to also import the schema of the job so import show schema from and this is in we need this schema folder i'm sorry nice schema schemas slash job schema okay and here we need to add a move module that for feature and here we need to pass the shop schema like this this is an array sorry an array and we need to pass the object here that's gonna have two properties the name that's gonna be a job and the schema associated to it that is gonna be shop schema like that okay let me remove this and let me remove this okay let's add some space here and i think we're good to go okay okay something is wrong here export ah yeah that's the issue okay and now we should be fine great okay so now we can go back to our service and we can inject the model so we can add the constructor and we pass the model here but first we need to import a couple of things we need to import our interface that is the shops interface from this is within the interfaces folder interface and then we need to import the model class from mongoose and finally we need to import the inject model option from the mong use [Music] module within nest js import check model from nest js and here we can pass insect model and we pass shop as the name of the model private read-only [Music] model and here we use the mobile class from mongoose that one and here we need to pass the interface that we created that is going to be shown okay now we have our mongoose model ready to use um there's an error here is show like that okay okay and now some other things that we need to import in order to connect with mongodb we need to go to the main module of the application and we need to import a couple of things here we need to import the model that we created let's go to the shops module from and this is within the shops folder this one actually like that let me check shop module okay i'm going to rename this actually it should be shop's module okay shop's module let's go back and this is yes great and let's rename this as shop's module okay that's one thing we also need to import the mongoose module mongoose module [Music] and this is going to be this one okay now we have the shops module the mongoose the mongoose module and we need to add those imports here so here we have the shops module and here we need to pass mongoose module and here we pass the url forward okay and here we need to paste the mongodb uri it's going to be a string and it's going to be 27 [Music] 0 17 and then there are basically shops let's save this and we have everything ready to interact with our database from this service okay so let's create some methods so we're gonna need four methods to be called from the controller so let's go back to the controller so we're gonna need one method in the service to get a shop buy id another method to create a new [Music] job another one to update a job and the last one to delete an existing chart so let's go back to the service and let's start working on those methods let's create the first method that is going to be defined [Music] where we're going to pass an identifier of the job that is going to be a string and here all the methods that we are going to use from this mongoose model are going to return a promise so here we need to set the type as promise and in this case you're going to return a job so we need to add that interface as part of the signature of the meta and here what we are going to do is return actually this is gonna need to be an async method and here we're going to use a weight so this is going to be this that should model that fine one and here we are going to pass the identifier that in this case of that for mango is going to be underscore id and we pass the id that we receive as an element that's going to be the first one then we need to create another one to create a new job so it's going to be also an async method create and it's going to receive a job and this is going to return a promise as well like this so we need to find a new job here const job and here we need to do new things that show model and we need to pass the job and here we're going to return [Music] a weight new job dot save okay the next one is going to be the update method and we need to use pretty much the same the only thing that is going to change that is that we are going to receive two parameters one is going to be the identifier it's going to be the string and the other one is going to be the job and here we're going to return await this.model that and here we are going to use define by id and update method find by id and update and we're gonna pass the identifier the job and we're gonna set that if the item and we're gonna set that if the job doesn't exist it's going to create a new one new new tool and we need to rename this method as update okay that's the update method and then we're going to create the last one that is going to be the delete method and here we only need to pass the identifier string and it's going to return the same promise as before and this is going to return a weight is that your model and we're going to use the find by id and remove method find right id and [Music] remove and we just pass the identifier here okay and now we have our service credit with all the methods that we need and we need to start working on our controller so we can call these methods and start finding existing jobs creating jobs updating shops and removing jobs so let's go back to the controller and let's start using this shop service but first we need to create a dto to [Music] model the structure of the payload that we are going to receive so this is the json object that we're going to receive it's going to have two properties title and salary the same that we defined here on the interfaces here title and salary okay let's go back to the controller and let's create a dto so let's create a folder within the shops folder that is going to be dtos and let's create a new file that's going to be dot dto dot ts and here we're going to export class we're going to call it shop dto and we're going to have two properties here read only title that's going to be a string and read only salary there is going to be a number and that's pretty much it okay and now if we go back to the shops controller we need to import that dto so import dto from videos [Music] slash shop.dpo okay the first one we we don't need the video here so we just call this.service that fine and we passed new identifier that we need to actually it's not final is fine and we need to pass the identifier here [Music] actually this needs to be a pattern this another [Music] decorator that we need to import first so let's do that param and now we can use it on our method so find that and the name is going to be id and here we pass that maybe as a parameter to our service and here is going to give us is going to give us an error because this method within the shop service is returning a promise so we need to add that to the signature of this method so now we are good uh yeah i need to import also this shop interface so let's do that so here it's going to be job from interfaces interface okay now we're good okay the next one here we're gonna need [Music] the dto and we're gonna need to import another decorator that's gonna be the body decorator this one so now we can use it in our post endpoint like this add body and here we create the show parameter that's gonna have the type shop dto and here we're going to use again the service is that service shop service sorry that create and we're going to pass the dto okay and now this is going to return the promise and if we go to the job so we have the interface and if we go back to the dto we're gonna see that we have title and salary that are part of the interface definition here title and salary and the identifier we define it that property as optional so everything works just fine okay let's go back let me close this let's go back to the controller hey sorry not this one the shops controller this one actually and let's move on and let's work on the update method here we are passing this id that is going to be part of the url but also we need to pass the payload here so we're going to use the body decorator again we're going to pass the dto and we're going to also here use the bottom decorator and here we receive the identifier as part of the url so the pattern is basically taking the data from the query stream and the body the creator is going to get the data from the body of the request and here you can find identifier okay and here i need to call the service method so um again i need to return the promise so let's do that and i need to go to search here is that service dot update and i'm going to pass to arguments identifier and the video okay that again here we have the identifier and here we have the interface and the dto is compliant with that interface so we are good okay and the last one is going to return this promise as well i mean the delete method and we only need to pass the identifier in this case let's save this and here we need to call again the short service and the delete method and we only pass the identifier okay let's let's start the server again okay there is an error here okay i found the error here what we need to do is we need to remove these modules this sorry we need to remove this uh the controller and the server from the app module because we already imported those that service here within the shops module file so we are going to remove that from here and i'm going to keep it just in the shops module and remove this okay and now we should be fine yeah we have the routes so now we can test our controller so let's start by creating a new job so i'm going to use the post method to remove this and i'm going to run this okay we have our new job created so if we go to the database we should see here refresh we should see one document here that is actually this one okay so now let's take the identifier and let's try to get that job so slash fire and if we submit this yes we get the same information and let me yeah yeah we get the information okay and now let's execute that booth method so let's change for c plus plus developer let's send this and now we get the shop modifier and the title has changed and we go to the database and we refresh this sorry close this and if i refresh and if i open the existing document yeah we have the new title assigned to this document okay let's close this let's go back to bosman and let's execute remove so let's run the delete http verb so if i send this yeah i get the removed element and if we go to the database and i refresh we should not have we shouldn't have any documents yeah so we don't have any documents here the next.js exception filters can be applied using a decorator in a method or in a controller or we can globally apply a filter by declaring it in our main ts file let's jump into ps code and let's see how we can use exception filters on a previous video we created our shop's controller basically here we defined all the different endpoints of our api we defined a get endpoint the post port and a delete endpoint let's execute the post endpoint for example so let's create a new job and let's pass c plus plus developer as the title as the salary we passed seven thousand so let's run this and okay so now we created in our mobile db a new developer so if we go to the mongodb database we're gonna see that we can access that document here in the jobs database we have the c plus plus developer and the salary has 7000. okay um so let's go back let's grab this identifier and this identifier we can go to the api and we can get the shop information okay but what happens if we change the identifier let's put something random here and we send a request so we get we still get that 200 response and that's not correct for a restful api because we want to receive in this case when we don't get any results we're going to get a 404 or an http and not fun so let's make a change in our get endpoint let's go back to our controller and let's make a change here in our get endpoint so we can return an http status according to the result so if we don't get any results from the database we need to return and not found http response follow for so here what we need to do is we need to handle this promise so we are going to add again here and i'm going to create a narrow function to handle this promise response where i'm going to receive a result and what i want to do here is if i get the result i'm going to return that result but if we don't get any results i want to throw an exception so this will allow us to see how nest js handles http exceptions by default and then we are going to create our exception filter and we're going to see the difference between the two strategies the next js default strategy and the filter strategy with the class that we are going to create so now what we're going to do here is i'm going to throw an exception draw new http exception and i'm going to pass the message show.com and i'm going to pass the http status and i'm going to return the http status as not found actually the http code is photo 4. i want to return that and i'm going to also add a catch block here i'm going to create another another arrow function for this and here i'm going to throw the same exception okay let's try this now and now we send the request and we receive a photo form as we expected and the message that we just entered there okay so this is the default behavior of nest js and now i am going to create a filter and i'm going to centralize the exception management using that filter and first i'm going to grab this code from the nest js documentation and i'm going to customize this printer a little bit i'm going to create a new folder this is going to be filters and i'm going to create a new file that's going to be http exception dot filter dot yes and here i'm going to paste the code that that i grab from the nest s3s documentation website okay basically what it's doing here is implementing the exception filter interface with this http exception filter is using this sketch decorator with this http exception as a parameter so it's going to catch all the http exceptions depending on the scope that we define we're gonna see that in a second and here what he's doing is extracting the response the request he's extracting the status code from the exception and he's generating this response including the status code and a json with stereoscope a timestamp a path and we can add whatever we want and for example the description or something like that okay and now what we can do with this filter this http exception filter that we are going to import into the controller now let's copy this http exception filter and here we can apply this filter at a method level or at a controller level and in order to do that we can use a specific decorator that is called use filters where we can pass a list of filters in this case we are going to pass just this one http executive return we can pass it in two ways if we just pass the class name as it is now the framework is going to inject using the dependency injection mechanism is going to check the instance of this filter the instance of this class or we can create the instance ourselves like this and it's going to work either way so let's just put the class name so let's js is going to inject an instance for us okay let's try this now let's go back to postman and let's execute this request on a random with a wrong identifier that we know that is not in the database so if i execute this request now i get the custom [Music] json that i define it on the filter as we can see here that we have a status code a timestamp a path and a description this encryption http error so that's one way of specifying the or applying the filter right at the method level we can also apply the same filter i'm going to grab this and move it at the controller scope so [Music] if we throw an exception in any of these endpoints is going to apply this this filter at the control level so let's try this now and if we go back and if we run this we should get the same response yes we get the same response as before and if we remove this completely we can include that exception filter globally in our main file so i'm going to grab this and i'm going to paste it here i'm going to import this filter here in our maintas file i'm going to change the path and what i can do here is i can do app that use global filters and here i can pass a list of filters in this case i'm going to pass this only this filter and here it is here i need to create an instance of it okay and let's go now and let's execute our request again and we're gonna get the same result so we apply applied this filter at a method level then we applied the same printer using the collector as a controller level and finally we created or we apply this filter globally next three years validation pipes we can apply validation wipes using a decorator in a parameter in a method or in a controller or we can globally apply a validation pipe declaring it in our main ts file let's jump into ps code and let's see an example of a validation type okay now let's create a validation pipe so as you may remember nestjs allows us to use dtos to encapsulate the body that we receive as part of the requests in our endpoints for example in our host endpoint so what we're going to do first i'm going to stop the server and i'm going to install a couple of dependencies so i'm going to run npm install save class validator and class okay and the first thing that i need to do here let's run server again i'm going to the dto and what i'm going to do here is i'm going to import the class validator library import that's validator and i'm going to import a couple of decorators this string and is it and i'm going to use these decorators here string and is okay and using these decorators i'm going to be able to validate the input but another thing that i need to add is the actual pipe so i'm going to create a new folder let's call it pipes and i'm going to grab the validation pipe from the nest js website we also have the alternative to use choi soy is another library in this case we're going to use class validator okay and this is the validation pipe that i want i want to use so let's create a new file here let's call it validation that by that ps and let's paste code and this is going to implement the pipe transform interface and he's going to make some validations he's going to make some transformations and here i need to i'm going to change this to any so we're going to get an errors okay so let's go back to our controller and here what we can do is we can apply this is pretty similar to the filters where we can apply the validation pipe at a method level a controller level a global level and also at a parameter level so we can actually add the validator here so that's going to be the first thing that we're going to test we can add validate let's grab the this one we can use the validation pipe like this and we need to import it first actually so to import validation pipe from pipes validation.type and here we are going to validate this shop dto at the param level so let's go back to both man and let's execute the post request but instead of passing and a number an integer we're going to pass a string here so we should get an error yeah we get the http error remember that we still have running here in our main.ps file we still have this exception filter so we can do something different here if we go back to the type we're going to see that what we are throwing here is about the request exception so we can copy this exception these are not this is not a good practice but just for the sake of giving an example of this i'm going to copy and paste of course we need to create a super class we need to extend it we need to try to don't repeat ourselves but just for the sake of the example i'm going to copy and paste this i'm going to rename this and i'm going to call it validation exception filter dot yes and here my going to catch this button request exception and let's make a couple of changes here import this okay um here we can say bad request let's say this and now if we go back to the main.ps file we can use that filter so let's import it this is that let's grab it from the here and actually i'm going to change i'm going to rename this one to by the deviation filter or the validation exception filter that's gonna be better and i'm going to import that here validation exception filter and i need to change this this is going to be validation exception data filter and i'm going to use this one okay now if we go back to postman and we execute the same request we should get a different description let's run this and we get the description that we specified for that exception specific so in this case we are using two things we are using this validate on this validation type and we are using also a validation exception filter and if we go back to the controller we can also define this validator or we can apply this validator at the method level we can say sorry this is use pipes and we can pass sorry the this is the validation file actually so if we execute the request again we should get the same response yes we get about request and we get the description that we specified on the filter for the validation exceptions and we can also use pipes at the controller level so let's do that and let's go back to both mine and let's run this again and we're going to get the same the same response and if we remove this from here select this i'm going to grab evaluation pipe and i'm going to include this validation pipe globally in our main.ts file i'm going to change the path [Music] and i'm going to use here app dot use global pipes and i'm going to include the name of the pipeline to create a new instance of the validation part actually pipe and now if we go back to postman and if we run the same request we should get the same response next three is custom decorators we can create a custom decorator to be more specific regarding the request that we receive in our endpoints and custom decorators will allow us to improve the code readability of our application is going to improve the reusability and we can also apply pipes on these custom decorators for example a validation pipe or we can also access a particular property from our custom decorator a custom decorator can also be useful if we need to pass the data of an authenticated user in multiple endpoints so let's go to bs code and let's create a custom decorator for our api okay and now let's create a custom decorator so i'm going to create a new folder decorators and i'm going to create a new file i'm going to call this show data dot decorator dot ts and here what i'm going to do is i'm going to import a function the function is create param decorator from the nest cs common liberty next yes okay and here what i'm going to do is i'm going to create a constant data and i'm going to use that function to create my custom decorator the idea is to use this decorator instead of using body here let's go blackboard controller so instead of using add body as the decorator i want to use at shop data so it's not that it's not just a genetic body it's a specific request that i'm going to describe there right i'm going to describe this shop dto data so let's go back to the integrator and here is going to this function is going to receive an arrow function where i'm going to receive that data i'm going to see a data argument it's going to be a string and then the request and here what i'm going to do is i'm going to return if i get data i'm going to return the body of the request i'm going to do a condition here to check that i receive the data break that body theta and in the other case i'm going to return b body completely okay let's go back to the controller and i'm going to import that custom decorator so import data from the creators show data that decorator and now i can use that decorator here for example and now i should be able to create a new job as usual so let's say java developer 8 000 let's run this and i am able to create it and we still have our validation pipe and our validation exception for the running so if i pass this as a string i should get another yes i get the same error as before so it's still running i'm going to command this and i'm going to apply this validation pipe at this level at the param level so i can pass it here and if i run this request again i should get the same error yeah i get the error but i'm not wrapping i mean i'm not using the custom exception so i'm going to add that exception here so i'm going to use the filter use filters and i'm going to pass the and let me go back to the main.ts this one validation exception filter i'm going to pass that one okay i think i have to import it okay let's grab this up here let's go back to the controller and let's paste it here let's paste it here and change the path like that okay and now we should get the error and we should get the json that we specified here with this but request in the description so let's go back to postman and let's run this again and yes we get the json that we specified on that validation exception filter so if we go back to [Music] let me close everything here so if we go back to the controller to the shop's controller here we are using a custom decorator with a validation pipe and we are also using the validation filter or the exception filter here at the method level nest js middlewars a middleware is a function that is called before the route handler with access to the request and response objects and the next middleware function if the current middleware function is not able to end the request response cycle it must call the next function to pass control to the next middlewarm function by default a nest sjs middleware is equivalent to an express middleware what can i do in a middleware function i can execute any code i can make changes to the request and the response objects i can end the request response cycle or i can call the next middleware function okay let's jump into visual studio code and let's create a custom middleware to audit some specific operations performed in our api okay as you may remember in the first video of the next sjs crash course we created an api a shops api actually and we implemented a controller that is this one and here we created some methods for each of the endpoints of our restful api we created a get operation where we are passing the identifier of the shop to get that specific job we created a post method to create a new job we also created a put method to update the data of a specific job and we also added a delete operation and here we are we have this decorator these are actually the creators and we here we have the decorator to handle the delete http method so what we're going to do now is we're going to create a custom middleware to actually audit all the delete operations that are going to be performed in our api so a middleware will be executed before reaching this method here so what we're going to do is we're going to log some specific data from the request and so let's do that now i'm going to create a folder little words and i'm going to create a new file here and i'm going to call it audit dot me build word dot yes and here what i need to do is i need to create a class export class audit in the world and this class needs to implement the next middleware interface so next middleware and here the nest middleware interface if we go inside that interface we need to implement this method so we are going to run a quick fix here this is going to automatically add that the template with for that method and here we have the template of the method and as we can see here we get access to the request the response and the next function of the request response lifecycle so here we can use the express classes so request is actually an interface from express if we go here if we go there we're going to see that csun interface okay and also here we can import the response from express like that and here we can say that this is going to be a function actually function okay and here we are going to start working on our audit logic right this needs to be injectable so we are going to use that decorator here and now what we're going to do here is we're going to console.log some properties from the request we're going to log the ip address the path and the headers for example we can do that login delete request ip and we can access the ip property from the request install that logo and i'm going to copy this login delete request and path and we can access the path property from the request request that that path like that and we can also access the headers for example so login delete request headers and we can access the headers property from the request like that and this is our audit middleware so every time that we receive a delete request we are going to log all these properties from the request the ip address the path and the headers and now we need to set it up so in order to set it up we are going to do that within the shops module that includes the controller the service and what we need to do here is we need to implement an interface that is the nest module interface and if we go here this is going to give us a quick fix here and this is going to add the skeleton of the configure method if we go to the interface we're going to see that that's the only method that we need to implement so let's go back and let's click here on quick fix and implement interface nest module okay and remove this and i'm going to remove this here and i'm going to add this because i can import that middleware consumer from the nsjs command library okay and here what we are going to do is we are going to apply the middleware that we just created to the consumer to this middleware consumer so first i'm going to import import audit middleware from audit middleware and we're going to pass that class here in the apply function and because we created this audit middleware class as injectable we're using this injectable decorator we the nest shares framework let me close this the next chase framework is going to automatically create an instance for us here and after this we can set up the routes that we want to use to apply this audit middleware so we can say four routes and we can pass an object and this object is going to include a couple of attributes one is going to be the path in this case we're going to use the shop spot if we go to the controller we have the shops string as part of the url and we're going to use that to set up our middleware here so we're going to say shops slash and we're going to use the wildcard and here we're going to set the method that is going to be the delete http method like that and that's all we need to set up audit middleware for this specific method and now it will go back to postman and click on send okay we have some shop postings already there and i'm going to remove one of these and we're going to see [Music] here in log we're going to see these messages the ip address the path and the headers okay so let's run this delete operation and as we can see we get the ip address this is localhost using ipv6 this is the path and these are the headers of the requests of the request and the problem here is that what we need to do here is we need to call the next function so i'm going to add that here just below this causal log and now it's going to be actually run the delete operation and let's run it again let's delete that so posting and now it's actually executed and here we have all the messages that we defined here in our audit middleware login delete request ip path and headers and if we go back to postman and we execute the gate operation we are not going to see this element again it was actually removed nest js interceptors interceptors allow us to implement aspect oriented programming so we can add extra logic before or after the execution of a method we can transform the result of a function we can transform the exception thrown from a function we can extend the basic function behavior or we can completely override a function depending on specific conditions for example caching as we've already seen with pipes interceptors can be controller scoped method scoped or global scoped and an interceptor implements the intercept method with access to the execution context that is actually an instance of the execution context class using that class instance we can access the http request and response objects let's jump into visual studio code and let's see how we can use interceptors for caching and also for benchmarking in our api okay we are going to set up first a caching interceptor and we are going to install a library for that npm install save it's going to be a cache manager and this cache is going to be in memory we can also set up this cache using redis for example we can use some decorators that are part of the nest js common library and for example we can set the key of our cache using this decorator we can say here single quotes all jobs and we can set up the ttl of this specific for this specific method now we're going to see how we can set it up globally and this is going to overwrite the ttl that we defined there but first let's define it locally and here we can say 15 seconds for example and we can do the same for this method here and here we can say and we need to use this interceptor this is another decorator called use interceptors and here we can add a list of interceptors in this case we're going to use the cache interceptor i disagree with this one okay and to set it up we need to go to our shops we need to add the cache module like this cache module that register and here we pass an object as a parameter and here we said that pl the global dtl in this case let's say five seconds these are seconds and the maximum quantity of items within that cash let's say i don't know 100. maximum number of items in cash and that's all we need to set up our in-memory cache if you want to set up radius for example you need we need to add some more parameters here such as the url the port etc okay let's try this i'm going to run to start the server again and let's go to ultman and here first i'm going to execute a get request this should be caching this data for 15 seconds and what i'm going to do is i'm going to remove one element directly from the database and i'm going to remove the first element so i'm going to delete this document but i should still get it yeah i still get it but if we wait a couple of seconds now yeah was removed so let's go back and the same is gonna happen for this find endpoint for this get endpoint by id id so we can run this let's create now let's add this identifier here okay we still get that element but let's go to the cache sorry let's go to the database and let's let's remove that one this actually this one the first one let's remove that document and now we call it we still get it it's going to it's going to be available for 30 seconds okay and now it's no longer available great okay now we have our cache all set and now what we are going to do is we are going to create a benchmark interceptor that is going to log the execution time of each of these methods here okay so let's do that i'm going to create a new folder i'm going to call let me it this okay i'm going to create a new folder let's call it interceptors and i'm going to add a new file this is going to be benchmark revenge mark that interceptor dot yes okay now i'm going to grab this class from the nest js documentation and i'm going to tweak it a little bit i'm going to add a couple of things we have access to the execution context that is actually this interface that extends argument host and we are going to use this method to access this interface where we can get the request and the response and we are going to extract the http request url and method and we are going to show the execution time for that specific endpoint using that http method okay let's go back let's close this and this okay and here what i'm going to do is i'm going to get the cons the context ctx equals context that switch to http and now i'm able to access the http request option request equals cpx.getrequest this is going to be the express request so i'm going to put that one the first one and i'm going to load using the console i'm going to load the endpoint request that url and i'm going to log the http method that i'm using to execute that endpoint method request that yeah and here what you're doing is we are running the next middleware in the request response lifecycle that is actually the one that we receive here and after that execution we execute this tab operation and we are logging the execution time so here we get the the timestamp before running the method and at the end what we do here is the difference between the current date this is where the method finishes to run and the and the timestamp that we assign before running the method okay here we can say execution time let's go back to the controller and the only thing that we need to do here is we need to import this benchmark interceptor let's rename it as benchmark interceptor and let's import it first import import from interceptors benchmark that interceptor and now we can add it to this list for this use interceptors decorator and that's all we need this is going to show the benchmark or the execution time for every endpoint here on this controller okay let's go back to postman and let's run this endpoint through this let's run a file endpoint and if we see here we get the endpoint the method and the execution time for that operation and let's remove an element and in this case we're gonna see the benchmarking and we also gonna see these messages here that are part of the middle one so let's run this and if you go back here first the middleware is going to lock all these messages the ap address the path and the headers and then we're going to see the benchmark interceptor running that's going to show the endpoint the method and the execution type okay so far we've been working on a restful api we created a controller here to handle different http methods of our shops api we printed the get post put etc and now what we're going to do is we're going to reuse this controller but in a different way so we have to create our web application doing the rendering on the server we need to create a couple of folders first we are going to create a public folder where we are going to store the css files the fab icons some images logos the robot file etc and we are also going to create a new folder we are going to call it views where we are going to include the html templates and we are going to use two template engines the first one is going to be pug index.pug so here sorry here we are going to include the html using this template engine and we're going to create another one that's going to be index that hbs where we're going to use handlebars handlebars is a superset of mustache and pug was previously known as shade the shade framework and here we are going to create i'm going to create a new folder actually it's just to keep things organized and i'm going to move these files there so we are going to use our shop's controller that is this one and i'm going to keep those views within the shops folder just to to be consistent with the naming and structure okay the next thing that we need to do is we need to update let me close this and we need to update our main.ts file so we can include we can set these folders the public and the views folder in the application so we're going to use express and we need to make some changes here here we need to use the nest express application and we're going to pass the app module we need to import that class import copy the class name [Music] and we need to import this from nest chef yes platform express and now we have to associate these different folders our static assets folder and our views folder so [Music] up that use static assets and we need to pass the public directory and we are going to use join we're going to use their name this is our reserved word and we're going to position this on one level above the current file and we're going to pass the file the folder name that is public and we need to import the join function okay and now i need to associate the views directory using set base views there and it's going to be pretty much the same instead of public it's going to be views and we should also associate the view engine up that set view engine and we're going to start using pile okay the next step is going to be installing actually the view engine i'm going to start to uninstall bug and handlebars so we can use bug or we can use hps that is handlebars so i'm going to run npm install save plug and handlebars okay the next thing that we need to do is we need to go to the main module of the application and i'm going to remove this default controller this service we are not going to use those i'm going to remove this dependencies here and now i'm going to make some changes in the shops controller i'm going to use this method where we get the list of jobs and i'm going to rename this function as root i'm going to remove the type and i'm going to add a decorator to associate the view the decorator is render and i'm going to pass the view here that is going to be index sorry that is going to be shops slash index so it's going to be actually this views that we created here within the views folder okay let's go back and here what i'm going to do i'm going to change this a little bit because this is returning a promise and this is actually an array of shops like that and let's go back so i'm going to make some changes here and i'm going to add a then statement or i'm going to receive a result and if i get results i need to return a specific structure and specific model that is required to be rendered in the view i need to return an object and this object needs to include some attribute so i can access it from the view so if we get any results i'm going to return this object i'm going to add an attribute i create an object with just one attribute that is going to be shops and it's going to include this array of shops but if we don't get any results i'm just going to return an empty array it's going to be like this shots and an mp array like that okay and now we can work on our views that are going to render this model this one okay let's open first let's work with the index using pug so html here we're going to assign a title we're going to call it bug show index and we need to add a body and we're going to add a list and each item of this list is going to be a job that we are going to get from this method okay and here i'm going to iterate through the collection that we get that is actually this collection this shops collection and here is going to be each shop in shops shops is the attribute name of that model and here we are going to create a list item where we are going to include the subtitle and the salary like that okay let's try this run start that and now let's open the browser in localhost 2000 slash shops slash and yeah we should be able to get okay something is wrong let's see what's going on okay my bad this is shops slash and index okay save this let's try again and here we get undefined okay some type of there let me check yeah it's not tile it's title okay let's refresh okay here we get all the elements i didn't show you the database but if we go to the database let me open the database here is the shops collection and we have these four documents c plus plus developer c developer c-sharp developer and javascript developer all this form okay let's close all this let's go back and now let's create first let's change the view engine to handlebars and let's create our html template here so this needs to be html.html html let's add header head title let's call it hbs and then check the name just to shop index add the body and here we on another list and we're going to iterate each element of the shop's collection jobs i need to close this each statement and within this i'm going to add a list item and here i can access the attribute of each shop like this title and the salary okay we have the handlebars view engine assign so if we refresh we should get a different title hbs shop index but the same list let's write this now and yes we get the same list and we had hps 400 bars and shop index okay so we've been working so far on our shop posting api and we created a controller where we define at different endpoints get endpoints post put delete and we also created a dto for the post and the put operations this one and those are the two classes that we are going to be changing or we are going to add documentation using some swagger decorators once we add those decorators we are going to be able to generate an interactive documentation that we will be able to access from the web browser and we're going to see the different endpoints the schema the data structure some other things that we're going to define on these decorators and we are going to be able also to test the api get the shop postings available create new shop postings update postings delete postings before adding any swagger decorators we need to install some dependencies so let's do that now npm install nest js swagger and we also need to install swagger ui express remember that with nest cs we can use express that is the default http framework or we can also use fastify and if we are using fastify we need to install a different set of dependencies for swagger but in this case we are using express so where we need to install specifically this one swagger ui express okay let's run this okay the first thing that we need to do to set up swagger we need to go to our main.ts file and we need to create a couple of elements here we need to create the swagger configuration where we're going to set a title a description the version of our api so let's do that this is going to be swagger config [Music] and here i'm going to create a new document builder and here i'm going to save the title let's import this first okay i want to import document builder from sjs slash blogger and now i'm going to set the title this will be shot postings api i'm going to set the description it's going to be short posting shop postings crowd api we are going to set the version of the api it's going to be 1.0 and to finish we need to include that we need to call the build method of the document builder object and now we need to create a document using the swagger module class const equals so other module that create document and we need to pass the app that is actually the application that we create with the nest factory and we need to pass the swagger configuration that we just created using the document builder here and we need to also call the setup method of the swagger module library and here we're going to define the url that's going to be api and we pass the app the app that is the next js application and we need to pass the dock that is the document that we created here okay now let's go to the controller and here we can add some decorators we can add an api tags decorator api tax as we can see here this decorator was automatically imported here on line five and here we are going to set the shots as the tags for this api okay and some other decorators that we can add here are for example we can add api yeah okay response is one of those this is actually a decorator from sjs this extends some decorators from swagger and here we can pass the description in this case gonna be the resource list has been successful for the return in this case this is the final method where we are returning all the short postings available so this is one of the decorators for our endpoints and we can also add another decorator and let's say that we want to return at some point an http 403 a forbidden response api 4b then response we can also set a decorator for that response and here we can add the description to document this response so we have a description and here we're going to say forbidden just to keep it simple and here we can add these decorators to the rest of the endpoints and for the post method we can use um here we can change yeah the description the resource has been successfully returned because here we are accessing just one element using the identifier and we've got the type of identifier that's going to be a string [Music] and i think i'm going to put that here as well i'm going to add that here string and here and for the post operation there is another decorator that is the api created response but here we're going to change the description and this is going to be the resource has been successfully created and for the rest we are going to use these two the first one and it's going to be the resource has been successfully updated and the last one is going to be the resource has been successfully removed we are going to also make some changes in our dto and here we are going to use the api property decorator this one and here we can pass some parameters we can pass the type [Music] and this case is going to be a string we go as a description we can put something like the title of the shop position and we can set a default value we're going to leave that empty okay and the same for the other attribute in this case the type is going to be a number we're going to say the expected salary of the shop position and default is going to be 3k and let's try this so i'm going to run npm run start web okay and now i'm going to open the browser on localhost 3000 slash api and we're going to see the documentation this is let's go back a little bit this is the title that we assigned here shop postings api this is the description that we assign here show postings crowd api and these are all the http methods this is the default endpoint that is actually this one if we try this we are going to receive the hello world this one so we are not going to do anything with this let's move on to the shops this is the one that we just modified for example we can check the schema this is the shock dpo that we just changed with adding this to decorators so this is the title property that is a string and this is the description that we define it here to fix this and the same for the salary the default value and the expected salary for official position is the description that we assigned here okay and if you go to the get endpoint where we get the list of the shops here are the responses here is the okay response that is actually this one api okay response and this is the description and we can see the same description here and this is for the 403 code the forbidden response and this is the description that is the same that we have here and it's going to be the same for the rest here here and the others okay and let's try this one if we run this we only have one shop position in the database that is this javascript developer position and here we have the schema associated to the request let's create one so we're going to create a new shop posting let's call it c plus developer and salary 9000 and let's run this and here we have our new shop posting if we go back and we execute the get operation to get the list of all the positions available here we get the javascript developer and the simple plus developer okay and here we can also get a specific job for example if i copy this identifier and i'm going to click here and try this out i can enter the identifier here execute this request and i get the expected shot posting for that identifier and i can also modify that same object from here or i can delete that element so i'm going to copy this and let's change the salary and i need to enter the identifier and if i run this here i get about request unexpected token oh yeah that okay and here i get the updated posting okay and if i go here to the get by id if i use that identifier i should get the updated response yes with the new salary okay and now i'm going to remove this show posting i'm going to entertain here and i'm going to execute that request and i get that 200 so it was successfully removed if i go back and if i get the list of all the shop postings available i should get the javascript developer and that's yeah that's the only element that we have in the database okay this is what i have to show you for the swagger documentation now let's move on to the compodoc documentation so compodoc is a documentation tool for angular and it will support necessity yes and it's going to generate a static documentation so basically it's going to parse the source code of our application and it's going to generate a bunch of html files that we will be able to access from the web browser we're going to see that in a minute and some other characteristics are it provides a clean and simple design and it provides some themes that we can select it supports four languages and we can also search within this ui that compodoc creates it also generates automatically a table of contents for our documentation and it's a local tool it it's going to run locally of course in our development environment and it's going to start a web server where it's going to serve these html files with the documentation and no typescript compilation compodoc is only parsing the typescript code as it is so it's not transpiling anything and it also supports some decorators from the share stock library at param at returns at link at ignore at example and it also provides a reporting on the documentation coverage and those are the main features of this tool so let's go back to visual studio code let's close this and let's install the compodoc dependency so let's run npm install this is going to be installed in the development environment at combo dock slash compodoc okay now that compodoc is installed i am going to add a script here and this script is going to generate the documentation and it's going to open the browser on port 8080 because it's going to start an http server on that port and we are going to be able to access the documentation from localhost port 8080 so i'm going to create a script i'm going to call it compodoc and the command is going to be npx compodoc minus p and it's going to take the ts config file this is where we configure the transpiling of the typescript code minus s and let's run that script npm run compodoc and this is going to show the data folder that we're going to see here this documentation folder with a bunch of html files and folders etc and now we can access the recommendation using this this thing okay on the left side we can see this index let's say of this table of contents and here we can see the modules the classes the interfaces some miscellaneous and the documentation coverage reporting here so here is the readme file here we have some graphics of the modules of the application here we have the app service and the app module this is the default module we can zoom in these are the default modules that come with the application and here is the module that we created the shop's module and the shop service and we can check more details here we have the app controller we have the app service this is the default module and here we can go to the shops module where we can see the shops controller here we have all the methods the source file here we have all the decorators that we created for for swagger and here we can access the dto definition with all the properties and let's go back we can see all the methods of the controller we can also access the short service documentation the source file or we can see directly the source file here and we have access to the documentation of the different methods of the service and here we have access to the dto interfaces that we are using and here we can search for example if you want to search for the shop's controller here we can see that we get the results and that's pretty much it so this is a really good way to document our application and it's really really easy you just run that command and it generates all this html content for you you
Info
Channel: Pragmatic Reviews
Views: 1,587
Rating: 5 out of 5
Keywords: Nestjs tutorial, nest js tutorial, nest tutorial, nestjs framework tutorial, nest framework tutorial, nest js framework tutorial, Nestjs crash course, nest js crash course, nest crash course, nestjs framework crash course, nest framework crash course, nest js framework crash course, learn nest, learn nestjs, learn nest js, learn nest framework, learn nestjs framework, learn nest js framework
Id: k6ya4ZVlMAg
Channel Id: undefined
Length: 141min 47sec (8507 seconds)
Published: Mon Jun 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.