WEBVTT

00:00.020 --> 00:07.430
Okay, so now let's work on refactoring our schemas in our application to entities in type ORM.

00:07.580 --> 00:11.170
Let's start off with the reservations Microservice.

00:11.180 --> 00:16.730
So right now under our models directory, we have our reservation dot schema.

00:17.240 --> 00:22.070
I want to go ahead and rename this as we've done in the previous cases.

00:22.070 --> 00:25.100
I want to rename this to reservation dot entity.

00:25.130 --> 00:25.730
Now.

00:27.760 --> 00:35.040
And here we will no longer be importing the abstract document or using the schema decorator.

00:35.050 --> 00:42.070
Instead, we're going to use the Add entity decorator from type ORM, which will mark this as an entity

00:42.070 --> 00:45.640
and will create a table for us based on this schema.

00:46.510 --> 00:55.540
Now let's change this to be a just reservation and it's going to extend the abstract entity where we

00:55.540 --> 00:58.420
pass in the reservation.

00:59.830 --> 01:04.360
And we can also remove the exported schema from the bottom.

01:04.720 --> 01:12.430
Now all we have to do to move this over to a type of entity is change these prop decorators to add column

01:12.430 --> 01:18.830
decorators which represent a column in our table in our SQL database.

01:18.850 --> 01:23.590
So let's go ahead and replace all of these properties with an Add column decorator.

01:23.590 --> 01:30.070
And now let's go into our reservations repository where we're going to have to refactor this to now

01:30.070 --> 01:34.390
work with our newly implemented abstract repository.

01:35.200 --> 01:42.520
So of course we will remove the reservation document and replace it with just a reservation.

01:42.970 --> 01:49.570
And now we are going to still extend the abstract repository, but now we'll pass in the reservation

01:49.570 --> 01:50.800
entity.

01:51.610 --> 01:54.130
And importantly, in the constructor.

01:54.130 --> 02:01.570
Let's go ahead and remove this because now we're going to be using at inject repository from Nestjs

02:01.600 --> 02:06.070
type ORM to actually get our repository injected for us.

02:06.100 --> 02:10.480
All we have to do is provide the entity name here.

02:10.480 --> 02:12.430
So let's provide the entity.

02:12.670 --> 02:21.840
So we'll call this reservations repository of type repository and pass in the reservation entity.

02:21.850 --> 02:28.150
And then of course, we also need the entity manager of type entity manager from type ORM.

02:28.750 --> 02:36.470
Now in our super call to our abstract repository, we will pass in the reservations repository as well

02:36.470 --> 02:38.120
as the entity manager.

02:39.350 --> 02:42.710
We can go ahead and remove our imports to Mongoose.

02:43.370 --> 02:47.750
And now our reservations repository is set up to work with type ORM.

02:48.020 --> 02:54.560
So we need to tell Nestjs about this entity we've created so that it knows how to resolve this injection

02:54.560 --> 02:55.230
here.

02:55.250 --> 03:01.240
So let's go back to our reservations module and let's change out a few things here.

03:01.250 --> 03:07.000
Firstly, we'll change our import to just import the reservation entity itself.

03:07.010 --> 03:14.000
And then for the database module, we're no longer calling for feature with a set of schemas, but instead

03:14.000 --> 03:17.030
now we'll have an array of just straight entities.

03:17.030 --> 03:24.920
So all we have to do is pass in our reservation entity and now Nestjs will know how to inject this repository

03:24.950 --> 03:29.570
for us because we're providing it to type ORM through our database module.

03:30.050 --> 03:36.710
All right, so next up, let's go to our reservation service where we can see we have some issues creating

03:36.710 --> 03:40.500
our reservation in our reservations repository.

03:40.510 --> 03:47.370
Now, the reason this is, is because right now we're trying to just pass in a straight JavaScript object.

03:47.370 --> 03:53.730
But of course we know with type we need to actually instantiate new instances of our entities in order

03:53.730 --> 03:54.570
to save them.

03:54.570 --> 03:56.250
So we can do this easily.

03:56.250 --> 04:03.720
Let's create a new const here called the Reservation and we will instantiate a new reservation.

