Building a Production-Ready E-Commerce App: Node.js, Prisma ORM, TypeScript, and MySQL

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey there everyone and welcome to the new course section it is the most exciting part of this course where we will be building the full fet production level application so in this section we will be exploring all the things all the best practices which are followed when we are building something production grade so it will be a pretty exciting section and there will be a lot to learn so just follow along so what we are going to build in this section is in classic e-commerce app so why e-commerce because uh with like with the help of e-commerce app you'll be able to understand each and every concept very clearly like all the relations validations user authentication role based authentication how to differentiate between admins and a regular user and all these things so it will be pretty uh good project to implement and you'll learn quite a lot so what we'll be building so here are the database tables that we'll be having so one is the users products card and orders table uh apart from these like there will be several other tables as well like the pivot tables between order and products and so we'll we'll figure that out when we like move forward in this section and similarly like here are the routes for the user we have a login route and a signup route and then a mi API to like get the logged in user based on the a token so here we'll be like uh implementing the full authentication system how it's being implemented in the production role based authentications all the middle wees like how to differentiate between user admin which route can be accessible which route can be accessed either by like only by admin or by user so we'll be exploring a lot uh similarly for the products as well we have all these routes products and get put and delete and this is a get this is a search API for the product in which we'll be exploring a like a totally New Concept which is a full text search like not new but a new compare to this course because we haven't touched on full text search how to do it in Prisma so we will perform that and and for the cards we have all these apis and orders so I'll link this image in the resources of this lecture so you can follow along like what we are going to build so this is the high level overview of all the routes that we are going to build obviously there will be some addition to this uh when we like move forward in this course and I'll convey to you as we follow along so yeah uh I'm pretty excited to like teach all these things to you and most important we'll be using typescript for this so we'll be using node J Express typescript and obviously Prisma so yeah uh so follow along like uh learn as much as you can through this project and try to implement in in your production level applications as well so see you inside the uh section now uh let's go ahead and set up the project so I have my terminal open and I'm in my desktop folder like you can create the project in whatever folder you want I'm creating a on the desktop so first of all what I'll do is I will create a directory I will say mkd eCommerce and then I'll navigate into that directory and then we will initialize a note project so to initialize a note project project we have to say npm in it and we want to keep all the defaults so our note project is initialized now we will install some dependencies so obviously we need typescript so we'll say npm install typescript and it will be a development only dependency because obviously when the code will go into the production we have to compile that typescript into JavaScript to upload that on the production so we need typescript only for the development phase so we'll say save Dev so it will take some time to install so it's installed so next next we will say we we will initialize this project with the typescript so to initialize it we will say npx TSC it's a typescript compiler and we'll say in it so it will initialize the project and it will create some files so and that file is you can see that TS config.js so it holds all the configuration for the typescript so now in The Next Step what we will do is we will install the types for the node so we will say npm install types SL node and it will also be a development only dependency so it will give all the type safety for all the node apis like files process and operating system so all these things so that's why we need it and the JavaScript we don't need this so and let's install this so we have all these things installed now let's open this folder in the vs code I'll say open and inside the desktop we will say e-commerce okay so you can see that all the okay allow it yes so you can see all the files are there we have TS config.js we have package.json so here we have two development dependencies which is uh type SL node and typescript and now we will create a folder here so just go into the terminal and say mkd it will be a source directory where all our source code will go okay so inside the source directory here uh we will create a file which is index.ts so yeah so we have all the files now we need couple of things so first we need Express so we will install and payments install Express so let's do this and for the body parcel we will uh use the inbuilt middle V of Express only which which is Json now we'll say we have the express now we will install the types for Express as well so we will say in npm install head type SL Express save Dev but you you'll see that all the types are installed at the development depend so as I already told you uh the code will of the types script will be compiled to JavaScript before going to the production so we don't need these types in the production so let's install this as well and it's giving an error okay maybe I guess we don't need it because I remember in the latest version of Express they uh include the types automatically in that Express package itself so let's see like we will go through the core if we'll face any errors we'll try to resolve that together so so yeah basic folder structures are ready like basic project is ready now in the next uh video we will see how we can uh initialize the express and get our project running so see you in the next lecture now let's go ahead and create our first express route so we'll say import from Express and if you go over this you will see that uh it's asking to install the types like which we were trying to do earlier but uh there was a type over here in that package name so it's Express not exp so we will again do this and let's try to install this again okay so this time it's installed and you can see that the error is gone so now we will create an app so we will say conab is equal to Express and we'll say app dot get we'll say on the home route and we'll create a controller request comma response and we'll say response do send and working so and now we'll say app do listen and we will listen on Port 3,000 and we will say console.log App working okay so we have this basic Express app here now in order to run this we have to create a script here but like since it's not the JavaScript it's the typescript so we need an extra package to compile this to JavaScript and run that so in order to do this we have this uh amazing Library which is TS node so first we installed it npm install TS node and we will also install node one for like h r hot reloading and these will all be uh development only dependencies okay so it's installed now let's go onto the home directory and we will create a file and let's call this file as nodemon do Json so here we will store the node one configuration so it will be a Json file so first will be watch and inside the watch we will say you have to watch The Source folder so inside the source folder we have all our uh source code so source and second argument second like configuration will be extensions so inside the extension we'll give a comma separated value so we'll watch for GS extensions and do TS extensions as well so apart from this we will give the execute command and inside the execute command we'll say npx ts- node and we'll say do/ SRC and next. TS so this is the node one file now in the package. G we will write a test script for this so we'll say start and inside the start we'll say npx non one now let's try to run this we'll say npm start and let's see if it throws any error okay so you can see that app is working now if you go to the route Local Host 3,000 you can see that it's working so uh our Express setup is working fine now in the next lecture we'll create some more directories and we'll see how we can proceed from there now as of now we haven't utilized the type typescript power so what we'll try to do is we will try to assign the types for these variables which is app request and response so using that types of Express package like types / Express package we can low import some of the types so we first import Express and then will be request and response so this app will be of type Express this request will be of type request and the response will be of type response and if you go over it you will see that these are all the interface types so that's the beauty of typescript now you can you will get all the auto completes here so app dot post and everything put so you can see and you'll say rest dot Json so all the autoc completes are available and it will explicit implicitly check the types for you so if you pass any wrong type there so it will throw the exception in the compile time only so yeah so now let's go ahead and create some of the folders here so first folder will be middle wees here we will store all the Au middle Wares and Ro related middlewares here and then we will say no not file we will create a folder and the folder will be exceptions here we will store all the exceptions in the root yeah so in the root we will create a folder as controllers so yeah so as of now you have seen that in the last lectures as well we have written the controller here only but now since like we are structuring the project so we'll separate the controller into the separate folder and its respected files so yeah and apart from controllers what we need is we need schema so here we will store all the validation schemas using yep which we have studed the previous section and uh the next thing which we need is uh we need routes yeah so these are all the folders that we need and you will see that uh I I did a mistake I have created all the folders in the root so we will move all the folders into the source directory so it will go inside the source and Route s schema also yep so now it's fine so inside the source we have all these folders now in the next uh lecture we will install Prisma and we'll initialize few of the models there so see you in the next lecture now let's go ahead and install Prisma so to install Prisma first we will quit this server now we will say npm install Prisma and we'll install Prisma client as well so after the after these two packages are installed we will initialize the Prisma so we will wait for until these packages are installed okay so now we will say npx Prisma hit so it will initialize the directory with the Prisma so if you go into the vs code you can see that we have this now Prisma file here we have es schema. Prisma and by default the provider is posted SQL but we will say MySQL and inside the EnV we have this file so let's quickly go to the SQ light sorry SQL a and create a database there say root we will say password connect okay no sorry Local Host as well now we will simply create a database so we'll say e-commerce so database is created now if we go back to this we will say root and we will say password and Local H 5432 schema is equal to public so yeah I guess that's what uh we have to do now in the next lecture we will create some tables like a user model and all these things and we'll try to migrate it using Prisma migrate in the last video we have initialized Prisma but in this database URL we have to make two more changes first of all we'll need to change this provider to mySQL and then we'll have to change the name of the database in our case it's e-commerce so now it's ready now in the schema. Prisma we will create our first model we will say model a user and in the user we will have I ID which will be of type in and it will be primary key and autoincrement when default Auto increment we will have name which will be of type string we will have email which will also be of type string and it will be unique we will have password which will be of type string and uh what else like what else can we keep in the user we'll have address but it will go into the different database table so as of now we'll keep it simple if you'll need anything else we'll uh anytime come here and can add those feelds but apart from this we need two more fields which is created at created at will be date time and its default value will be now so and apart from this we'll have updated that it will also be date time and it will be simply uh updated at and and we will map this model to the name of users now go into the terminal and we will say npx Prisma my G myr Dev and we'll say name as create users table let's see if it's uh if it runs or not okay can't reach the database server Local Host 5432 okay I guess there is some mistake so let me check the connection again I'll close this I think we'll say Local Host I guess it was working fine initially password is pass password connect yeah so root and password let me see if I have made any typo in the password root password okay so yeah the port is wrong 3306 now I guess it should work let's see yeah now it's in sync uh let's reload the database and first choose the database we have e-commerce and you can see that we have this users stable so fine now in the next lecture what we'll do is we will try to create separate routes so earlier like in the course previous course section we used to define all the routes in the index.ts but now since you have already seen we have this routes folder so we will split the routes based on different modules so we will have separate route for Route file for users separate route file for products cart and orders so we'll see how to do that so in the next lecture we'll set up that and then we'll proceed to creating a login API so see you in the next lecture now uh before moving forward in this video we will try to set up the envirment variables so to set up the environment like as of now we are using the hardcode values of these ports and in the future when we will be using JWT we have to store the secrets or if we are using some third party Services we have to store the API keys so we cannot hard code them in the code because when we will push this code to GitHub those Secrets will be exposed which is not a good thing so we have to create EnV file and put all the secrets on there so as of now we already have the CMV file but this is for Prisma so we are going to like reuse this file to be used in the nodejs as well so in order to use this setup what we have to do is first we will create first We'll add this like in the git ignore this file is already added you can see that dot here because we don't want this file to be pushed to the GitHub because as I already told if you'll push it to the GitHub the secrets will be exposed which we don't want now to do deal with this like to deal with the EnV file in the nodejs we'll be using this package which isv it's a very good package you can see that it is a huge number of downloads as well so we'll be using that so let's first install this package we will say npm install EnV so so it's installed now in the source we will create a file which will be secrets. TS because here we'll be storing all the secrets now we will initialize this EnV so first we'll import it import EnV from EnV now you can see that it's not asking me to uh install the types explicitly because this package like the types are inbuilt into this package so we don't have to install it separately L now to initialize this we have to say EnV do config and here we have to uh provide the path of the EnV file we'll say path and it's uh EnV it's a root path so we can just directly specify the file name now we can export the constant so first we'll try to export port and Port will be process dot EnV do Port now what this EnV file does is uh it export all the variables defined here and made make them available inside the process EnV file so we'll say Port is equal to 3,000 so we'll export const now it should work okay now in the index.ts file uh instead of using this hardcoded port we will say port and it will be automatically imported from this Secrets now uh let's try to run this run the server and see if everything is working or not npm start and you can see that it's uh running and let's go to the we will say Local Host 3,000 and you can see that it's working so that's how andv variables are set up now uh for the other people who are like collaborating in this U project what we have to do is since uh we have put this CB file in the G ignore so how do those people know like what are variables they have to Define in the enem file so to overcome that we have to Define this do EnV do example and we will push this file to the GitHub so that they have a a template of what all the EnV variables they have to Define in order to run the project locally so we'll say Port is equal to some Port we don't specify the actual Port here or maybe actual Secrets here because obviously we will not so we just provide a Dy value there and the people who are cloning this project they can specify the values accordingly so that's how it works so in the next lecture we will Define the routes now now uh let's go ahead and Define the routes so first we will Define all the Au routes which are like login and sign up so in the routes folder we will create separate route file for all the routes so we'll say Au do TS and inside this we will first import something from Express Xpress and this something is router class now router class enables us to split the routes across multiple files and use them so we will say const a routes is equal to we'll create the object of this class router and then we'll say a now routs do get or maybe let's first Define the type router and then I guess we will get the auto complete yeah do get and we will say login and here we will provide the uh controller so inside the controller let's create a Dy controller air as well so we will say .ts and inside this we will export a function which will be export const login it will be a controller function so we will provide an arrow function here and it will take two arguments which will be request response and then we will say response do send login works now we have to provide the types here as well so we will say import from Express and we will import request and response so we'll say request of type request and response of type response so we have this file here this login controller here now in the routes we will pass this controller as and log in so it will automatically import from here now in the routes file like in the future Pro like in the future we will create all other files for like products orders and all these things so we have to combine all these files into single so first we will create an index file here which will be index.ts now in this index file we will combine all the routes so again we will do the same thing import router from Express and we'll say const root router so it will be a root router and then we will say a root router of type router and now we can say root router. use and for the Au for all the Au routes we are going to use Au routers so we have to export this as well so we'll say export default Au routes so in the index.ts we will say outout so it will automatically import from do/ and similarly here as well we will say export default root router and now since everything here is configured now we will go to the index.ts file now in place of this we will say app. use sorry app. use we want to use that root router on API prefix like you can give the root prefix as well you if you don't want to use any prefix but I like to call my apis with this API prefix so I will say that and I will say root router so that's all we have to do to configure the outers let's see if it's working or not uh the server is still running and if we go to slash login okay it's saying okay so it's not login it's au/ login okay it's still saying o/ login not found so let's see what the show is we have missed the API as well so we will say slash API / login now you can see that login works so the path is as follows first the API and then it will go to the root router then it will find the Au routes inside this/ routes module and if you go into the Au routes you will see that we have this login route defined as a get route so this is how the code splitting is done inside the routers we will Define all the routes here for the ODS like login sign up and then we will create a separate file for products orders and cards and then we will will Marge all those files into index.ts file so this is how it's being done so now in the next lecture we'll Define the login route we'll finish the login route we'll see how Json web tokens work how to uh encrypt or decrypt the passwords so see you in the next lecture now in this lecture we will be finishing up all the Au routes that is login and sign up but before we proceed to that we have to initialize the Prisma client so we have imported this Prisma client from at Prisma client now we will say const Prisma client is equal to new Prisma client and if that's it like if you want to provide the log levels as well you can say that log query so we want all the logs for the database queries since we will be needing this Prisma client in the controller file as well to perform all the queries we will say we will have to export it so we'll say export const Prisma client now let's move to the O controllers so in order to implement login and sign up we will be needing two packages one is this bcrypt and one is Json web token so bcrypt is used to like store the hash of the password in the database so that the original password doesn't get exposed and Json web token is used to issue the jwt's for the front end or the mobile app so that they can authenticate the users in the further requests so let's do this so if you go to the terminal like I have already installed these two so if you go to the terminal and type npm install bcrypt and jsonp token it will install all the dependencies for you so let's go ahead and use it so first we'll Define the route for sign up so in the sign up we will be receiving all the data in the body so first we will destructure that so we will be getting email password and name so in the next lecture we will see how we can Define the schema and first validate it before like the flow reaches to the controller so we will see that in the next lecture and now what we have to do is we have to first create the user first like we have to check whether the user already exist or not so we will say let user user is equal to await Prisma client do user do find first where Emil colon email or you can just give the short hand of this as well and we have to make this as async so if user is there what we have to say is through we have to throw the error that user already exists and if user does not exist then we have to proceed further so if user does not exist we have to create the user so user is equal to AIT prismat client. user. create then inside the create we will pass the data and in the data we will say name email and for the password we will say we have to import something from the bcrypt so import we have to import something from bcrypt and that something is Hash sync and you can see that it's giving an error so it means we have to initial ize the type file as well so just copy this go to the terminal add install the types and once the types are installed you can see that if we retype this uh it will give the autoc complete so we will say password hash sync we will say sorry password and we will say the salt round will be 10 so it will rate 10 times to generate a salt here so it will generate the hash for this password and the user is created now we will say response. Json and we will pass user so I guess that's it for the signup Let's test this now in the Au routes we will say post and we will import sign up and we will say sign up so I guess that's all now let's run the server and PM start okay now let's test this in the postman so we will creating we'll be creating the postman collection for all the routes that we'll be defining so the collection name will be e-commerce and inside this collection we will create our first directory which is what so like this is how the things and the production are done like they are structured pretty nicely now in the O folder we will add a request and we will say it is a sign up request and it will say HTTP colon sl/ Local Host it's not https it it says TTP let's use this API slash sign up it's a post request and the body we will say raw type will be Json and we'll say name test and email will be let's say test at theate gmail.com and password will be let's say bc1 2 3 now let's hit send okay it crashed let's see the reason for the crash email is undefined in the request body okay so before like using this what we have to do is first we have to configure the middleware as well so app.use and we will say express. Json so remember like earlier we have used body passer to pass all the Json requests but since Express has this in built middle there which is Json so we will be using that now let's see if it's working or not okay now you can see that it's working and if you you will notice the password it's like encrypted or hashed so that's how it works so if like someone gets the hold of our database so let's go into the database first connect this go to the database and in the users if someone like gets the hold of the database they will not be able to figure out the password because it's in the hash form so that's the reason why we were using bcrypt as a hashing Library so that's it for the sign up in the next lecture we'll see how we can log in the log log in a user sorry my bad log in the user and generate the Json web token so see you the next lecture now let's go ahead and finish the login route so we will say I guess let's copy this and change the name here to login and we will not be receiving the name here so just email and password this will be same but here we will say if not user if user is not found then we have to say user does not exist so we have to throw this error as user does not exist and this will also change now first we will have to compare the passwords like whether the passwords match or not so in order to do that we have to import something from bcrypt again so instead of hash sync we will say compare sync now hash sync is used to encrypt the password and compare sync is used to compare both the password the original password as well as the hashed one so let's do this so first we will say if not compare sync now here first we will provide the original password so the password which we will be receiving from the request body so we'll say password and second argument will be the hashed one so user dot password because in the database we stored the hashed one so it will compare both the password whether this hashed password when it will be decrypted whether it's same as password or not so and if it's not same that's why like we have added not here then again we will throw them throw an error which will be incorrect password so all the checks are done now if everything is good we will say token we will then generate the token and to generate the token we will be importing the JWT Library so we will say import we'll be importing everything as JWT from Json web token now again we have to I guess install the types here so let's copy this and go to the terminal quit this and let's install the types for Json web token now you can see that uh the error will be gone so it's gone it will be token so in order to generate the token we have to say JWT do sign we have to sign a token with some payload and we can provide anything in the payload so generally like we used to provide the user ID so user ID like for which user this token belongs and we will say user dot ID and second argument will be the secret so we haven't defined the secret yet so we'll go into the EnV we will say JWT secret and you can give any secret here random secret which is hard to like decode so just give any random key here and in the secrets we will be needing this so we will say export const JWT Secret is equal to process dot NB env. JWT secret so same thing and here it will be Port now in the .ts we will just import this GWT secret here so I guess this is fine I'm not sure why it's giv an error JWT do sign okay seems like it's good okay so the error is like the second argument like the JS WT secret cannot be null so like the EnV file the EnV package that we are using to decode all these envirment variables they like pass it as either string or undefined so they place a check like this EnV variable may or may not be defined that's why it's a string or undefined so we just have to append this here so now it's saying a string because we are sure like this JW secret is defined and it cannot be undefined so and now if we'll go to the .ts sorry and the controller .ts now you can see that the error is gone so this JWT secret is used to again like decode the token in the Middle where where we will be decoding the token which will come from the front end now we will say response we have already this so we will say user comma token so I guess that's it uh now what we have to do is we have to define the route so we will say auth routes. post login so the route is defined now let's go to the postman and test it we will duplicate this request and now we will change the name to login login and in the body now we have to Omit this name because we just need email and password head send it's giving an error let's see what's the error is okay so the server is not running that's why I guess it was giving an error now let's try again okay it failed again now it's running sorry I was in a hurry now you can see that it's working so it's giving the token as well now we will use this token as a header to authenticate the further request to UNI identify every user we will see that when we will be defining the middle beers so that's how login works and you can see that there is an issue here we are getting the password so we can we have to like obviously we don't have to send this password to the front end so we will see how we can exclude this password from the response so that's it from this video see you in the next lecture now in this video we will learn about error handling so as you can see that as of now in case of any error we are just simply throwing error object so this is not the best way of dealing with the errors so you will notice that we have created a separate folder exceptions here so we are going to work in this folder now so first of all we will create a root exception class I'll explain you what that is in a minute we'll say root. TS now uh if as far as exceptions are concerned what you want to send so first we want to send is the message so error message and then we want to send is the status code so it is the HTTP status code which is 44 and 401 and so on and apart from that we want to send the error codes as well now error codes are for front end to uniquely identify any exceptions so for example there is a localization on front end so obviously we cannot send the message error message in every language so the front end determines the error message using the error codes so that's why error codes are important so these are the things which you want to send through the error code exceptions and one more thing is the error like the actual error which occurs like the validation error or something so the default error class of JavaScript does not provide these things out of the box so we need to overwrite that class so for that we will say class we will create our own class which is HTTP exceptions and it will extend the exception class sorry the error class of the JavaScript and now in this uh we will Define all these things so first is the message message will be of type string and then we have error code now I will uh as of now we will give it a type of any like we will Define the error codes inside imem so we will do it in a minute and apart from error code what we know what else do we need is a status code it will be of type number and apart from a status code we need errors it will be of type bny because they can either be an object or the array so all these things now we will Define The Constructor to initialize all these things so we will get message of type string we will get sorry we will get error code of type any we will get a status code of type number and we will get error of type any so we will say this do message is equal to sorry message we will initialize everything so eror code is equal to error code here it will be this now we have status code is equal to status code and now finally we have errors is equal to errors so we have these things defined now what we want to do is we want to call the super method as well so the Constructor of this error class only takes the message so we will say message yeah so why is it giving an error okay super must be called before this so yeah now it's fine so we have defined this HTTP exception class now we will Define the enum as well so it's an enum of error codes and here we will Define few enums so first one will be user not found and let's give the error code of one1 like it's up to you you can give any error codes and these error codes will be shared to front end as well so that they can match match and get the exact error from that sorry error code is user not found and then we have user already exist we can give it as one2 and then we have incorrect password we can give it as 13 so as of now like let's work with all these three if like in the future we will need more error codes so we can come here and Define it at any time now since the root exception is defined now we want to create the class for each and every exception so in the exceptions first uh what we want to do is we want to create the class for bad request so we will say bad request do TS and in this we will say export class bad requests and this best request exception we'll say and this will extend our HTTP exception I guess we have not exported that now we say HTTP exception so this is all it is so in the Constructor we will say it will get the message of type string and it will give there get the error code as well of type error code so I guess I haven't exported that as well but I have it's the error codes not okay so I guess it should work I'm not sure why it's not working yeah so error code and apart from this yeah these two things are just required and we will call the super Constructor as well and inside the super first we will say message first argument is the message then we have error code I guess yeah and then we have status so for the bad request uh we have the status of 4ed so it's the predefined status for HTTP bad request exceptions and it's just still giving an error and in the so in the errors we'll simply provide null now in the HTTP exception I guess we have to change the type as well of this errors as error code and here as well error code now it's the bad request now in the controllers or controllers where we are sending this through error user already exists so it's kind of a bad request or let's see how we can do this first we'll give it a try then we'll change it based on the naming convention so we will say Throw we will pass new and we'll say bad request exception and in the message we will say user not found and the error code will be error code dot user sorry user already exist so user already exist now in order like the express pick this exception we have to define the error middleware as well so in the error in the middleware we will create a file which is errors. TS and here we will export a middleware export error middle beare and this error middle Vare will be a function which will take now the error middle we there is a special convention for express the first argument needs to be the error but in like the general meddle wees we have request response and next function but here we have the error argument as the first uh error as a first argument so we will say it is of type HTTP exception which we just created and uh we have request which will be to of type request then we will have response of type response and then we will have next function yeah so that's how it's being done now inside this they will return something and we will say sorry it's an arrow function and now I guess it should work okay it's the constant okay now it's fine so we will say response do status and response. status will be the error dot status code and do Json and inside the Jon we will say message will be error do message error code will be of type error. error code and actual errors will be errors so I guess that's all we need to Define in the middleware now in order for Express to use this middleware we will go into the index dots and we will say app do use we'll say error middleware so that's all what we need to do now whenever uh any controller will throw any exception this error middleware will automatically be called by the express so that's how it works now let's give it a try uh in the postman we will try to create a user with the same email now let's see it's giving an error okay now in order to make this work we have to do one more thing here so in the controllers we need to add this next function as well which is like used to handle the errors and for the middle Wares to pass the control to the next controllers and so on so we will install this so we will like not install basically import this so and now what we'll do is we will call the next function with this error object so whenever the next function is like called without this error object the control is passed to the next controller if there is any because you remember like how Express works is in the routes we can give as many controllers as we want and the these controllers are called as middle Wares so that's how it works so whenever we call the next function without the error the control is passed to the next middle Weare or the controller but whenever the next function is called with the error object the control is directly passed to the error middleware and how Express knows about it because in the index like we have given this middleware here so we have asked Express to use this middleware which is the error middleware and whenever the next function will be called with the error object this middle bear will be called so now let's give it a try and see if it's working or not so let's see we'll say hit send now you can see that it's working fine we have the message as user already exist error code AS one2 and error we don't have any as such errors here and the status code is 400 bad request now for your assignment what you want to do is create uh another exception with this uh user does not exist as well as incorrect password and let me know in the discussion section and in the next lecture I will give you the solution and also in the next lecture we will give a better way of handling these things because obviously we cannot import next function in each and every controller and do this manually again and again so we will find a better way of handling the errors so see you in the next lecture hey there everyone now uh before moving forward and uh looking into how generic error handling Works uh here we are going to see how first of all a validation works so if you have followed my previous lectures uh we have used the Zod Library uh which is the not this one uh this one yeah so we have used Zod library to perform all the validations so we are going to use this to perform some input validations on signup route so let's open the terminal first and quit this npm install Zod so it will install Zod and I guess Zod also like automatically ships the types for it as well the typescript types so in the schema I guess yeah uh we are going to create a file which is users. TS we are going to store all the schemas related to user like update user create user and all these things here only so we will say first we'll import the Zord so import so we will import Zed and now we will create a SCH schema so const sign up schema is equal to Z doob and inside the object we'll pass a object with all the uh Keys which you want to take as a input so let's first go to the postman and see what all we want we want name email and password so uh we will say name name will be z. string and that string will be notable sorry not notable is by default so if you want to make it nailable you just have to sayable song by default it's not nailable and email also we'll say Z do I guess this ship with email validator I guess I'm not sure I'll have to look into it yeah so we'll say Z do string and we will say do Gmail and for password we will say Z do string and Dot and we want like minimum length six maybe so yeah so this is how uh you define the schema and now to in order to validate the request what we have to do is we have to go to the index.ts and we have to extend the Prisma client so uh I guess the place where we have defined the Prisma client here here we will say do extend and in the extends we will pass an object which will say query we want to extend the query on users and what you want to extend is create so we want to like perform certain operations on create so first will be ARS ARS is the like request body which you will receive and then we have query and then we will say ARS do data is equal to uh then we have to like import the schema as well so I am not sure whether I have exported it so we will say export and let's like name it in all caps uh sign up schema so yeah so index.ts we will say sign up schema. pars and we'll say ar. data and now we will say return query we will perform the query with all the arguments so this is how you perform the validation and extend the Prisma client like we have already discussed this in the validation section now in order to handle this error we have to go to TS and we have to wrap this sign up into try and catch so we will say try and catch in catch we will receive an error so let's first move this code inside the try block and inside the catch we will say what you want to do is we want to first uh first we want to like create a class separate class for all the validation errors so and the exceptions we want to create a file and that file will be validation. TS and in the validation. TS we'll say export class unpr procl entity so it is like the official name for all the validation errors and it will extends HTTP error HTTP exception yeah so this is the class that we created in the previous lectures and then we will say Constructor and in the Constructor we will receive error which will be of type any and then we will receive message and then we will call the super Constructor and the super first we'll pass message error code and all these things so here we will like receive the error code as well of type string message will also be of type string and in the super so let's go to the HTTP exception and what all these things message error code status code and error okay so message and then it's error code so in the error code we'll simply pass error code and then it's a status code so for all the like unpressable entity we have 4 to to assign status code and then we will pass errors so yeah this is how it works and I guess error code will be number okay so now in Back to the controllers in the O we will say uh throw so we'll say first next and then the next we will see new unprocessable entity and in the unprocessable entity first we will pass errors so errors will be er. cause do issues that's how like we get all the errors from the Zord Library and these all will be nullable so yeah and then after this we will say message so we'll say unprocessable entity and then what we are what we are going to do is then we have to pass I guess the error code so in order to pass the error code first we have to define the error code as well so in the error code we will say and maybe we can say that 21 it's like completely random you can assign whatever you want and back into .ts we will say error code dot unprocessable entity so I guess this is what cause dot does not exist on type eror so error will be of type any I guess yeah this will fix the issue now let's see if it's working or not hopefully it will work so go to the postman and first of all we need to run the server so and go here npm inst start okay there are no compilation errors as of now so first we will like uh remove the name and see if it's working or not it's saying user already EX exists okay let's try to remove the email as well okay seems like there is an issue okay so the issue is so if you look look into the controller so first we are doing is find first so as soon as like this line is encountered it automatically throws an exception like the user already exists so what uh we want to do is in order to like throw all the validation error prior we have to validate it before everything else because if you will see in the Prisma dot like where we initialize the Prisma index.ts the validation is like only taking place when we when we try to create a user so whenever a create method is called on the user then only the validation kicks in so in the controllers the create function is after this line so before like after this error is encountered then we are calling this this create and that's the main reason why we are getting this error so in order to tackle this what you want to do is we want to like perform all the validation checks before anything else so most probably here or somewhere else so let's try to do this so first we do is what we'll do is we will remove this from here so we don't want to do it on create now go to the od. controllers and what we will say is we will say sign up schema. pass and what you want to pass is request dot body so like whenever the controller the code to the controller controller code is reached sorry this statement is executed first so it will perform the validation before anything else now here in order to get all the issues from the Zord Library we will not call this cause we can directly like call this er. issues so now let's try to see if it's working or not so we have removed email and password and hit send you can see that now it's working it says unprocessable entity and we have all these errors here so the name is undefined the email is undefined and all so let's try to give the name and email so email is this hit send now you can see that the error is only on the name and if we get name also you can see that user already exists and if I modify the email s test to one you can see the user is created successfully so uh this is how the validations are done now you can see a big downfall here what is that we have to like write these try and catch again and again in all the controllers and perform these Logics so we have to call the next again and again when we withow any exception so in order to like deal with this and like write the reusable code we will Define a error handle so we will look in the next lecture how that's defined because that's a very important part and you will learn some best practices there how the things are done in production so let's catch up there now uh let's go ahead and see how we can do the generic error handling so in order to like uh perform this first we will create a f and the source directory which we will say error handler. TS now inside this error Handler what we are are going to do is we are going to define a function we'll say export const error Handler and what this function will do this function will take a function as a parameter so we will say method so it will take a method as a parameter so it will be of type function so it's a inbuilt type we like the function is a inbuilt type and typescript so it will take a method as a function now what it will return is it will return a controller function it will return a controller function so now what this controller function will do so in order to make a function a controller what we have to do is we have to pass three arguments request first will be the request response and next it will be of type next function so now it's a controller so inside this controller we want to say try sorry uh right it's giving an error because it's not imported I guess yeah now here we will say try and catch now inside this try and catch we want to execute the method which we have taken as a parameter so we will execute that method and that method will also be a controller function so that method will be executed with all these parameters request response and next so you can see that whenever we will Define a controller we will pass that controller to the error Handler and in return error Handler is responsible for like executing that controller by wrapping it it inside a try and catch block and doing all the error handling out of the box so the benefit of this is we don't have to like WR try and catch again and again we don't have to call next Whenever there is an error so this is handled behind the scene with this control error Handler so you can call this error handle as a high level function as well now inside the catch we have to do couple of checks here so we will say if so first you will say if this error is an instance of HTTP exception and if you remember this HTTP exception is the class which we have defined ourselves so if that error is an object of this HTTP exception it means like it's a handled error we have explicitly thrown that error that's why it's an instance of HTTP exception so here we will create a variable let sorry let exception of Ty HTTP exception and we will assign this exception to error to exception so exception is equal to error now in case if it's not the instance of HTTP exception it means it's an UNH handle error or the runtime errit which we say because we haven't thrown it if we have thrown it explicitly it must P of type HTTP exception and if it's not the type of HTTP exception it means it's an un unhanded error that's why you have seen on certain websites there is a error message which says something went wrong or internal exception so these are the kind of error that are unhandled so in order to throw that first we have to Define one so in the exceptions we will create a file which will say internal exception dots and we'll say export class internal exception which extends HTTP exception and inside the Constructor message of type is string and then we will have errors of type any and then we'll have error code of type uh number now what we will do is we will say super and inside the super first we will pass message then we will pass error code and then the status code now the status code for internal exceptions so these exception is 500 and then we will pass the errors so this is how we Define internal exceptions and in the root we will Define the error code as well and we will say 31 and let's change it to keep it consistent so we will say 30001 and now inside the Handler what we say if error is not the type of HTTP exception we will say exception is equal to and in the exception for we will Define the object of that internal exception so will see new internal exception inside the message you will say something went wrong this is the classic error message which you generally see on some websites some sorry something went wrong and inside the errors we will say error and inside the code we will say error code dot internal exception and now once everything is done we will call the next next function with this exception so this is how the error handling is done so you don't have to write try and catch this next again and again so this all will be handled behind the scene by this higher hter function which you just Define now in order to like use this we have to go into the routes. TS file and where the place where we pass this sign up we have to wrap this sign up into the error aner sorry I guess okay so error hander we'll say sign up same goes with login as well error Handler login so let's uh summarize this so in the inside the error Handler we have passed this controller which is signup and inside this error Handler like it will return the function and that function will be a controller function because it takes three parameters request response in next function and this controller function is responsible for calling the original controller with try and catch and all the exception handling out of the box so if you go into the controller which is .ts uh here like uh we can like write simply this logic we can remove try and catch and we can simply use this so let's try to test it first so go to this and let's see okay there is an error I guess the server is not running so let's run the server first and by the way you will get all the source code on the GitHub so I'll give you the link that's what I was doing in the free every time I was pushing the code to the GitHub so let's see npm and start and see if there is any RS or no so let's hit send now it's still giving an error that's fine okay so the server was like not a app and running now it's working so you can see that uh there are handling this working fine and if I change this okay death seems like there is still an issue and the issue is if I guessed it properly it should be an Asing function I guess async and we have to avade this method called now I guess it should work and still cannot find name of it okay now let's see if it's working or not yeah it's working so it was a problem of facing and a wait so that's how it's it works like it is a very best practice to consider in the production you have you don't have to like repeatable code try and catch again and again so yeah I guess you learned something from this lecture now we will Mo move forward and see Define all other routes so the main focus of the next lectures will be first to define the role based Nexis like the middle we to control the based access and the admin can perform certain actions and user can perform certain actions so we already deal with that so let's see you in the next lecture in the previous lecture we have seen how we can create a generic error Handler now here are a couple of things first we can remove this next from here because we don't need it because we are doing it inside the error Handler function that we created in the in the previous lecture now inside the login as you can see that we are still throwing these uh generic error so we need to replace it with the custom errors so for user does not exist we will create a separate error which is 404 not found so go into the exceptions and create a file which is not found. TS and inside this we will just copy this code I guess and we will change the name to not found and the status code for this code will be 404 not found and I guess everything is fine and inside the root. TS error code so we have user not found already there so we don't need to create one so just go into the login controller and instead of throw error we will say Throw new not found exception and inside the message we will say user not found so and obviously we need error code as well so the error code will be error code dot uh user not found so this will do the trick and inside incorrect password so it will be bad request exception so new bad request exception the message will be incorrect password and I guess we have the code yeah so inside the code we will say error code dot incorrect password so this is all let's give it a try then inside the login uh let's hit send it's giving an error let's see if the development server is running or not it's running okay okay so it's working I guess the server was in the reload pH that's why it was giving an error and if we change the password let's say 1 2 3 4 and hit send you can see that it's giving an incorrect password error so that's how it's being done now in the next lecture uh we will see how o middleware Works in this lecture we are going to see how Au middle Weare works so the goal of this lecture is to create a me API so it will be slme and it will return the logged in user so the logged in user will be based on the o token that we will send in the headers of any request so remember the token that we have like used in the login so that or token we will be sending it in the headers of any request and from that or token we will be determining which user is logged in so for that uh we have to create a North middleware so I have created a dummy middleware here with a boiler plate code and and uh also one more thing I have created one exception here which is unauthorized exception so it has the status code of 41 so this error we will be throwing when there is when the user is not authorized and he's trying to access some resources or the routes which are uh authorization protected or maybe you can say login producted so that's how it will work so let's go into the .ts middleware and start working here so there are a couple of steps involved so first is extract the token from header and second if token is not present through an error of unauthorized third step will be if the token is present comma verify that token and extract the payload and fourth step will be to get the user from the payload fifth step will be to attach the user to the current request object so so first step will be extract the token from the headers so let's do this so the way we are going to do is const uh token is equal to we will say request do headers do authorization so we will be sending the token inside the authorization key in the headers so we will get the token if token is not present so the second step is if token is not present through an error of unauthorized so we will say if there is not any token so this uh will convert it into truthy or falsy value so if token is null or undefined it will be converted into false and this uh symbol would convert into true so if token is not present we will say next so we have to call next here because we are not wrapping this or middleware inside the error Handler so we will say next new unauthorized exception and the message will be unauthorized and the error code will be error code Dot unauthorized so if token is not present we have sent the unauthorized exception now third step is if token is present verify the token and extract the payload so first to verify the token we have to import Json web token Library so import everything as JWT from uh Json web token so we will say const payload is equal to JWT do verify and verify the first argument will be the token that we'll get from the header and the second argument will be the JWT secret which we have like set in the involment variables so we have the payload and uh this uh step can through an unwanted exception or the runtime exception so we have to wrap it inside the try catch and if there is any error this means the token is malformed or like not valid so we will again uh throw that an authorized exception error and now we will move all this code inside the tri block okay so we got the payload now we have to get the user from the payload so we will say const user is equal to and we will say await Prisma client do uh user. find First and in find first you will say where ID is equal to payload do user ID so remember inside the payload we have uh given this payload user ID so we are getting the user ID from that payload so it's giving an error because the payload is not defined so we will say it is of type user ID of type uh and the user will be user ID will be of type number so I guess it will work and this verify this verify doesn't give any sort of uh that what you can say the type so maybe you can say as any as of now and remove this type from here so the payload can be of type any and it will like get you rid of this error so we have this user now check if the user is there or not so if not user then we will be again sorry we will be again sending this exception throwing this exception which is unauthorized exception and if the user is present we have to attach that user to the current request so request. user is equal to user now you can see that it's giving an error because the express request object does not have any s such key user so we have to extend that request object to attach that request sorry user key so for that inside the source directory we will create another directory which will be types and here we will be store we will be storing our over overr and types so let's create an extra file here for Express express. d. TS and all the types are like we have to give the extension as D.S now we will say declare module Express and here it will be declare and here inside the express module there is an interface we will say export interface request and inside that request we have a user which will be of type user and this user will be important from Prisma client and one more thing we have to import the express as well here import Express not like this yeah so import Express from Express that's how like we Define the type over right so in the module Express there is an interface which is request and on that request interface we want to attach to an extra type which is the user type so now if you go into the middle we you can see that the error is gone okay so and after this we have to call the next because we want to pass the control to the next controller so this is how the O medle whereare is designed so if there will be any error uh we will come back and change here now the controllers we will Define a me controller here so we will say let's copy this and get let's get rid of this and we will say me and in request do response dojon we will simply say uh request dot user so in the O Middle where we have assigned that user to the request object so in the Mi API we can directly send the user from that request now let let's define the route here and here we are going to say Au routes. get it will be a m API and inside the M API the middleware will be off middleware and the Handler will be the controller will be inside the error Handler and me so that how it works so it's fine let's give it a try in the postman let's see if the server is working or not yeah server is working let's create a separate request and add request which will be me and the URL will be /me let's hit send and you can see that the messages unauthorized because we are not sending any uh headers so in the key we will say authorization and in the value we will be sending any token so first let's send any random token and you can see it's still giving an unauthorized error so let's go to the login and fetch one token from there so let's hit send it's an incorrect password so I suppose it was abc123 okay so we have this token here let's grab this token go to the mem and we have attached this token here now let's hit send okay now you can see that we have the current logged in user so it's working fine so that's how Au middleware works so let's recap this we have designed Earth medle Weare where we are first extracting the token from the headers inside this authorization key and if the token is not present we are simply throwing an exception of unauthorized now uh when we have the token we will verify it whether it's valid or not if the token is not valid we are again throwing that an authorized exception and after that once the token is verified we are extracting the user from the payload so in the when we are assigning the token we have given the user ID as a p load then we are extracting the user and if the user is also not present then then it means that the the request is unauthorized so we are again simply throwing that exception and if everything works fine we are simply assigning that user to the request and we are moving forward from here and inside the controller we we have simply created a me controller where we are simply throwing request. user so this is how o middleware works now in the next lecture we will see how we can create the role based middle Wares as well so for example if the user has had admin role then only he's allowed to access some resources so in the upcoming lectures you will see that now in this lecture and the upcoming lectures you will see how we can create role base access management so for that in the user model we will be having an extra property which is the role so for that we will first create an inum and we'll call that as role and here we will be having two role one will be admin and one will be user and here we will have role which will be of type role and by default uh every user will be have a user role so if you want to like assign some user admin we can directly go into the Prisma studio and change it from there so this is how it works now go to the terminal and create a migration so let's quit this and we'll say npx Prisma migrate Dev and we will give it a name of uh add roles to user okay so it's done now let's run the server again and go to the go to the new terminal and run Prisma Studio here npx Prisma studio and it's running on Local Host 55 uh we will say Chrome we will open the Chrome and inside the Chrome we will say Local Host coren 5555 so here is the Prisma Studio we have one model user and you can see that by default sorry yeah so by default everyone has a user rule so if you want to edit any of the user for example I want to edit the first user and uh just simply click here and just say admin save one change so now the user one has the role of admin now we will use this uh user to create the products because in our system we want only admins to create and update the products so in the next lecture first we will create the product model and then we will create a simple route which will be a post route which is used to create a product and on that route we will place that role based middleware so let's see you in the next lecture now let's move forward and see how we can create the role based access middleware so for that I have done few things so first I have created a product model so it's pretty basic so it has ID name description price and tags TS will be the comma separated values and we have two time fields which is created add and update ad and then we have named this table as products so the products table is created and in the controllers I have created a separate file which is products dots and inside here we have this create product uh controller which is pretty basic apart from that in the routes folder I have created a separate file for the products route so it's also the boiler plate code and inside index.ts I have used this route against / products path so this is all we have so now let's go to the products controller and try to create one so we will say const product is equal to A8 Prisma cl. product. create and inside the create we pass the data we will pass everything in the request body accept the tags because we are going to store the tags as a comma separated values so in the input we will receive the tags as uh an array so for example we will receive let's say t and it's uh let's say from India so we want to transform it something like this T comma and yeah so so for this we are going to say request. body do tags. join and we are going to join it using comma so this is how we are going to do this and here is a quick assignment for you guys you have to create a validator to create a validator for this request so just create a validator you have to validate all the data which is coming inside request. body and you have to throw the exceptions I guess you don't need to throw the exceptions it's automatically done by error error Handler so just create a validator and use it here let me know the solution in the discussion section so and apart from this we will say response do Json and simply we will say product so it's completed now in the routes folder we will use this products uh routes do post and for the simple slash route we are going to use the error Handler for create product so this is what we are going to do now let's give it a try as of now this route is not role protected or any sort of permissions given on this route so any user can create a product so let's give it a try first so in the user earlier like I have given this rule to user one as admin now I'm going to change this and we will simply say user here now let's go to the postman and create a simple folder new folder for all the product related routes we will say products and here we are going to create a request which will be add product so you have to learn all these things because these things are done in the companies where you have to structure these requests or the documentations so it's obviously a about practice to do this so on API we have products and we have to create a post request and inside the body we will pass the Jon so let's give it a name I will say t inside the description you will say that a sweet T just the random one and for the tags we are going to say it's a t from India and for the price we are going to say it's 20 and and do we need anything else as well let we check name description price tags so that's all what we need I guess so let's hit send okay so it's giving an error what the error is because we are not running the development server so we will say npm start okay now let's give it a try again hits working so there are two things which we need to take care of first this uh route is not either authentication protected not ro ro based protected so first we want to give a off middle wear here so inside the routes inside the products we will say first we will say o middleware and as soon as we say o middleware and try to run this again so let it hot reload and if we send this request again you can see that it's failed because in the headers we are not sending any authorization header so we will say authorization let's copy the token from the Mi API copy this and here so now let's hit send so you can see that again the request was successful because now we have the authorization token here so it's the request is authenticated now what we want to do is we want to create a uh Ro middle we so in the Middle where what we want to do is we want to create a file which will say admin dots so the uh this middle we belongs to the admin all the admin users are only allowed to authenticate this request so let's copy the boiler plate from here and use this let's remove everything from here we will say admin we will say admin middleware and inside this middleware what we are going to see is first we will get the user and which will be request. user the order of these middle wees are important so before this admin middleware we have to give the O middleware so that we can get an access to the user object on this request so once we we have this request so we will say if user. rule equal equal admin then we are going to say next else if it's not an admin then we are going to say next or maybe we can simply copy the exception from here we are going to say it's unauthorized so we have to import this as well so we are going to say let's try to type this I guess yeah it will automatically import this so yeah so this is howal admin is defined so we have the request user sorry and if the role of the user is admin we want to pass the uh control to the x controller and if it's not an admin then we are going to say it's unauthorized so let's give it a try so inside the products. TF after the O middleware we are going to pass admin middleware so now let's see I let it reload okay the app is crashed I am not sure why it says the port is already in used let's run this again okay so app is working now let's hit send you can see that it's an unauthorized now even though we are like passing the authorization token it says unauthorized because the user is not of type admin so let's go into the Prisma studio and try to modify it to admin now let's see the request now you can see that it succeeded so now this route the create product route is protected with the admin middleware or the admin only admins can access this route so this is how the RO based middleware works now in the next lectures we will proceeded forward and create other routes for the products like get products like the listing of the products and get product by IDs and updating everything so let's see in the next picture hey there everyone now let's go ahead and finish all the product related routes so what I have done is I have created four controllers here just to save a little bit of time so when is the update delete list and get product by ID controller so it will update the product it will delete the product it will like list all the products in a paginated way and and it will list a single product based on the ID and I have used these controller in the routes as well so put route for ID as a param will update it same for the delete get route on slash like the root route will list all the products in a paginated way and similarly if the ID is passed to the param we will list that specific product one more thing I have changed is earlier in the the description was of type simple string so in the MySQL it restrict us to use certain number of characters in the database so in order to make it uh like unlimited characters we have to use this at db. text so it makes this column as a text type in MySQL uh it is only required in MySQL so if you are using postgress and all you don't need to give this oper operator yeah simple string will be treated as text so it is only required for MySQL now let's go ahead and finish all the controllers here so for the update we need to First wrap it inside TR right catch because we need to explicitly catch the error If the product does not exist so in the catch uh we can simply say Throw new uh not found exception and in the message we will say product not found and in the error code we will say error code dot product not found now in the try first we will say const product is equal to request dot body and we have to change couple of things here so if tags are given in the product we need to make it as comma separated values so we need to explicitly put a check here if tags are there we need to change it other I just proceed so if product do tags then we have to to say same things uh sorry product do tag is equal to we will say product. tags. join and we want to join it with comma so this is done now we can simply update the product so we we can say const updated product is equal to await sorry Prisma client do product. update and update takes two arguments so one is the we Clause so in the we we will say ID request. params do ID and by default all the parameters out of type is string so we need to explicitly type cast to number because ID is of type number in our database and the second argument we give is of type data so data will be product and we will simply say response do Json and the Json response we can say updated product so this is all what we need now let's go ahead and give it a try so in the postman I can duplicate this request and I can change the name to update product so uh let's try to First refresh this I have created like 20 products here so that we can test out the things so let's try to change the price of this product which is ID 46 so let's say 46 and in the body we can say price so price let's suppose 100 yeah so let's hit send it says cannot post okay so obviously it's not a post request it's a put request so let's hit send now I forgot slash here okay so now you can see that it's working so if I try to update a product uh which does not exist for example 12 it throws an exception which says product not found so update is working so the homework for you guys is to uh implement this delete product it's for assignment it's same as the update product you just don't need to do all these things here you just need to call a delete and pass the wear argument and inside the catch you have to Simply throw this exception now let's let's uh do this for the list product so for the list product we need to have a pagination here so the response which we want to send is which uh we want to send the total count of the object as well so for example count 100 and then we want to send the data as an array so this is the response structure which you want to send so we need to perform two queries here so first to get the count so we will say const count is equal to await Prisma client do product dot count so it will give all the counts now the count is necessary because we need to provide front end some data so that they can write the logic of pagination on the front end so that's why we send the count and once we have the count we can get the product as well products is equal to a weight Prisma client. product. find manyu and inside the find manyu we will pass two arguments one is a Skip and this skip will will be in the request dot query do Skip and if a skip is not there then we will pass simply zero and apart from skip we can pass take so we want to like restrict the page amount so we don't want to give front end that control so back end is responsible for sending that so we will hardcore the value to five so if SK skip is not there we are telling like just return the first page p and if a skip is present then just do as it is uh it's giving an error okay so we need to type cost this to integer as well now it's fine now in the response we will say response do Json count and inside data we will say products so this should work let's give it a try go on to the postman just save this request and duplicate this and we will say list products it will be get and just remove this params let's try to hit send and you can see that count is 20 and since the value of es skip is not given we are sending the first five results so now if we give es skip Escape is equal to Let's ES skipe five and hit send now you can see that the ID is from 51 so list is working fine so let's save this request now the last one is uh get product by ID so it is very simple and straightforward what you have to do is we have to obviously wrap it inside TR catch because the product may or may not exist now inside the error we will simply just C copy this and throw this exception and we will say const product is equal to a wait Prisma cent. product do find first or through and inside find first or through we will pass where ID is equal to request. params do ID and just pass this as a response so this is pretty straightforward now let's give it a try as well and just duplicate this and change the name to get product by ID and here let's get the ID of one and you can see that product not found let's say I want to get the product with id50 it still says the product not found but the product is there I am not sure what's the error is it says request. params do ID okay makes sense let's try to print the error it says the app is crashing address already in use so I'm not sure if node Monon is creating some issue so we will say npm is start again App working let's try to find this again okay now it's working so I guess it was an issue of node one that's why it was not working so you can see that all of these things are working all of the four routes um delete product is for assignment so let me know in the discussion section so in the next lecture we will finish up some user related routes as well so we will create a separate model to store the address of the user and then we will assign some Building address and Shi address to the user so let's see you in the next lecture one more thing if you have noticed here is that we are not handling the validation errors so if I like show you in the postman just go to the sign up and try to remove this password and hit send so even if there is a validation error it's still saying something went wrong because when we are like saying uh sign up schema. pars we are not handling that anywhere whether this succeeded or failed so what we can do is in the error handlers so we are checking for the HTTP exceptions here so if the error is of type HTTP exceptions we don't need to do anything but if it's not of type HTTP exception there is a chance that it's a validation error so we have to place another check here so we can say that if error instance of Zod error so Zod error is a type which is exported by this Library Zord which we are using to perform all the Val validations so here we can say that exception is equal to new uh bad request exception and we can say that unprocessable entity and in the error code we can say that error code dot unprocessable entities and we can pass the error and inside the else Clause now we can move this statement up now it should work now if you go to the post man at give a try you can see that it's now giving an unprocessable entity exception so name is the Zord error and you can see that the password is required so that was a bit of a change which we need to do in order to handle this uh exceptions regarding the validations now uh let's go ahead and create the address model for the user so we'll say model address we will copy some things from here let's copy this all and paste it uh we will remove all these things and in the maps we'll say addresses so it will be the addresses table and in the address we will have line one it will be of type string line two it will also be of type string and it can be optional like uh it's not mandatory to have this so for optional we can place this here and apart from this we can have city of type string and Country of type string and apart from that we can have pin code as well of type string string so this is all what we need for the address and we need to link these two models so address must contain a user so for that we will have a user ID and user ID will be of type in and then we'll have a user and user will be of type user this is how like we establish one to many relations so our user can have multiple addresses and we'll say add relation and inside add relation we'll say Fields user ID and it references ID so this is how you establish the relation and for the reverse relation we will have addresses here and it will be of type address array so the relation established so when user can have multiple address and every address must be linked to a user so user ID is given here and it references the ID field of this user table so it is like pretty obvious if you have followed the course till now so I am sure you must be aware about this so let's quit this and we will say npx Prisma migrate Dev and we'll give it a name of add addresses table so it's created now what we want to do is uh in the ODS where we are sending the current logged in user we want to send the address as well and then we will create like we can either send it here or we can create a separate route where we can list all the addresses of our user so we will go with that approach we'll create a separate route where we can list all the address of a given user and we will create a simple one more route to delete that address and one more to add the address so three routs in total so let's do that in the next lecture now let's go ahead and finish all the address related routes now I have done couple of things here before recording this lecture so I have created three controllers uh the boiler plate add address which is used to like add the address of a user delete address and the list address and apart from that what we have done is uh we have created a separate routes folder for the user routes file for the user where I have used all three controllers here so slash address SL address colon ID and then get route with the address so this is all in place now uh just let's first uh finish this controller which is the add address controller so for this first we need to create a schema so in the users. TS let's say export const address schema which is equal to Z doob so for the address what we need is uh we need line one it will be Z do string apart from this we need line two it will be also Z do string but uh it can also be nullable apart from this we need pin code it will be Z do string and it will be of length six so the PIN code here are of six length so I'm just keeping it as six apart from that we need country which will be simply z. string and I guess what we have we have city as well City and user ID okay so City will be allof type a string and then we have user ID of type number okay so we have address schema in place now what we want to do is first we will say address schema do pars request. body so it's passed now first we want to fetch the user so we want to wrap it inside TR catch because a user may or may not exist new not found exception and we will say user not found and the error code will be error code dot user not find okay so it will be full stop and inside try first we will say let's create a variable of user it will be of type user so we are using typescript so let's utilize the types as well so user will be await Prisma client do to user. find first or throw where ID is request do body do user ID so we have user in place now what we want to do is we want to say const address is equal to a wait Pres client do address do uh create and inside create we want to pass data which will be request. body and for user we will have user. ID and we'll simply say response dot Json and address not our add address simple address okay so it should work let's give it a try uh let's go to the postman and uh create a new folder here and we'll say it as users now duplicate this request and drag this request to the user so that we can have a template of the request and now change the name to add address and in the API we have to say it's users and address so it's a post API in the body we will say nothing and let's hit send you can see that the validation is working fine now what we want to do is we want to say line one so I live in C 6 671 line two will be let's say parking Road and City let's say Delhi country is India add in the PIN code let's say 1 2 3 4 now let's hit send okay so pin code is uh different and apart from that what we are saying uh user ID we need a user ID as well okay so let's say user ID one or maybe let's say 51 I guess the 51 user ID exists so we have this let's hit send so the PIN code validation is also working fine so it says user not found okay so at least we have surpassed the validation request. body. user ID it's fine I guess okay so 51 user obviously does not exist so let's try with one it is still says user does not exist so I just need to go to the users Tab and okay the ID is 89 and 10 so my bad so we will say it now it says uh Prisma validation error so it's an unhandled exception so let's see what's the issue is in the tab okay uh seems like there is some issue so okay so the issue was in the user we are assigning user. ID so it will be user ID so we need to assign user ID to this variable now let's see if it's working or not now it's working fine so add address is working fine but here is an issue for example uh we are taking a user ID as a request. body but this is not ideal obviously so what we want to do is we want to extract the user from the the O token itself so because if someone is authenticating and using our app he or she will only be responsible for creating its own address so there is no point of taking the user ID in the request. body we can simply use the O middleware and get the user from that or token so this change we will make in the next lecture so let's see you there so in this lecture we will see how we can use the or token and get the user from there instead of taking the user ID in the body so we need to make couple of changes here so first in the schema we have to remove this and then in the users uh we can remove this as well we don't need this now in the routes since like we have used this o middleware obviously we will not be using any admin middleware here so it's wrong so let's remove this so since we are using o middleware we are like sure that we will get the user in the request do body so what he'll say that request dot body dot user. ID now let's give it a try and see if it's working or not so let's try to do this again so we will remove this user ID from here and see something went wrong okay so let's try to but that there is no error object as such okay makes sense so what we can do is instead of this okay so it's not request. body it's request. user. ID so it was my bad so let's hit send now now you can see that it's working so that was the issue it's not request. body. user it simply request. user so it's working fine now uh you can see how we can use the token to get the current logged in user we can remove all these unused Imports now let's go ahead and finish all these three routes these two routes sorry so for the delete we will wrap it inside try catch uh because address may or may not exist so we will say Throw new not found exception and we will say address not found and in the error code we need to add one so we will say for all user related things we are using one so we can say address not found and it should be one4 go into the users you'll say error code dot user sorry address not found so it's fine now and why is it giving an error I'm not sure okay so it was an import error and apart from this we will say await Prisma c. address do delete and inside delete we will say where ID is equal to request do params do ID and we have to type cost this toint and once it success you can say response. Json and we'll say success colon true you can simply send the status code it's not necess to send the body in every uh response so you simply you can say response. status 200 so that will also work fine and in the list address uh it's pretty straightforward we don't need to have pagination here because hardly any users add five or more address so that's why so we can simply say const addresses is equal to a wait Prisma do address do find many and inside find manyu we will say where user ID is request. user. ID and we'll say response. Json and we can say that addresses so this is how every route works so I guess you have an idea of how these things work now now in the next lecture in the user schema we will have two more fields to store the default shipping address and default billing address because in multiple e-commerce application you have seen that you have certain default addresses stored there so we will design that functionality and apart from that we will see how update user and all these things work so see you in the next lecture hey there everyone now in this video we will write the controller for updating a user so I have like return a boiler plate for the controller and its respective route as well so it is a put route on slash and we are using the update user controller with OD metalware now I have to do few things so first is to define the default shipping address and billing address in the user model so let's do that it will be of type in and it can be a label and same goes for default billing address as well although like we are not working on the payment Gateway but let's uh give you an idea of how things work so default shipping address and default billing address let's migrate these npx Prisma migrate Dev and name and default addresses so it's done let's run the server again npm start and now first we have to define the schema here so for the schema go to the users. TS and Define the update user schema Z do object and what we want to update is we can update name we will say Z do string and it can be nullable apart from that we want to update let's go ahead and see name and let's update these two things as well which is default shipping address and billing address so it will be Z do number it can also be Nel and same goes for this do relable so this is how the schema works now let's go ahead in the controller so in the users controller in the update user first we will verify this schema so we will say const validated data is equal to update user schema. pars and we will say request dot body now if we go into the schema let's make it all caps because let's keep it consistent so here we also say update user schema and in the Imports we have to say update user schema so it's fine now you can see that now I'm holding the result of this par in a separate variable earlier what we were doing is we were like simply uh using the request do body after the passing so if you over over this you can see that the type is automatically like inferred so this is the benefit of typ script now we have to do couple of things here we have to write couple of try catches so this try catch is for uh validating the shipping address so we will say first let's define couple of variable let address of type address and same for billing address now in the first try catch what we are going to say is uh shipping address is equal to Prisma cine do address do find first or through where ID is equal to validated data dot default shipping address I guess it should be ID here not just the default shipping address ID no no no we can like I have made a mistake it should be ID here because we are not storing the complete address here we are just storing the ID so okay let's use uh this only then I made a mistake there the IDE name should be default uh shipping address ID so let's see uh default shipping address and if shipping address is not found we want to throw an exception so let's copy this from here and we will say not found address not found everything is fine and this thing uh we only want to do is if validated data dot default shipping address so we will move this inside TR catch because we want to perform this operation only if user is TR to update the uh shipping address and same thing we have to do for billing address as well so we will say default billing address let's copy this default billing address and it will be billing address so it's fine let's close this first so we have validated these two things now let's update the user we'll say cons updated user is equal to a wait Prisma client do user. update and we will say where ID is equal to request do user. ID and in the data or we even say or we can directly pass the valat data here add in the response Dot Json we will pass the updated user so this is how uh update user controller will work there are a couple of things more we which we have to check so if the shipping address is found and if shipping address do user ID not equal to request. user. ID then we have to throw in a exception here new sorry bad user bad request exception and we have to say that address does not belong to user and in the error code uh we have to Define this error as well so in the root. TS uh we can say that and the users only address does not belong like you can give whatever name suits you the best I am just giving the simple name here and we will say error code dot address does not belong because uh user can attach the shipping address its own shipping address so we have to write this explicit check here and same in case of billing address as well so billing address do user ID is equal to is not equal to request. user. ID then we have to say address does not belong to user now let's go ahead and use test this controller first so just go to the postman let's first save these requests and we'll duplicate this request and we will say update user and inside the body what I want to say is I want to update the default shipping address and go to the Prisma studio and if you can see that in the address we have two address there with the user ID of 8 so I am logged in with uh user ID 8 so that's good so let's change the user ID of one of the address to see if the error is working fine or not so I want to attach uh the address to to the uh user 8 so let's see if it's working or not send cannot post so obviously it's support API okay uh you can see that invalid type name is required shipping default shipping address is required and default billing address is also required but I guess we have made all these things nullable here yep these are these are nullable so I am not sure what's the error is okay update user schema okay let's give these things first name empty but empty name will like override that so it's not a point of giving the empty name here I am not sure what the error is first uh let's see if it's actually calling this controller or not so we'll say console. log we'll say update user called and just open the terminal okay the app is crashing maybe that can be the reason so let's npm start again because it's creating the port problem sometimes so I'm not sure why that's happening okay so update user called so it means that update user schema is working fine okay so the issue was in the documentation they suggest using optional instead of nullable like I'm not sure why it's not working because in the previous versions I used to write this code so Nel was working but now they are saying to use the optional so let's use this like if you go into the documentation they are saying to use this optional here now let's see if it's working or not it's giving address not found so I guess the issue is in the controller this is throwing an error and it's coming inside this scratch block so we just need to remove this and place it here and same for billing address as well now I guess it should work fine let's see yeah now it's saying address does not belong to the user so if I change it to one you can see that now it's working fine so this is how update user works now in the next lectures we will see how to design the cart functionality now in this video we will Define the cart model so let's define that model we will say cart items and let's copy couple of things from here uh we don't need name description price and tags and for the table name we will say card items now uh every card item will have a user for which user that card item belongs we have a product so the product in that card and we need the quantity as well so we need three Fields so let's copy the user from here and use this for the product we will copy the same thing and replace user with product same goes here it will be of type product and relation will be on product ID and we need to define the reverse relation as well cart items and we need to do the same thing for users as well so in the users we'll say this so uh the model is defined we need one extra feied which is quantity so quantity will be of type int now let's go to the terminal and Define the migration we will say create card stable so I guess it should work fine yeah so the card table is created now in the next lecture we'll Define the controllers hey there everyone now in this video we will work on the card so what I have done is I have created a card controller here and defined four methods here one is to add items to the card one is for deletion one is to change the quantity and then want to list all the items of the card of a given user and apart from this I have created a routes file as well so post and get route on slash will add item and list items of the cart respectively and we have this params for the cart ID then to delete the item or the changing the quantity so let's first work on adding item to the card so for that we need the schema so go to the schema and create a file which is car. TS let's borrow some code from here let's copy this paste this here we need product ID and and we need quantity and this will be of type number this will also be of type number remove this email so this is uh create card schema now go back to the controller and use this so we'll say const validated data is equal to create card schema. passs and we will say request do body now we will fetch the product as well based on the product ID so we need try catch so in the catch we will say Throw uh it will be not sound error and the message will be product not found and the error code will be error code do product not found and in the try we will first create a variable here let product of type product and we will say product is equal to await Prisma client do product. find first or through add inside the we Clause we will say where ID is equal to validated data dot product ID so now we have the product so we will create the cart item const cart is equal to await Prisma client Dot cart item. create and sorry create we will pass the data and we have to pass a couple of things first is user ID so user ID will be request. user. ID then is the product ID product ID will be product. ID and then we have quantity quantity will be validated data do quantity and then we will say response dot Json and in response. Json we will say card so let's give it a try go to the postman and create a separate folder here we will name this folder as cart and in the cart let's first duplicate this move it to the card we will change the name to ion item and here we will say cards and inside the body we will say product ID 1 and we will say Quantity as let's suppose two so so let's it send and you can see that put is not working so it's post okay so it's still running I am not sure what the error is so let's see if it's working or not let's try to rerun this again the port is causing some issue so maybe that's the reason product not not found so let's grab a product ID 46 and it send and you can see that the cart is created so if you go into the cart item you can see that user 8 has 46 like card ID and the quantity is two so it's working fine now let's go ahead and work on a different controller here so go to the card and item to the cart is done now we have to delete item from the cart change quantity so let's work on the delete item first so first uh we have to say it's a straightforward like delete is pretty straightforward so we can say that await Prisma client do card item. delete where ID is equal to request dot params do ID and once it's done so let's type cost this to in we will say responsejson and we will say success to true so let's give it a try let's duplicate this request we will say delete item and it will be a delete request on cart id1 so let's hit send okay it's creating an issue let's see if it's working or not again like the port is causing an issue I am not sure if node modon is creating an issue or what so let's reload this you can see the success is true and if I reload this uh you can see that the cart is gone now here are a couple of assignments for you guys so first what you have to check is check if user is deleting its own card item so basically you have to check that if the card item. user. ID is not equal to the logged in user then you have to throw an error and in this controller what you have to check is If the product already exist in that cart we don't have to like add an additional product we have to Simply increase its quantity so we have to see check for the existence of the same product in users card and alter the quantity as required so let me know the solution of these two things in the discussion so and if you want I can make a separate video but these are pretty straightforward so I hope you can do it on your own so let's see you in the next lecture and there we will finish all these two routes now let's go ahead and work on these two routes so what is the change quantity and what is the get card so in the change quantity first we will fetch the card so we will say and change quantity like we will receive simply the quantity in the schema so if you want to idate that you can uh in the schema card. TS you have to define a separate schema and let's do it anyways export const change quantity is schema is equal to Z doob and here we will have this so now let's go back to the card we have to validate this as well const validated data is equal to change quantity schema. pars and we will say request dot body now the quantity is validated now we have to update the card so we'll say const updated card is equal to so we will say a wait Prisma client do cart item. update and inside the update we here we have to pass two arguments so one is the where so where ID is equal to request. params do ID so it will be of type number and apart from this we have to give data as well so in data quantity will be validated data do quantity now return the response response. Json we will say updated card so this is done uh here also you have to do the same thing so you have to check if the user is updating its own card item and in the gut card it's pretty straightforward so what we have to do is we have to create a variable const card is equal to a weit Prisma client Dot card item. find many and inside find many we it will be where so where user ID will be equal to request dot user. ID and we have to include two thing one thing basically so we want to fetch the products as well so we will say product colon true so this is how you include the relation now simply we will say response dot Json and cart so these two should work let's give it a try in Postman so let's duplicate this request first and here we will say change quantity so here you want to change the quantity of card two because if you go into the Prisma and reload this you can see that the ID is two and the quantity is two so we want to change the quantity to four so let's go ahead and do that we don't need the product ID we need to change the quantity to six let's suppose okay so okay so it was sorry a put request so in delete I guess it has deleted this card no issues we have to create one card item here so the cart is created the ID is three now let's try to do that I like by default it was delete so it deleted that card so card ID is three now now you can see that the quantity is six so if I refresh here you can see the quantity is six so it is working fine now what I have to do is apart from this we have to test one more thing which is get so duplicate this change the name to get card remove this and it will be a get request hit send and you can see that the cart is retrieved so if there multiple items in the cart so it will be array of all the cart items so it is working fine now in the next lecture we will see how we can create the order from this card hey there everyone now in this video we are going to create the models related to the order so we will be requiring three models one is for storing the orders and one for storing the products of all the orders so it will be a man to man relation explicit man to man relation because not only we will be mapping order and products but also we will be storing the quantity and apart from that uh we will be having a order event as well so if order is out for delivery accepted cancelled and all all these things so let's create them so first you will say model so let's borrow something from here we will have the user ID we will have not the product ID then not the quantity apart from that we will be having the net amount it will be of type double sorry decimal and it will be orders what else do we need in order we will be needing the address as well so address will be of type string so we will be like Computing the complete address from this address model so the comma separated address which we have seen on the cards so we will be Computing that and storing it as a string in this order and apart from that I don't think so we need anything else so let's uh create the reverse relation as well so in the user we will be having orders so it's done now we will need another model which will be order product and again we will be copying the same thing sorry and here we will be having order ID because this uh product will be linked to any order and it will be of type order and apart from that we need a quantity it will be int we don't need address here and it will be order products let's uh establish the reverse relation as well products and it will be of type order product so it's completed and we have order ID product ID we need product as well so let's copy this so we will say here product ID it will be of type product and in the product uh let's establish the reverse relation we will say uh so it will determine in which order this product belongs so let's say order product it will be of type array so it's completed now we need one more table which is order events so it will be order event let's again copy this store it here we need order we don't need product and we don't need quantity as well and we will say order events and inside the order let's establish the reverse relation as well so it will be events and we will say order event and we need one more thing so event obviously so we will create a enum here so let's go on top and create enum so it will be order event status so we will first the order will be like pending so it will be in the pending State then admin will approve this so it will be then go to the accepted State sorry yeah and after accept accepted it will be let's say out for delivery and then it will be delivered and apart from this we will be having one more which is cancelled so these are all the order event status now let's uh use this so we will have status and it will be order event status we will give a default value as well so it will be so we can have the default as pending so whenever the order is created we can give it a pending so it will be pending so we have all three models here let's uh create the migrations for these let's quit this and we will say create order tables let's wait and see if it succeed or not okay so it succeeded so we have all the three tables in place now in the next lecture we will create the controllers and try to create all the routes for that hey there everyone now in this video we will finish some routes regarding the uh orders so I have created few routes here so one is the create order list order cancel order or get order by IDs these are all the routes related to the user in the further videos we will see how we can create the admin routes as well so these are all the controllers here and similarly I have defined a route file as well which is orders. TS and have listed all the routes here so uh let's first start on this create order so this create order will be a bit complex so there are a couple of steps which we will follow so let me write it down so first we'll be to create a transaction because we will be uh dealing with the multiple models and the queries so transaction is required second one will be so once we create the transaction second one will be to list all the card items to list all the cart items and proceed if cart is not empty so if there are no items in the cart then simply we will return an error error message else we will proceed forward now apart from this no it's not okay now apart from this what we will be needing is uh once uh the cart ised we want to calculate the price calculate the total amount once the total amount is also calculated we want to retrieve the address of the user so fetch address of user and apart from that like we will fetch it but we will also want to create the formatted address as well so we will be like leading a computed field so we will Define that so fifth uh part will be to Define computed feed for formatted address on sorry on address model once everything is done we want to sixth step will be uh we will create order and order products and as a sorry it will be order and order products not order routes okay seventh part will be uh create the event related to that order so by default the event will go inside pending State create event so these are all the things which uh we will be needing let's comment this out sorry come on what am I doing okay so let's uh start working on these step by step so first part is to create a transaction so first you will say return await Prisma c. transaction and inside transaction we will be passing an async function which will receive the transaction object here and then we'll perform all the queries inside this Arrow function now first one is to like the create transaction is completed now the second part is to list all the cart items so const card items then a wait so now we will perform all the queries on this transaction object instead of Prisma client so we'll say transaction dot cart item dot find manyu and inside find manyu we will say where uh user ID will be request. user. ID so we have all the card items now we will perform the check so that check will be if C items do length equal equal Z then we will say simply response. Json and inside the Json we will say message cart is empty and we will return from here so we don't want to proceed further if the cart is empty now if cart is not empty then what you want to do is we want to uh create the uh price so first we will calculate the price and that price we will be calculating it using the reduce function of the array so we will say const price is equal to cart item. reduce and inside the reduce we will passing an arrow function and the initial value so initial value we will start with zero and this Arrow function will receive two arguments so one is the previous value and one is the current value so the previous value will be of type number because we will be Computing the uh price of each item in the cart and the current value will be the current cart item so we will iterate for all the card items and calculate its price so we will say return so inside the return we will say previous Value Plus and we want to say current dot quantity and that quantity will be multiplied by so we want to fetch the products here as well so we will say include product Tru because we need the price of the product as well so we need the product model so we will say current dot product. price and let's type cost this to number so this will iterate our all the cart items and it will calculate the price so if you're not aware about the reduce function maybe you can read it on the MD and docs so it will start with zero so it will say 0er plus the first cart items quantity into its price then so on and it will calculate the price so once the price is also calculated we have to fetch the address so we will say const address is equal to a wait so we will say transaction do address dot find find First and inside find first you will say where sorry ID will be equal to request dot user dot default shipping address we can store default billing address as well but let's uh do it for the shipping address and it will will be same for the wiing address so address is also there now we have to include the custom field like the computered field of formatted address on the address module so what we will do is we will go inside this index.ts and the place where we have defined this initialize this Prisma client so here we want to extend it so this is how we extend the or create the computed Fields if you had followed my lectures and what you want to compute so on the results results of address we want to attach an extra field which will be formatted address that formatted address we it will require couple of things so it will require line one it will require line two as well then City Country PIN code and then we will say compute and compute will take a function and the argument of this function will be the address and then we will say return first it will be line one sorry address. line one then comma address do line two then again comma it will be City then so address do City then comma then it will be address. country and then Dash and then it finally it will have the PIN code yeah so it will work like this so we have extended this address model to attach a for formatted address computered Fields now once we have all the information here now what we want to do is we want to finally create an order const order is equal to a wait transaction do order. create add inside data we will say uh first we will say user ID so let's pass first user ID first so user ID will be request do user. ID then it will be price or I guess it was amount net amount okay so the amount will be equal to the price which we have calculated apart from that we'll have address address do formatted address now you can see that we have auto complete here and then we want to create the product as well so we will say product create so we can create the related fields here as well in the single query so what we want to do is inside this create we want to pass an array of all the products so we can simply map over this cart items cart items. map and we want to return something and it will receive the card one by one and what we want to return is first we want to return the product ID so it will have cart dot product ID and then we'll have quantity so cart dot quantity and if everything is succeeded then the order will be created successfully now once the order is created then we want we want to do is create an event as well so we will say on await transaction are we outside the transaction yeah so this will go inside this transaction so we say transaction dot order event do create and it will also receive a data field which will have order ID order ID will be is equal to order do ID and apart from ID we will have status so by default the status will be bending so we can leave it as it is so we have order event now there is one more thing which I forgot so the eth step will be to empty the card so once the order is created there is no need of the card so as a final step we will say await sorry transaction dot cart items dot delete menu and inside delete menu we we will say where user ID is equal to request. user. ID so these are all the things it's a pretty complex create order function so just go through it and if you have any issues let me know in the discussion section and I will will happy to help you out and once everything is done what you want to say is return response. Json order now uh let's give it a try in the postman so go to the postman create a separate folder for the orders let's duplicate this move it inside the order and we will change the name to create order rename this two orders and inside the body we don't need anything so let's remove this now in the Prisma studio if you go in the cart item we have uh one cart item for the logged in user which has quantity 86 and user ID 8 with the products 46 so let's see if it's working or not okay so it's still running maybe I need to restart the server or what let's restart the server first now let's hit send okay so you can see that the order is created the net amount is 600 ID is two order ID is two and user ID is 8 so if you go into the Prisma Studio go into the order you can see that we have a live order of net amount 600 because in the cart item okay the card item is deleted so in the order product we have the product 46 and the quantity is 6 so 46 product the price is 100 so multiplied by 6 is 600 so everything is working fine order event is also there with the status of pending so everything seems to be working fine so this is how the create order works with all the transaction we have like utilized all the functionality here how to create many to many relations how to deal with transactions and then the extended models and all these things so it's a pretty good exercise now in the next lectures we will see how these list order cancel order and get order by ID works so one thing which I forgot in the previous lectures was we are storing the history of all the events for the order but we have to store the current status of the order as well so to do that in the schema. Prisma file we have to add an extra fi in the order which is status and that status will be of type order event status and here we will give a default value of pending now let's run the server so let's create the migration first add current status now I guess it should work so in case like we are creating the order here so by default the order will go into the gued state of pending so I I hope like you got my point so it's important to store the history as well like on which date and time the order like the status of that order was changed so when it was in pending so and on what date and time it got out for delivery and all these things but on the other hand we need to store the current status as well obviously we can compute the current status by this order event as well to fetch the latest event of that order but it's convenient to store it this way in the order model so yeah so that's all from this lecture now in the next lectures we'll finish all these routes now let's finish all these rout so first is the list order so in the list order we will say const orders is equal to await Prisma client do order. find manyu and inside where we will say user ID is equal to request Dot user. ID and we want to include a simple products as well because we can do that and get order by ID because in the front end we will first show the list of all the orders and then if someone will click on any particular order then we want to show the detailed version of that order so let's do it this way in the get order by ID we will fetch other things as well so it's pretty straightforward we'll say response do uh Json and we'll say orders let's finish this as well get order by ID so first you will say const so I guess we need to wrap it inside try catch because order may or may not exist yeah and here we will say through new not found exception and I guess we need to Define an error code AS as well so let's copy this here we will say order not found and let's just start all the orders with six now uh in the not found exception we'll say error code do uh order not found and inside try we will say const I'm very bad at typing so pardon me for that a wait Prisma client dot order dot find first or through and here we will say where ID is equal to request do params do ID and here we want to include certain Fields so what you want to include is we want to include the products as well and then we want to include the events as well so these two things sorry so yeah and we will response do Json simply return this response with order so these two things are completed and inside the cancel order it's a straightforward so let's copy this do this so once we have fetched the order or instead of like doing this what we have to do is order. update and inside the update we will say where ID is equal to request. params do ID and inside the data we will say status and as cancelled so this is how we have to do is do this and we have to create an event as well for the same so we don't need to store that in a separate variable we can do that a wait Prisma client dot order event. create data we will say order ID order ID will be equal to order. ID and status status will be cancelled so this is how it should work and here is a couple of assignment for you so first what you have to say is wrap it inside transaction so these like this uh controller involves couple of queries so wrap it inside trans ction and apart from that check if the user is cancelling its own order so we you have to do these two things so it's pretty straightforward and let me know the solution in the discussion now let's uh try all these things in the postman so create order is there we have to first save this now duplicate this and we have to say list orders it will be of type get so let's see okay it's throwing an error I guess the server is not working so let's run the server and see if it's working or not okay list order is working now duplicate this as well and we will say get order by ID here it's get so order ID is one I guess okay order not F so order ID is two I suppose okay so now you can see that the products and events are also listed now let's save this and create a separate route for control sorry canceling the order so duplicate this and says cancel order it will be a put request on order ID to so this should work cannot put on this okay so I guess it SL cancel so let me check and the routes orders so it is slash cancel okay now you can see that the status is cancelled now if I again fetch this you can see the status is cancelled and we have two events here so one is for pending and then is cancelled so all these three routes are working fine now from the next lectures we will create the admin related routes where we can modify the orders or change its status list all the orders based on all the filters like list all the pending orders list all the cancelled orders and all these things so so let's see you in the next lectures here everyone now in the upcoming videos we will see how we can uh finish all the admin related routs so here are couple of things like which I have written down so first is regarding the user management so for the user management we will be needing list user API uh this will be paginated then one API to list a user by ID because uh then we'll list all its address and all these things apart from that we need another API to change the users to so these are the things which will be controlled by admin and in the order management we will be needing similarly an API to list all the orders and change the order status and at last for the products we just need a simple search API for the products now this will be for both users and admin because users will be able to search the product on front end and same for the admins as well and here we will learn the New Concept of full text search so let's get started with all these things so if you go into the users controller I have created the three routes so one is three controllers sorry one is list user get user by ID and change rle and the users routes I have used all these three uh controllers here so put on SLR will change the role get on slash will list all the users and similarly for ID so uh let's uh finish this first so what we are going to do is first is list user so it is pretty straightforward so what we are going to do is so we will say const users is equal to await Prisma c. user. find manyu and inside find manyu we will give two arguments one is a skip so how many rows we want to skip so it will be request do query. Skip and if it's not there then we want to Simply return the first page and we will type curs to number and take and we want to keep the page size consistent to Let's suppose five and we will say response. Json and users so it is pretty straightforward now get user by ID here we have to wrap the code inside TR catch here we will throw the exception so it will be not found exception message will be user not found and error code will be error code dot user not found and here we will say const user is equal to await Prisma client. user dot find first or through and here we will say where sorry ID is equal to request do params do ID and if you go into the schema and for the users we can see we have address and orders so for the user management we just need address because cart and orders are like not really necessary so if uh we want to fetch the orders of any users we can create a API which can all the orders of a given user so we will also do that in the order management so let's fetch only addresses for this given user so we will say include addresses scent true and we'll say response. Json and then we will say user so this is also complete now in the change role this is also pretty straightforward so let's copy this first and here we will say update so where ID will be this and we will not have include here instead uh sorry instead we will have a data field and inside data we will say rle and it will be request do body do Rule now uh you can perform the validation here as well validation so you can define a schema so you can do it on your own the schema will have a single key of rooll and it will be of enum so just do it on your own so let's uh give it a try for all these three routes so first let's check if the server is running no it's not running so let's run the server first okay okay now go to the postman and the users simply duplicate this request and we will say list users and in the body we don't need anything it will be a get route hit send you can see all the users are listed here we have only three users so obviously three users will be listed save this duplicate this and now change it to get user by ID and here we want to Simply fetch the user it hit send you can see now the address is also fetched so it is also working fine now again duplicate this and we are going to say change role and we want to change the role of user s so let's see if it has seventh user or not let's close all these tabs first so we have a user 9 so let's change the role of this user as of now it has a user role so we want to change it to admin so let's see change it to nine inside the body we will say roll to admin let's hit send okay it works now if I reload this you can see okay it's not working role is still user so let's see if it what's going on wrong here okay I need to change this as well sorry the route so let's check the route first so so slash rolles so it will be/ id/ rolles so it was my mistake so it will be SL id/ rolles I guess it's role only yeah now let's hit send cannot get so it's a put route now you can see that we have admin here now if I refresh this you can see it changed to admin so all these three routes are working now in the next lecture we will see how we can complete all these routes so let's add one more thing here list all orders of given user and also we want to list the order by ID as well but if I go inside this .ts I guess we have yeah we have this route so there is no need of a separate route here admin can use these routes only so but for admin uh I guess you are aware we have to put this admin middleware and if admin middleware is not like there so either admin or user both can access that route so that's how it works so let's see in the next lecture then now let's go ahead and finish all the order related routes for admin so as usual I have created three controllers one is list all the orders one is to change the status and the last one is to list the orders of a given user and in the routes. TS I have used all these three controllers so on/ index it will list all the orders slash users colon ID uh user ID it will list the orders of a given user and put on/ status will change the status so let's uh do these so first for list all the orders so first you want to fetch the filter const status is equal to request do params dot status so if a status is present we want to do something so first let's construct the we Clause let where is equal to where Clause is equal to so in the we Clause uh we want to as of now we don't need anything in we Clause because we want to list all the orders irrespective of any filter but if a status filter is given so we will say where sorry where Clause is equal to uh is status colon a status so it will be just a status here now let's remove this okay so if a status is there we need to alter the we clause and add the status here now we can say that const orders is equal to a wait GMA client. order. find menu and inside find menu we can simply say where colum where Clause is Skip we want to obviously include the pation as well so we will say request dot query do is Skip or zero because as usual we want to fetch the zeroth page if uh no esape is given and take let's say five so it should work let's type cast this to number now we can say response do Json orders so uh this is how list on orders work now for change status it will be pretty straightforward again uh we want to wrap it inside Tri cat so let's copy this here and if there is any error we will say order not found and if there is no error we will say update where and in instead of include we want to give the data so data will be is status coron and we will say request Dot body do status and apart from this we want to create an order event as well so we will say await Prisma c. order event. create we will say data and Order ID and for the status we will say request dot body dot status so it will create the event as well now we need to wrap this inside the transaction so let's uh do this as an assignment wrap it inside the transaction and so yeah it should work I guess now for list user orders we want to do again the same thing so let's copy this from here paste this now instead of we Clause initially where it will be user ID user ID will be equal to request do params do ID and it will be integer and what it's saying okay so first we need to extend the we Clause as well and then we can do that and let's give it of Type n so it should work so if a status is given we need to First include this user ID as well and then the status so I guess it should work now so yeah now let's give it a try all these three routes go to the postman and the orders let's close all these things first so let's first duplicate this now uh it will be a get route orders SL index lets it send it says order not found okay seems like there is an issue in the route definition uh we need to Define this route at the very last I guess because slash uh colon ID like this index route is picked by this colon ID so it's treating index as an ID so we need to Define this at the very last route order is important so please take care of that now let's see if it works or not yeah so it is working now let's uh give it an status so a status is equal to accept it so let's it send okay it's still giving the status as cancelled so I guess is status quy is not working request do peram do status uh it will be query do status sorry because we are sending it inside a status query not the parameters now let's it send it's giving anty error so we will test it in a bit once we change the status of any order and let's read rename this list all orders duplicate this and we will say change status it will be a put route and for change status the route is slash status so it will be slash colon id/ status because we want to change the status of Any Given order add in the controller yeah controller is fine so let's give it a try so I guess the order ID is let me check the order ID first order is is two and we want to change the status to accepted so we will say order ID 2 and a status and inside the body we will say let's s send okay it says accepted now if we go to the list all orders so the status is accepted filter now let's it send you can see that the status filter is working fine now one more thing is left to list all the routes for a given user so I guess it's pretty straightforward you can test it on your own so let's not waste time in that it will work in the same way just give the user ID here now uh in the next lecture we will see how full text search is performed in Prisma so let's see you in the next lecture hey there everyone now in this video we will learn about full text search so for that I have created a controller which is search products and in the routes so if you go to the routes we have this route of/ search so the route will look something like this so it will be slash search question mark Q is equal to and the string that you want to search so Q did like Q stands for query here so in the production like the best practice or you can see the conversation that we use is question mark Q is equal to and then the search term so this is what we will follow now uh to get started with this uh first let's go to the full Tech search documentation so it's a still preview feature so there are steps to enable that so first we have to add these lines full text search now uh before you move to implementing the full text search now first understand what full text search means now in the conventional databases like the relational databases you can search on a single column so for example in the schema. Prisma for the products we have couple of columns here name description price tags and all these things so in a conventional search either you can search using the name column so in uh like the SQL you have seen that keywords like like or contain something like that so either you can search using a single column but there is no way where we can see if the keyword exist in multiple columns so full text search enables us the capability to search across multiple columns in the same table so now like now we get what the full text search is let's enable this so this is for post SQL and this is for my so for MySQL you have to add these two things as a preview feature so let's copy this and go to the schema. Prisma and in the client add this now after this we have to run Prisma generate so npx so that it can fet the required things for us okay now you can see that it was successful now in order to enable this uh for the products we have to add an index as well so in the products we will say add at full teex search and here we have to list all the columns uh that we want to perform like through which we want to search a given keyword so we will say name and we'll say description and then we'll say tags so in these three columns we want to search a given query so now it's done we need to gen like uh gen the migration as well so we will say npx Prisma migrate Dev add full text search yeah so it was generated successfully now uh it says already in sync because I have tried few things before so mine was already there so for you if you'll try it on a new project or this one only it will say the migration was generated successfully now let's run the server again npm start now let's go to the controller so the end controller uh what we will say is cost products is equal to a weight Prisma client do product. find manyu inside find manyu we have to give a we clause and for we Clause uh the fields that we have defined in the full text search here we have to give all the all these fields and inside the V Clause separately so if you go into the documentation and scroll to the indexes you can see that if we have defined the full text search on content at title we have to give both these fields so and it says however if you'll try to search on title alone the search will fail so if you say if it's saying that if only content is given and you skip the title so it will fail so we have to Define all these three years so go to the controller and first you'll say name we will say search request. query do q and let's do this to two string because somehow it was giving an error so it will work now we will like convert everything to string same goes for title sorry description and same goes for tags so this is how it works now in response. Json we will say products sorry products now uh let's give it try in Postman I have already created a search product route so it's product/ search and the query which I given is let's say cotton so let's hit send so there are a couple of products here and if I search the word cotton you can see for the first it is present in name in description also in the second it's also present in name but in third you can see that it's not present in name but it's present in description so as you can see that and same for the last one as well so you can see that it's performing the search across multiple columns so that's what we need so yeah that's how full text search works and let me know if you have any doubts and try to implement on your own and just for an assignment implant Implement pagination ER so just complete this finish this and yeah so we have all the routes in place now now now let's see you in the next section now for the source code go to my GitHub repository or GitHub profile and my username is namish WMA 17 so this is my profile navigate to the repositories and here you will find this repository as Prisma resources and inside this you will find all the source code related to this project so clone this source code if you want to make any changes please go ahead and do that so and if you want to see how you can deploy that you can also like clone this and create your own EB files and deploy it to URL servers so let me know if you face any issues regarding this so yeah
Info
Channel: Evoqys
Views: 14,404
Rating: undefined out of 5
Keywords: prisma, prisma client, prisma orm, orm, nodejs, typescript, javascript, development, mysql orm, mysql, migrations, prisma studio, programming, backend, database, nested writes, raw, queries, raw queries, pagination, computed fields, one to one, relations, sql relations, one to many, many to many, error handling, error handler, generic error handling, higher order function, error, middlewares, authorization, full text search, full text, search, enhanced search, searching
Id: 6-mGtUyfGLw
Channel Id: undefined
Length: 215min 18sec (12918 seconds)
Published: Mon Jan 08 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.