TypeORM Tutorial (Seamless Typescript ORM)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello class in this video you're going to be learning about typeorm or typeom if you want to save 0.1 seconds which i do so i'm going to go with type on so what is type on typeom is an orm that works with node.js or any other javascript library or framework or anything that works on the backend of your application and like any other orm it allows us to connect to our sql databases and manipulate and fetch data from there and apparently it works with mongodb as well i haven't tried it with mongodb but i believe them i'm sure it works so what's nice about typeom is that it's written in typescript and it allows us to use typescript straight out of the box without having to configure anything which is really nice uh of course it allows us to get all the benefits of using typescript like type safety autocomplete in our editors having our editor shout at us if we make any typo that will cause a runtime error and also like decorators and a bunch of other nice things that come with typescript and of course which means that we can use also the latest features of javascript so let's actually uh set up our project with type oram shall we [Music] all right so here in typeon.io i'm going to go to getting started actually it's the same page that's just a dead link that's a bit misleading all right so here we have all the features that uh type arm has which is pretty nice i'm just gonna scroll through them and here it shows us um how to create a database model which are called entities in type orm and here by the way you have to watch out in the documentary of this documentation documentary it shows there's like two approaches that you can use or two patterns and you can use both the first one is the active record which is where you use like uh your entities as models like kind of like object oriented like model like um objects and the other one is using repositories what is it called um think it's here yeah the data mapper pattern i've never been a fan of this pattern i've seen it before in other orms i don't like it i'm just going to use the active record one and i think it makes more sense when working with actual classes and objects all right let's set up our project so we can scroll down here to installation it tells us what to install and how to set it up but we can also use a cli which is really handy so i'm gonna do that so right here go to using cli and scroll down so here it tells us my wheel is going crazy so here it tells us to install not here here it tells us to install typearm globally so let's do that so let's copy that i'm going to go back to my desktop i'm going to create a new folder i'll call this typeorm dash tutorial and open that with vs code and i'm going to open my terminal i'm going to paste that in and install type arm globally and now that it's installed and can say type or init and now it will initialize our project and create a bunch of stuff so we have a source directory we'll come back to this we have a dot get ignore and we have an orm config and here is where you put your database credentials to connect to your db and also we have some configurations so we can tell typearm where all our entities and migrations and subscribers are and we can also tell it to so we can set synchronize to true which will create database tables based on your entities without having to write migrations so this is really good in development and we have logging which are set to true for us to see sql queries that are run on our database in our console i'm going to change of course the credentials i'm going to be using postgres so i'll change this type to postgres the host is localhost the port is 5432 for postgres port i'm going to change the username to class because it's my username and the password to root of course these should match your credentials so yeah i'll save this and here we get a ts config which is standard with typescript it just has some configuration and it tells typescript to build everything into a slash builder directory once we do build our files for production and also it tells it to enable decorators because we need to use decorators in type on so let's go we have a package.json of course which has the dependencies but i'm going to change two things here that we have ts node and typescript have really outdated versions so i'm going to update those so let's open the terminal and let's say npm install uppercase d type script at latest and also ts-node at latest and hit enter and let those update and i'm going to say npm install to install the rest and while they install make sure to like this video and subscribe to the channel if you haven't done so yet alright everything is installed now i need to create that database actually i didn't name the database so here in our arm config we have a database which is called test now i'm going to change it to type or underscore tutorial so let's create that i'm going to copy that i i'm going to open psql i'm going to type my password and here i'll say create database and paste that name and put a semicolon and there we go i've successfully created it i can connect to it so backslash c and connect to it so now i'm in it of course if we do backslash d we have no tables yet so let's change that so i'm going to open a new terminal and actually let's go to our source directory first so here in our source directory we have an index.ts where this is our entry file our main top level file and here we import reflect metadata don't worry about it this is something you just need with type rm and here we have create connection from type on which we call which does exactly that connects to the database and then after that we do whatever we want to do on our database so here what we're doing is we're importing the user entity and we're creating a new user so let's look at that entity so here in entity slash user.ts we have our user entity which uses these decorators so we have the entity decorator which tells typescript that this is in fact inheriting from the entity type and here we have our primary generated column id which increments on its own of course and we have a first name and our last name columns actually i'm going to replace these with just one name column so i'm going to here say name and here we have a column age i'm going to change this to email and it's going to be a string i'm going to add another one so duplicate this i'm going to make this roll and to use the active record pattern we need to extend from a different class so we need to extend from base entity of course we need to import it from type on and now let's save this and if we go to our index.ts here it's already like complaining because these fields don't exist anymore so that's pretty nice so what we can do here is let's actually delete everything inside of here i'm going to say const user equals new user like this i say user dot name equals john doe i'm going to say user.email equals johnathemail.com and dot user.roll equals i'm gonna make him an admin and here we need to say await user dot save like that and here i'm gonna just console.log uh user created exclamation mark and save now to run this we already have a yeah we already have a start script which runs ts node and runs our index.ts so that's nice so we can go to our console and say npm start and hit enter all right we get an error that's uh interesting okay so this is my bad driver package not installed because we need to have postgres if we're working with postgres here we have my sql by default if you're using my sql this is not a problem for you but for me i'm going to actually uninstall my sql and install pg to have that postgres driver so now if i do npm start i shouldn't have any errors all right that's cool so it's synced to the database so it did a bunch of stuff including creating the table right here and it actually inserted that user and it said user created so if i go to my p sql and i say backslash d we see that we have a user table and if i say select star from user actually this is a problem it's uh there's a conflict between names between actual post psql users and this user inside of here i'm actually going to drop this schema so to the way to do this if we go back to the documentation we can use the type on cli when we're using javascript but we can also use it with typescript using something like this so let's grab this script from here and let's go to our package.json and let's paste that script here and i'm going to change it to not use the syntax instead of requiring that package we can use that package straight away so ts-node and run exactly this and now if i do npm run type orm it's going to run type omcli but using typescript which allows it to be used with our development typescript files so if i go here and say npm run uh run type orm and just hit enter okay it's uh i don't know why there's an error here so we got zero and one okay there was i didn't pass any options so that's okay let's not worry about it so here we have all of the uh commands that we can run so ignore bin dot js we have schema sync which allows us to sync the schema but i can drop the schema so here i can say type on schema drop like that and now it's actually going to drop all the tables so if i go if i want to change the table name i'll go to that entity the user and here we can pass an object inside the decorator and we can set a bunch of stuff here including the name which is the name of the table but if we just pass a string it's going to infer that that's the name of the table so i'll pass a string users so if we go back to our terminal and we run npm type run type arm schema sync now it's actually created you see here create table users it's actually created a table but named it users instead this time okay so let's actually start to set up some cred routes for our user instead of just using this we're gonna have some express routes so i'm gonna open the terminal i'm gonna say npm install express actually i forgot we're using typescript so let's install actually it's called that i will install as a dependency dev dependency so let's install at types express to have express types all right so now if we go to our app our index.js let's um let's separate the relative imports from the absolute ones or the dependency ones and here let's say import express from from express and let's create our express app so here we'll say const app equals express like this as a function okay it's complaining for something um okay so it says that express doesn't have a default import but we can we can either do this so import start a star as express or we can also enable that flag so let's copy this flag es module into uh op and go to our um ts config and add that here and set that to true save now actually let me i need to actually maybe i didn't need to close and open it okay that uh that warning is gone so now we have our express app uh let's actually use the json middleware so app.use express.json and now i want to set the first route to create the user so i'm actually going to remove this call or actually keep it but inside of after we create the connection we need to start listening so we'll say app.listen and we'll use the port 5000 and this has a callback and here for the callback we're just going to console.log server up on or at http oops http colon slash host colon 5000 save that we don't need this connection so we can remove that and here we'll create our first route so we're going to do the usual create read update delete and find so for our create let's say up dot post to slash users and this will have a handler and i'll make it async so we'll have a request we can use types as well so we can make it a type request hit enter and it will import it from express and we'll have a response which is of type response like that and we'll have we'll do an arrow function and inside of here let's actually get to the input from the request body so we'll say const name email and role equal request dot body so we'll send these in the request body so here let's do our try catch so here let's actually create this user we'll say user actually instead of doing all the fields separately we can say equals user dot create and do an object and pass those fields so name email and role and don't confuse yourself this create just creates an instance of the user entity it doesn't actually persist anything to the database so here we need to actually say await user.save for that to be persisted in database and now let's return that user so we'll say return res.json and we'll pass that user and of course let's do our catch so catch error and if there's an error i'm just going to console.log it and i'm going to return rest.status 500 500 dot json let's actually return that error during development we can here actually to be semantically correct have a status code of 201 because there's a resource that was created all right so let's save and now let's run that so let's go to our terminal and say npm start all right so we get server up on localhost 5000 i'm going to open insomnia to interact with this uh mini api that we have all right so we have some examples from last time that i'm going to use so we have the eraser i'm going to create in this tutorial because i used it in other orm tutorials so the first one is the create so we're going to send this object and we're supposed to get something similar to this of course we're not going to have this id because that was mongodb so let's send this make sure it's localhost 5000 users and it's a post request so send this all right so you get two one created we got our user with the id one and exactly what we created and if we go back to vs code and we go to our p sql and we do select star from users colon hit enter indeed that user does exist in our database so that's cool so we have the created already nailed down uh one thing that i want to add also is timestamps we don't have timestamps enabled by default in typearm so we go to our entity user here we can have some useful um decorators so we could say add create date column and which imports it from type arm and of course close do parentheses and here let's call this created at and this will be of type date this tells type arm to create this as a create date column which automatically sets it to the current date when that object is created and now we'll do the same for updated actually not the same it's a different directive not directive sorry decorator so here we'll say update date column and here we'll say updated add and that's of course the type date of course make sure they're both imported and this of course changes each time you update the model so let's save now let's uh run our app again which will sync this will be a good time for me to install nodemon and use that instead of restarting the server each time so let's say npm install dash up case d nodemon and hit enter i'll go to the package.json and add a development script here let's say here dev will be nodemon node mon and we're actually going to execute the typescript code so we'll say dash dash exec for execute and we'll say ts node source slash index dot ts so we're running the same as the start but using node 1 so that if we make any changes it's going to restart our server so save that and now let's say npm run dev and now it's actually started it with nodemon and it's persisted sorry i'm in sync the data the database and it's altered the table the table uses and added these two time stamps so that's cool so now if we go back to uh okay let me close actually i'm gonna go closer i'm just gonna go here so go back to insomnia and create jane doe so jane at email and jane let's say is just a user and we hit enter we indeed get our user and we get our created ad and updated ad timestamps which were created for us so that's sorted now let's create the read endpoint which gets all the users so let's go back to our code i keep going the wrong way so here in the index i'm gonna maybe just copy it to save some time paste it here so this will be a get endpoint to the same slash users which i realized oh no that's fine so here we have we don't need any input which means we can omit the request and here we instead of just creating the user we'll say const users equals weight user dot find and find usually takes a condition but we don't need any condition because we want to get all the users and here we're not saving any users so remove that and we'll return the users and the status code should be 200 which is the default so we can just remove this so save that and let's go to insomnia and here let's run this so it's a get request to localhost 5000 slash users so run that we indeed get our users so one is john doe and two is jane doe and they have their fields all right so that's created successfully so next thing i want to do is of course you don't want to expose the id and you want your users to have something to use to identify a user by that was a lot of user but you get the point so if i show you an example here in the previous thing we did in the find endpoint we're using slash users slash the id of that user but of course this id is not an incremental natural number so it's okay to expose it so let's create a uid for our users so we go back let's go back to our editor and in the console so i'll say npm install we need to use a third-party package for this uuid and we can install also the types for it because you're using typescript so let's say at types slash uid and close that now let's go to our user let's add this uid field so here we'll say at column and this will be called uid and it's a string and you can actually add postgres types here we can say type type inside of here and say that it's a uid so it creates it as a uid type inside of postgres but this doesn't set itself automatically what we can do we can use these hooks or i think in type arm they're called listeners so if we go back to documentation yeah right here listeners and subscribers we have a couple of events that we can use like after load before insert etc that we can use to operate certain things on our model so for example here they show you a manual way on how to create a created date for yourself so actually we can just copy this and let's go back to our ide and here we can go at the bottom and say at before insert of course we need to import this from type on and here we have a function we can call this anything it doesn't matter for me i'll call it uh create uid because that's what it does and here we'll say this dot u id uh let's import the uid library or we'll say import actually we need v4 and as uid from uuid and here we'll say this dot uid equals uuid like this as a function which sets the uid of this object so if we'll go back um actually if we go back to insomnia and actually make sure it's synced uh actually my server is not even running so let's do npm run dev okay we get an error so here it says um okay this because the previous data didn't have any uid so that creates a problem so if i go to psql and just say delete from users delete all the users uh that should solve that problem so if i just restart the server all right so it syncs properly because that is set by default to not be null and if you had previous fields that had null there i mean they would have had an old one that is created that column is going to error out okay let's check if this is actually working so if we go where is the insomnia it's here um so if we go to create and now we create jane doe again let's say we change the jane doe to be an admin and we hit enter there we go we get a uuid that is automatically generated for us so that's cool we are now using the listeners to perform different things on different life cycle events and places during the creation or fetching of models okay let's say we wanted to remove the id from the response which we should because this was should not be exposed so what we can do is in our model we can override something called to json which is the default method that allows us to return our object as a json so here we can say return and we can do the spread operator and spread this which refers to this instance and then we can set set the id to undefined so save that and now if we go back to insomnia and we can if we create another user so here is john because we don't have john right now and we run that we indeed get our user back but without the id so that's one way of removing those fields and of course the same goes for the read endpoint now the id is obscured or hidden or like removed so let's create the rest of the endpoints which include updating and deleting and finding specific users so here we have uh update which we need to send an id and send the fields that we want to update and it should actually update that row in the database so let's go back to our index.ts file so here on the update we can say up dot put which is going to be a put request for updating and this will be to slash users slash let's do colon to pass a parameter and say uid and then here let's do async request request of type request and response of type response and do an arrow function and here we need to get the uid from the request parameters so we'll say const uid equals request dot params dot uid and we also need to get the data from the request body so we need to destructure a name and email and role equal request dot body just like we did earlier with the create so let's do our try catch block so if we get the get an error and also here in our type in our try we'll say const user so we need to find the user first before we update that user so we'll say wait user and we can use find or fail or oops find one or fail and we'll pass it a condition which will be just uid being that uuid which means we can just do this so of course if it fails it's gonna throw an error and if it doesn't fail that means this user exists so let's update that user so you can say user dot name equals name or user dot name so if we give an empty value or a null value it's just gonna set it to the previous value so it doesn't actually set it to undefined so let's do the same for email and let's do the same for roll and now of course we need to say await user.save and here let's return that user return rest.json user and here if we get an error i'm just going to console logger console.log error and return rest.status 500.json and we'll say err something went wrong now let's actually copy that and give it up here it's better for production to not expose your actual error save now let's go to insomnia and try to do that so if we read we get all the users and let's say we want to update john and make him just a user instead of an admin and also change his email so let's take his id and go to the update so that will be to localhost 5000 slash users slash and paste that uid make that a put request and in the json body and change this email not to my email but to let's say john gmail.com and the role is now changed to just user so ctrl enter and there we go we get john doe and the email has changed to gmail and the role has changed and of course the updated ad has changed because that's uh changed because it's updated all right so the update endpoint is done so let's do the delete so delete is simple you just pass the uid and then it should delete and return a deleted successful message so i'm going to copy this i'm going to go to the delete and paste that we do the same we get the uid and then we don't get anything from the body and then here we say user equals let's delete this find one or fail by uid and then once it finds it we need to say weight user.remove and now here we return res.json and we'll say message user deleted successfully and we can be semantically correct in data say dot status status 204 which means this resource doesn't exist anymore and here if we get an error we just say something went wrong all right let's test this so we go to insomnia let's take john doe's i you id paste copy it go to slash same root slash users slash paste that uid make it a delete request and execute it okay so we get cannot delete this so the router was not found so that's because okay i forgot to change this to delete so the method should be delete all right let's try that again execute that okay we get no body it was returned i think we only return the status code the body is emitted okay so i want it to be a smart ass but apparently you can't return a body with two or four but it worked successfully because if we go to check in our database and we say select star from users we see that john is gone actually i could have just executed the read and point all right so the john is actually gone all right now we just have the find which is very simple we just get a one object or one instance or record and return it so again i'm going to copy this i'm going to make it into a get and it's going to get that with that uid it's going to find that user but instead of removing the user we're going to just return that user so status code 200 or which is nothing and the json we just pass user and this we know the error if there's an error here that means we just didn't find that user so we can actually set this to 404. of course you can check what the error says and here return different responses but that's a bit besides the scope of typo ram itself so i'm gonna just do like a simple error here and maybe this will be user and it will say user not found all right save that let's try to run that so in the find uh we have only jane so let's find jane of course the difference here we have an array of users uh okay let's create john doe again of course in read we get all of them and in the find and if we paste that uid and we execute this we get only jane as that soul object instead of an array of users all right so the end points for users are done let's actually create a posts which is a different table that includes posts but that are like created by users so here we have the first endpoint which is do you specify the id of the user and then the title and the body of the post and it creates it and returns it for us and it also creates this slug which is automatically generated from the title so let's actually create that so if we go back to our ide or editor let's go to our entities and create a new one so here i'll create a post.ts and i'm actually going to copy the user and they're very similar they both have a primary generated column id and here instead of name we'll have a title and instead of email we'll have a body and here we'll have okay we're not going to have a role and we're going to have a uid as well okay you know what i just realized there's a lot of similarities between the post model or the entity of the user one so there's a lot of repetitions so what we can do we can actually uh create a new one here and to avoid confusion i'm going to call it model so say model.ts so what this will do is i'm going to create an abstract class that our entities will extend to have all the shared functionality so here i'll say export abstract abstract class model and this will extend the base entity and this imports it from typo rm and let's open that and we're going to have the shared field so if we go to our user let's uh cut the id and take it to model and also let's go and cut the uid and the timestamps cut them and bring them to model of course we need to import these decorators and import column and import created date and also updated date and i think there's also yeah in the to json we need to hide the id for the post as well so cut that actually this as well this um listener so cut both of these basically just leave the fields in the user and remove the imports here they're not needed anymore here as well and also for uid let's go to the model paste those in of course we need uid so we can import that okay what is it doing okay i thought it's going to import it anyway let's import it manually so we'll say import v4 as uuid from uuid all right we have before insert let's import that from type arm and save and now if we go back to our user and we'll say import model which i can make it the default export from here so export default abstract class and here we can just say model without curly braces from the same directory model and now we just extend that instead of the base entity which means we should remove this from the imports all right so now our user file is so clean and now we can do the same in a post just extend the model import that and now we don't need any of this and also base entity and the timestamps the before insert and entity as well we we don't even need this actually no we do we need entity sorry we need entity for here so here we need to change this to posts and we need to remove the id and we need to actually rename the class to post remove uid and the timestamps and the before insert listener and also the to json all right so you see now our mo our entities are so like lean but they also have all the fields and functionality that is shared all like abstracted in this abstract class so now we need we can run our sync or actually we can just run our server which will actually just uh on its own restarted so that's created the the posts so if we describe posts here in our database we see that we have our post table and it actually has the id and all the other fields and it also has the fields that are specific to the post so that's a nice thing that we can do with typescript so let's actually start to create these posts and fetch them so we go back to our index ts as create those two endpoints so what do we have we have a create and a read for posts so go here let's say create create a post and also read posts so this will be an app dot post to slash posts and we'll have async request type request and the response of type response we'll do our error function and here we'll say const of course we don't have authentication so we're just going to obtain the use user uid from the body so we'll say user uuid uid and the title and the body equals request dot body so let's create this post so it will say try const post equals actually i just realized we need to find the user first because if there's no user we need to error out so it's basically this so let's copy that and paste that here but instead the the uid needs to be user uid of course we don't get that user we get an error and we need to catch that error and we'll say we'll just console.log that error and return basically the same as this actually not the same but i'm just going to change this to 500 and say just error and say something went wrong now if we do have the user let's create the post so you can say post dot actually let me show you another way of creating posts so we can use constructor constructors so we can go to our post model i have a constructor and here because this inherits from a different class we need to call the super of course the constructor takes some data so here let's say it takes um a title and a body now we can give them types title will be of type string and the body will also of course be of type string and when you we do get them we'll say object dot assign to assign them to this instance of course we assign them to this which is this instance and we'll pass this object with title and body so now we can use this syntax so we can say const post equals new post and we'll just pass it what we need to pass it so now it's suggesting to us we have a title and a body so we say title and body like that and actually i just realized we need to actually add details about the user in the post because the post belongs to user which will be a good segue to relationships or relations in type on so here you can go to document documentation almost said documentary again and you can find all the relations so we're interested in many to one and one to many because one user has many posts and every post belongs to one user so here we'll see the example here so here for example a category has actually this is many to many so let's look at uh can i click on this one too many no it's not clickable this is clickable cool all right so here we get the photo has a user and the user has many photos so this will be a good example to just copy so let's copy this let's go back to our editor and in our post we can just paste this here of course import that decorator so here this is the first kind of what is it called they call it say a type function or target and then there's the inverse relation so here this returns a type user and let's import that from our user entity and then in the user it we can say this is the inverse so for the user has user.posts and then this is a user of type user this doesn't exist yet but we'll create it actually for many to one the inverse relation i think is optional yeah we can just omit that so let's set set up the other side of the relation from the user side so we could just go here we see the user has one too many two photos so we can just grab that go back go to our user here just paste that here import one to many decorator so here returns a type of post and import that from our post entity and for the user or the post rather we return post dot user for the inverse and here we'll have posts as an array as an array of post entity so let's save now let's look at our output okay we get cannot read property title of undefined okay i'm just gonna make this a generic um a generic object so i'll just say i'll just say model and then just give it a question mark meaning that it could be null and here i'll just make it a partial of any object so i'll say partial and then give it a type of any uh actually this is a generic so we can use it for both so we can just cut it from here and then save this and we go to our model entity abstract class and save that here and then here we can say so assign this and assign the model and this is any and this is model all right so now in any um anything that extends this model we can use a constructor and pass it anything so here in our post it doesn't it's not going to complain so if we check our output yeah it doesn't and we check our database and we do select or actually uh just backslash d posts we see that there is here a user id which refers to the user so this is a foreign key that refers to the users table that connects the post to the users so that's cool so for us to actually tell typeorm that this post belongs to this user we simply pass the user itself as an object and it will take from it whatever key it needs so now let's actually save this post we'll say await post dot save and then return that post return res.json post all right save that let's test it out so go insomnia and go here to create posts let's grab uh let's grab an idea from here scrub jane doe's id or uid rather keep saying id so here in the create post let's give a user uuid and then paste that there and oh what did i click so here title should be like hello from jane that should be just like any title doesn't matter so here the body will say the body of the post very creative all right so execute this and voila we get our post with the timestamps with the uid with title and the body and with the user object as well returned with it now if you fetch this post on its own it's not going to return this it's only returned in this because we actually added it like this here so these uh the post is being created successfully and it's actually uh adding the user id if we check here we select say select star from posts we get this one post and it has a user id of three because that's jane's user id so we go and check select from users you see that jane has an id three so this post is indeed linked with jane let's create another endpoint for getting all posts along with their users so i'm just going to copy that and paste it here this will be a get to slash posts we don't need any input so we can omit that and here we don't need to fetch a user and here i'll fetch so i'll say const posts equal await post dot find and here we'll pass uh not a condition but if in options we can do relations and we'll pass an array of relations and we can pass the user which is the alias for that relation which will get the user for each post and here we just simply return res.json posts so let's go ahead and see how that works or if that works so here if i fetch so get slash posts and i execute that indeed i get all the posts which right now is just one alongside with their user and of course the ideas are omitted because that's part of the default model abstract class all right so that's we're fetching the relation between the post and the user so that's nice let's fetch the inverse of the relation so let's go when we read from users let's get also all their posts i'm going to create another post by by john so let's go here say john take his uid and go to create paste that here this will say hello from john the body of john's post and execute that create maybe another one hello again and i'm just not i'm going to change the body so we go to request get all posts we get all the posts like this so now we want to get to the posts as part of the user payload so if we go back to our ide what is this okay let's um so up here uh where we find honor here we can do that here as well but let's do that for the get users so here where we find we can say relations and then here's a post and that should work so let's save and go here run that and indeed we get for jane we get her posts which is just this one and for john we get these two posts as part of their object all right so that's cool uh one thing that i forgot to address actually is validation because if we right now go here and i think it's going to work if we create a user with just empty fields run that yeah it does actually work which of course shouldn't be the case so we get some nice um actually we don't validation we need to import we need to install a third-party package which is i think it was developed by the community for typeorm or like similar orms which is class validator so i think they mention it even in the documentation let me check yeah use invalidation yeah so here it shows you we need to install class validator and you can use all these nice decorators that add validation to your model so things like whether the string contains or minimum and marks for numbers etc and is email so let's use a bunch of these so i'm actually gonna go back to editor go to the terminal close this and say npm install class dash validator and hit enter and let's go to our let's start with the user so here for the name let's say i want to add a length of so length and open this and the length is now imported from class validator and we can give it a minimum and a maximum so minimum will be one and a max will be 255. so this automatically if we pass a null or empty string it's gonna error for us and i'm gonna do the same for the email and i'm also gonna say at is email for email to check that it's a valid email address and here for role we can use a default enum type so here let's inside the column let's open an object and say type enum and then also give it the actual enum itself which is an array of values so we'll have user and we'll have admin and we'll have super admin and then let's actually set the default in case it's empty and this will be of user so by default a user is just a user so let's save this and let's check if it's working so go back to insomnia to create this should give us a couple of nice errors so let's run that all right actually i forgot to run my server so let's go open the terminal and pm run dev and let's make sure that we're returning the errors so in the index.ts where are we post yeah here so yeah we are returning the errors okay so let's go to insomnia execute this cool so we get all right so not that cool in terms of like errors because we only get an error for the enum it's kind of like yeah it's just trying to execute the query and it's not actually doing javascript validation it's just executing the query and depending on the first constraint that was violated it's going to return that error so if we fix the enum error so the role is a user actually creates a user with empty name and email okay so let me fix that what's happening here okay looks fine um let's look at the example they used okay let's check class validators [Music] uh documentation uh oh i see so you need to import validate and also call validate on your model instance for it to validate it okay there is the javascript validation we just didn't call it all right my bad all right let's go to the index and let's go up here and we'll import that so import oops import validate from class validator and here where we yeah where we post after we create our user instance we need to validate it so we'll say await it's actually asynchronous so we'll say await validate user which actually returns the returns the validation errors so actually we need to make that into a variable so const errors equals this is const equals these errors and we need to check if we have any errors so if errors dot length is bigger than zero then we need to actually throw these errors so throw errors and here actually where we throw them yeah nothing happens we just return them so that's that's all right and of course if there's no errors then actually try to create that user so save that and go back to insomnia and now if i execute this cool we do get an array of errors and the first one is for the name and it says name must not must be longer or equal to one characters and another one for email and for role if you give a different one users which is not valid we should but we didn't get an error for um okay i know why because we actually the i created this is this postgres validation this is actual postgres uh database constraint and not class validator validation rule let's find that validation rule and search for enum okay so here we have uh is enum okay so here on top of roll i'm going to stack this other decorator and say it's enum let me import it and here okay do i pass it d right i'll just go i'm just gonna pass the array and see what happens all right so let's go back to insomnia run that okay cool so that's not a valid value so if i just say user it should be a valid value cool we don't get an error and if i of course say admin we don't get an error but if i say administrator and execute we do get an error because administrator is not valid and if we emit it completely we don't get an error because it's going to give it okay we do okay i think i'm going to add maybe uh undefined to one of them so it has to be either undefined or one of these all right so execute that okay it's a bit hacky but it works and what's more important is that we have the database constraint so it can never actually be persisted the wrong way in the database itself even though if our validation errors are not super on point all right so name must not must be longer than one characters so let's actually create one for myself so ahmed and email actually let's uh make sure that it's validating the email so ahmed how to without.com run that we get that this is not a valid email so which is correct and the valid email oops is this oops so many typos execute boom there you go so armored and it created me and man i'm just a user should be an admin now all right so that's validation so yeah that's uh you can go into the class file data and look at all the other stuff that you can use to add some more validation to your models if you need it and yeah so let's go i want to create migrations now because of course in production you don't want to be using sync because that's really dangerous so let's see how we can do that actually i think it's a it's a command yeah it is a command let me check all right so npm run i actually forgot how to do migrations in type arm okay so okay so we have migration generator which looks out our entities and generates a migration file so before i do that i'm going to drop all the database first all right so i'm going to go here copy i don't actually i didn't even need to copy it it's not even that difficult so say npm run type orm what is it schema colon drop to drop everything and let's go to our configuration so orm config and set synchronize to false to make sure that it doesn't create these tables and we create them through the migration so i'm going to run typeorum and run migration excuse me i'm losing my voice uh generate and hit enter okay there's an error migration okay we need the argument n which is uh the name of the migration so i'm just gonna say and create dash like schema all right okay i know why it's missing the argument because to forward the argument to an actual script we need to say dash dash and then do your arguments all right hit enter all right so migration was created and let's have a look at it so it's right here and it actually has the sql to create we have this enum for the role and we have the table posts and we also have the alteration on the post to add the foreign key and yeah also the table users all right so to run these we need to say type or npm run type on migration run and hit enter and there we go it actually ran all that migration and now if you do run again of course it's not going to run it because it knows which one it ran and which one it didn't because it keeps track of that in the database because if you go i do backslash d you see there is a migrations table and if you do select star from migrations and execute that you see that the create schema was actually run and there's a timestamp and if we can we reverse it yes there is a down of course we can reverse it what question is that all right so we can say migration is it revert yes i actually saw that earlier let's revert cool so now we reverted it and if we do is there status there should be status yes or there isn't okay okay it's actually show in type or keep switching text stacks and it's confusing show okay okay it just shows that oh okay i just i just rushed through it it shows that it's create a schema and this is supposed to be a checkbox and if it's checked that means it's run so if i say migration run and now if i say migration show it should have a tick in there yes it has an x in there which means it's run it's a bit smart way of i mean anyway i'm not gonna rag on it whatever it works okay so now our migrations are executed through files which is of course much safer for production speaking of production of course in production you shouldn't run typescript you should run javascript so let's actually build out our server so uh we can say tsa tsc actually if you don't have it installed globally you can just use a script we wrote that earlier thank you we didn't so let me do that so here i'll add a script called build to build the files into javascript which is just tsc because all the configuration is is here for typescript to know what to do so here let's say npm run build and hit enter and there we go we get a build directory let me close this and we get an index.js of course this is a generated javascript from our models and our migrations interesting that it has create schema migration okay that that's interesting but it works all right so to run our javascript we need to actually cd into it so cd into build and node index and run it as javascript and there we go we get server up on localhost 5000 let's uh test that okay we get something went wrong a repository found for user okay i've seen this error before i was expecting it and that's because in the auram config we need to also tell it where to find javascript files so i'm going to copy this i'm going to put alt and select all of these and do a comma and paste that so here for entities for javascript entities we can look in the same directory because once we run it from here it should look relative to here so we'll say dot slash entity and instead of ts at the end we say js and actually i'm just gonna paste that instead of this and this will be migration and this will be subscriber which wouldn't create any but it's not that important all right so now we should actually find the javascript uh entities and migrations without any problem so if we do node index all right so get server up on 5000 and if we execute this all right we get okay and it's actually working because if i go and create a different user i'm just going to create myself again hit that cool actually persists it and it's actually working and it's using javascript so that's that with typeform i really like it it's a bit confusing to get going with typescript if you're new to that and decorators and stuff but once you get the hang of it it's really powerful again please do make sure to like this video it does help a lot and i really appreciate it and of course if you haven't hit the subscribe button and hit that really nice bell so that you get all these amazing videos that i release so yeah that's it for this thank you for watching and i'll see you in the next one cheers
Info
Channel: Classsed
Views: 16,591
Rating: 4.9409285 out of 5
Keywords: typeorm tutorial, learn typeorm, nodejs typescript orm, nodejs typescript tuorial, get started with typeorm
Id: Paz0gnODPE0
Channel Id: undefined
Length: 58min 4sec (3484 seconds)
Published: Tue Nov 10 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.