04:04.170 --> 04:11.670
And now we can pass in this partial of the reservation from our DTO, which is why we did this.

04:11.700 --> 04:14.850
It's going to be very easy to create a new entity.

04:14.880 --> 04:22.390
We can simply cut the object we're using to the repository now and paste it into our constructor call.

04:22.410 --> 04:29.880
So now that we have this reservation entity, we will pass it in to our Create call and our repository

04:29.910 --> 04:35.880
now knows how to actually deal with this object and can save it to our database.

04:36.120 --> 04:37.950
So a couple other things.

04:37.950 --> 04:39.570
We're going to go ahead and refactor this.

04:39.570 --> 04:46.560
So instead of taking in an ID of type string, we know that type expects this as a number.

04:46.560 --> 04:53.490
So let's go ahead and change the ID parameter to be just ID of type number and we'll pass in this to

04:53.490 --> 04:54.600
our find one.

04:55.140 --> 04:58.440
We'll go ahead and do the same thing for our update method.

04:58.440 --> 05:04.210
We'll change this to ID of type number and pass this into here.

05:04.240 --> 05:10.120
Now of course our update method is complaining because it has no idea about this set property which

05:10.120 --> 05:11.830
only exists in MongoDB.

05:12.670 --> 05:21.460
Instead, we can just simply pass in the entire update reservation DTO, which of course we know is

05:21.460 --> 05:24.910
just going to be a partial of our create reservation DTO.

05:25.330 --> 05:28.450
Finally, for the remove method, we'll do the same thing.

05:28.450 --> 05:33.310
We'll change the ID to of type number and swap this out.

05:33.610 --> 05:36.810
So now our reservation service is all refactored.

05:36.820 --> 05:42.910
We'll go to the reservations controller where we'll go ahead and have to change this ID to of type number,

05:42.910 --> 05:47.230
which we can easily do by just applying a unary operator.

05:47.260 --> 05:53.680
The plus sign beforehand, which will cast this string to a number in these three methods.

05:53.710 --> 05:59.290
The other thing we have to do now is update our dot m file with the properties that our database module

05:59.290 --> 06:07.690
expects so we can go to our existing dot env and copy over these existing dot env properties and let's

06:07.690 --> 06:10.360
swap them out here for our MongoDB Uri.

06:10.690 --> 06:18.100
We'll have the MySQL database of type sleeper and this will be the MySQL password we'll set equal to

06:18.100 --> 06:19.540
our root password.

06:19.990 --> 06:24.240
Then we'll go ahead and add the remaining variables that we need.

06:24.250 --> 06:28.780
We need the MySQL host which will be equal to MySQL.

06:28.810 --> 06:35.890
Now this is because our Docker image is labeled as MySQL and this represents the host name in Docker

06:35.890 --> 06:36.520
networking.

06:36.520 --> 06:38.170
So that would be MySQL.

06:38.170 --> 06:43.210
And then the MySQL port, we know we set to 3306.

06:43.420 --> 06:48.250
I'll go ahead and also set the MySQL username which we know is root.

06:48.490 --> 06:56.350
And finally, if you remember we have the MySQL synchronize environment variable and we can copy this

06:56.350 --> 06:59.410
from the database module as it's a little bit easier.

06:59.410 --> 07:04.910
So we have the MySQL synchronized which is going to synchronize our schemas when we're developing locally.

07:04.930 --> 07:06.820
We'll set this equal to true.

07:07.420 --> 07:13.900
So now the dot m file and the reservation service has everything we need to satisfy the database module

07:13.900 --> 07:14.560
here.

07:15.340 --> 07:18.730
Let's move on to the auth microservice next.

07:18.760 --> 07:22.570
We'll start off by going into our libs common folder.

07:22.600 --> 07:28.960
Go into the models directory and this is where we're hosting the user schema, which if you remember,

07:28.990 --> 07:31.570
we're sharing between several different microservices.

07:31.570 --> 07:33.940
So we have this one type in one place.

07:33.940 --> 07:35.830
We only need to change it once.

07:35.830 --> 07:39.460
So let's go ahead and do this just as we have done with the reservation.

07:39.460 --> 07:45.550
We're going to refactor this to be a type ORM entity that will extend our abstract entity.

07:45.760 --> 07:52.000
I'll go ahead and remove the schema decorator and add the at entity decorator.

07:52.030 --> 08:00.910
I'm also going to go ahead and change the name to just be a user that extends the abstract entity and

08:00.910 --> 08:04.660
I'll go ahead and then pass in the user type to our generic.

08:05.210 --> 08:11.270
Next we can remove the user schema, export and everything else from Mongoose will remove and we'll

08:11.270 --> 08:19.040
go ahead and replace the prop with at column decorators as we've done before for the email and password,

08:19.040 --> 08:20.840
which are simple data types.

08:20.840 --> 08:29.000
However, in the case of roles, roles is going to be a relationship in our type or entity and this

08:29.000 --> 08:34.910
relationship is going to be a many to many relationship where we can have many different roles that

08:34.910 --> 08:37.760
are associated with many different users.

08:37.760 --> 08:44.420
So the user and roles will end up being in totally separate tables and we will have a join table that

08:44.420 --> 08:47.020
links the user and roles up together.

08:47.030 --> 08:55.010
We can go ahead and describe this relationship using type ORM by adding the many to many decorator.

08:55.280 --> 08:58.280
And then we're going to go ahead and provide some metadata.

08:58.280 --> 09:01.310
So we'll go ahead and specify a new role type.

09:01.310 --> 09:04.550
So we need to create this user role entity.

09:04.580 --> 09:07.860
Now let's go ahead and do this in the models directory.

09:07.860 --> 09:12.540
We will export a class called Role Dot Entity.

09:15.490 --> 09:19.650
And we will have a new ad entity from Typeform.

09:19.660 --> 09:26.530
We'll export the role that extends the abstract entity and pass in the role type.

09:27.190 --> 09:33.490
And then we will have a simple one column table which is just going to have the name of the role.

09:34.380 --> 09:40.740
Now, if we go back to the user schema, we can now provide the type for the role by passing it in to

09:40.740 --> 09:43.620
this decorator as the return type.

09:43.620 --> 09:48.870
And then I want to specify an options object where we're going to set cascade property to.

09:48.870 --> 09:49.560
True.

09:49.590 --> 09:55.920
So you can see here, this means that if it's set to true, the related object will be inserted or updated

09:55.920 --> 09:57.060
in the database.

09:57.060 --> 10:02.940
So essentially what this is going to allow us to do is save just the user entity, but then the roles

10:02.940 --> 10:07.710
that exist on that entity will also be updated using this cascade.

10:08.190 --> 10:14.070
So we'll go ahead and enable this and then we can say this roles array is of type role.

10:14.100 --> 10:20.190
So the benefit of this approach now is that we are going to not have to duplicate and create new roles

10:20.190 --> 10:21.930
each time if they are the same.

10:21.930 --> 10:26.820
We can just share these associations with many different types of users, which is great.

10:26.850 --> 10:33.870
Now finally, let's go ahead and rename the user schema to a user entity to stay consistent.

10:35.870 --> 10:43.940
And then what we can do is find all occurrences of our user document and go ahead and replace that with

10:43.940 --> 10:46.070
a just straight user.

10:46.100 --> 10:52.700
I'll click on Replace to replace all occurrences of our user document with just the user because we

10:52.700 --> 10:55.460
referenced the user quite a bit in our application.

10:56.000 --> 11:03.530
Finally, we need to specify the adjoin table decorator which is used in this many to many relationship

11:03.530 --> 11:09.620
to specify the owning side of this relationship, which just means the user is going to be the one that

11:09.620 --> 11:13.740
is is in charge of the association with the role.

11:13.760 --> 11:16.430
So we'll go ahead and provide this decorator as well.

11:16.730 --> 11:26.330
So let's also go into our index.ts and make sure that we explicitly export our newly created role entity,

11:26.330 --> 11:29.980
which we will need to provide to our database module.

11:29.990 --> 11:35.610
So additionally, we can go ahead and remove our user DTO.

11:35.820 --> 11:41.700
Let's go ahead and also do a search and replace on the user DTO for just the user.

11:41.730 --> 11:49.650
I'll go ahead and replace all occurrences with the user model instead of the user DTO, which will simplify

11:49.650 --> 11:51.630
our code a bit.

11:51.630 --> 11:57.780
So make sure then we go to the index.ts for the user DTO and remove the export.

11:58.170 --> 12:05.520
Now, since our roles are actual objects, now we need to change how we are checking for them in our

12:05.520 --> 12:06.600
pipe here.

12:06.750 --> 12:16.530
So after roles we're going to call dot map to transform the role and get the role dot name because we

12:16.530 --> 12:23.850
want to check for the role name, which if you remember, is what we are providing to our role decorator.

12:24.270 --> 12:29.850
Okay, so back in our reservation service, you can see our create method is complaining because we

12:29.850 --> 12:33.180
are no longer using the underscore ID off of the user.

12:33.180 --> 12:39.780
We want to pull off the ID field and then we can also see the reservation is having issues because right

12:39.780 --> 12:44.430
now the reservations user ID is set to a string.

12:44.430 --> 12:50.670
Let's go ahead and change this to be a number which is going to match our data type on the ID for that

12:50.670 --> 12:51.300
user.

12:51.330 --> 12:51.720
All right.

12:51.720 --> 12:56.670
Let's go back to the auth service now where we will start off in the dot m file.

12:56.670 --> 12:59.700
We'll update this just as we did with the reservations.

12:59.700 --> 13:07.290
We can actually just copy over all of the environment variables and we'll go ahead and delete the MongoDB

13:07.320 --> 13:10.770
Uri and paste in all of our MySQL information.

13:11.530 --> 13:12.040
Next.

13:12.040 --> 13:18.310
Let's go ahead and go inside of our users repository, which we know we're going to have to refactor

13:18.310 --> 13:21.730
to match the type pattern we have in place.

13:21.730 --> 13:28.630
So we need to go ahead and remove our current constructor implementation and instead we will call inject

13:28.630 --> 13:36.730
repository and pass in the user entity and call this users repository of type users repository.

13:36.730 --> 13:41.800
And then we will get the entity manager of type entity manager.

13:42.190 --> 13:49.660
We'll go ahead and then pass up the users repository and entity manager to our parent class and users

13:49.660 --> 13:56.830
repository here should be repository from type ORM with the user entity supplied, then we can go ahead

13:56.830 --> 14:00.550
and remove our additional imports to Mongoose.

14:00.550 --> 14:07.450
And let's go to our users module where we will refactor our database module call to now just pass in

14:07.450 --> 14:14.510
an array of our entities which we know is going to be the user as well as the role that exists on the

14:14.510 --> 14:18.050
user, which we will also import from app slash common.

14:18.530 --> 14:24.440
All right, so from our find and replace earlier, we need to fix a couple of our DTOs and the users

14:24.440 --> 14:25.280
directory.

14:25.280 --> 14:33.260
So make sure we relabel the create user DTO and the get user DTO and then we'll go to the users controller

14:33.260 --> 14:40.040
where we will relabel this, create user DTO and change our parameter back to create user DTO.

14:40.040 --> 14:47.570
And now if we go into the user service, we'll add DTO to these two types as well and the same thing

14:47.570 --> 14:49.160
as our parameters here.

14:49.160 --> 14:54.530
For these methods, we will change this to create user DTO and get user DTO.

14:54.530 --> 15:01.130
And lastly, we'll go ahead and make sure we change the parameter name back to create user DTO in the

15:01.130 --> 15:10.700
controller and in our user service, we will change this back to create user DTO and get user DTO make

15:10.700 --> 15:14.120
sure we also update our parameter names in our function.

15:14.120 --> 15:17.600
So I'll change this back to create user DTO.

15:18.450 --> 15:24.030
And in our Create method we will also change this back to create user DTO.

15:24.180 --> 15:29.850
So next, let's go ahead and create a new user by creating a new const and calling new user.

15:29.850 --> 15:37.560
And then we'll pass in this subset of properties from the create user DTO into our options object.

15:37.560 --> 15:45.120
And we can go ahead and make sure we import the user entity from app slash common.

15:45.570 --> 15:51.540
So our user constructor is complaining because we haven't updated our dto's for our roles.

15:51.540 --> 15:52.830
So let's go ahead and do that.

15:52.830 --> 15:53.310
Right now.

15:53.310 --> 15:57.930
We're going to create user DTO, we have our roles still set as strings.

15:58.020 --> 16:06.570
Let's go ahead and create a new dedicated DTO called Role DTO Dots and we will export a class called

16:06.570 --> 16:09.660
Role DTO that has two properties.

16:09.660 --> 16:18.700
Now the first will be in is optional and is number, and this is going to be the ID of the role that

16:18.700 --> 16:24.370
we want to reference in case we don't want to create a new role and we just want to reference an existing

16:24.370 --> 16:28.450
role, then we pass in the ID here and we don't create a new one.

16:28.630 --> 16:34.540
However, if we do want to create a new role, we'll go ahead and specify this with providing an optional

16:34.540 --> 16:40.420
name, which can be a string, and we'll go ahead and enforce this with class validator by providing

16:40.420 --> 16:49.180
the is optional the is string and the is not empty so that this cannot be the empty string.

16:50.460 --> 16:57.690
So if the name is provided and the ID is not, then we will have a new role that gets created in our

16:57.690 --> 17:05.550
database with an auto generated ID thanks to our Cascades in type, which we set up on the user entity

17:05.550 --> 17:07.770
and describe this role relationship.

17:07.770 --> 17:12.900
So now that we have the role DTO, let's go back into the create user, DTO where we're going to go

17:12.900 --> 17:15.030
ahead and reference the role.

17:15.030 --> 17:20.520
DTO, we're also going to go ahead and get rid of these two validators because this will be an optional

17:20.520 --> 17:25.110
array and all of their validation will occur on the Subobject.

17:25.140 --> 17:28.800
We can then go ahead and get rid of the unused imports as well.

17:29.190 --> 17:36.180
Finally, to make sure our role DTO actually gets validated, we want to provide a validate nested decorator

17:36.180 --> 17:43.230
and then we need to provide the at type from class transformer to make sure this actually gets instantiated

17:43.230 --> 17:43.890
as a role.

17:43.890 --> 17:52.540
DTO So now back in the user service, let's set the roles property equal to the create user DTO dot

17:52.540 --> 17:55.510
roles and we'll check to see if it exists.

17:55.510 --> 18:03.460
If it exists, we will map over the role DTO and instantiate a new role that gets passed in the role

18:03.460 --> 18:09.060
DTO as its constructor and also make sure to import it from app slash common.

18:09.070 --> 18:15.430
So now that we've created the user, let's pass it directly in to the repository in order to create

18:15.430 --> 18:15.760
it.

18:15.790 --> 18:21.340
Now next you can see down at the bottom our get user method is complaining and this is because in our

18:21.340 --> 18:26.190
get user DTO, we're still expecting an underscore ID to be provided.

18:26.200 --> 18:31.600
Let's change this to just a regular ID and we'll also need to change this type to be a number.

18:31.600 --> 18:36.850
Now next up, head to the auth service where we will change the token payload.

18:36.850 --> 18:45.070
We're pulling off of the user to user.id and we can get rid of the two hex string call as well.

18:45.220 --> 18:51.390
Then we need to go to the token payload itself and update the user ID to be of type number.

18:51.400 --> 18:57.580
Next, let's go to our JWT strategy where we are currently calling get user.

18:57.610 --> 19:02.020
We want to pass in just the ID property and change it from underscore ID.

19:02.770 --> 19:09.790
So before we start up our containers, make sure that we go to the reservations module and remove the

19:09.790 --> 19:12.700
MongoDB Uri from our validation schema.

19:12.700 --> 19:18.790
Since we're no longer supplying this, we'll go ahead and do the same thing in the auth project.

19:18.790 --> 19:21.280
We will remove the MongoDB Uri.
