WEBVTT

00:00.020 --> 00:04.160
Okay, so we're ready to test out our newly created abstract repository.

00:04.160 --> 00:09.770
And to do that, we're going to go ahead and create our first microservice inside of our mono repo.

00:09.800 --> 00:16.910
The service responsible for actually taking reservations from our users when they want to book a stay

00:16.910 --> 00:17.510
somewhere.

00:17.510 --> 00:23.990
So in order to generate this in the terminal, I'm going to use the nest cli and run nest G for generate

00:24.020 --> 00:32.270
app and we'll call this microservice reservations so we can see that we have a newly created apps directory

00:32.270 --> 00:40.340
here with a default directory with our existing source folder from before and the important reservations

00:40.340 --> 00:48.350
folder which has its own source directory and set of default files as well as its dedicated config that

00:48.350 --> 00:50.660
will extend our root TS config.

00:50.660 --> 00:56.090
So if we also go ahead and look at the nest CLI so we can see we've added these two new applications

00:56.090 --> 01:02.820
into our nest client JSON and so we're not actually going to keep this sleeper directory here, the

01:02.820 --> 01:07.950
default one out of the box so we can actually go ahead and remove this and let's go ahead and change

01:07.950 --> 01:14.700
our route here to instead of Apps Sleeper, we'll change it to apps Reservations, which will be our

01:14.700 --> 01:15.780
default project.

01:15.780 --> 01:24.090
And also go ahead and change here the TS config path and make sure we pass in app slash reservations.

01:24.090 --> 01:29.910
And finally we have the source route property here which we can see points at the default project in

01:29.910 --> 01:30.930
a mono repo.

01:30.930 --> 01:35.130
So as I said before, our default project we will just use the reservations.

01:35.130 --> 01:41.760
So swap that out here and then finally we can go back and actually delete the sleeper directory altogether.

01:41.770 --> 01:48.420
And so now we just have our apps reservations directory to be able to go back to our terminal and start

01:48.420 --> 01:53.610
things back up using NPM, start dev and you can see our application starts up fine.

01:53.640 --> 01:59.580
We are not seeing the Mongoose module being initialized anymore and that's because of course we've gotten

01:59.580 --> 02:05.910
rid of the original source directory and we will have to re import it in our new reservations microservice.

02:05.910 --> 02:11.490
And that's exactly what we're going to do by going into the source directory and inside of the reservations

02:11.490 --> 02:12.240
module.

02:12.240 --> 02:20.310
We know of course, that we are going to pass in the database module and make sure we change the import

02:20.310 --> 02:23.340
here to be at app slash Common.

02:23.700 --> 02:30.540
And so now if we go back to the terminal, we can see that the Nest app starts up and the Mongoose module

02:30.540 --> 02:33.000
is initialized and everything's all right.

02:33.000 --> 02:35.670
And of course I still have Mongo running in another tab.

02:35.670 --> 02:42.390
So in order to add some default CRUD functionality to our reservations service, we can also use the

02:42.390 --> 02:49.830
nest Clive and have it generate a resource for us called reservation and make sure we generate this

02:49.860 --> 02:51.690
in the reservations project.

02:51.690 --> 02:55.380
And we can see here that it asks us which transport layer we want to use.

02:55.410 --> 03:00.120
We're going to use a variety of transport layers in this course, but for now we're just going to start

03:00.120 --> 03:05.700
off with a default rest API and then it asks, Would you like to generate CRUD entry points?

03:05.700 --> 03:07.650
We will go ahead and say yes.

03:07.650 --> 03:13.710
And so this is going to go ahead and create some boilerplate code that's going to save us a lot of time.

03:13.710 --> 03:19.410
So after our command here completes, you should see we have a bunch of new files have been created

03:19.410 --> 03:20.310
for us.

03:20.310 --> 03:26.220
And so if we go back into VS code, we now have a new directory, our reservations directory, where

03:26.220 --> 03:31.230
we have a set of files here that will allow us to accomplish CRUD functionality.

03:31.230 --> 03:35.040
So first off, here we have our reservations controller.

03:35.040 --> 03:41.190
So this will be a controller with the reservations prefix that will have a reservation service and we'll

03:41.190 --> 03:48.750
call all the CRUD functions on it, including being able to create a new reservation, find all, find

03:48.750 --> 03:51.090
one update and remove.

03:51.090 --> 03:56.700
And you can see here we're taking advantage of these nestjs decorators in a controller so that these

03:56.700 --> 04:00.660
routes are mapped to get patch, delete and post routes.

04:00.660 --> 04:04.140
And we're also extracting the body here on some of these calls.

04:04.140 --> 04:10.860
So in our Create Reservation request here, we can see we have an automatic DTO already defined for

04:10.860 --> 04:16.860
us that will have no properties by default, but we will fill out eventually and for find one we have

04:16.860 --> 04:20.910
the param to get the ID of the reservation for Patch.

04:20.910 --> 04:27.500
We do the same and take an update reservation DTO, which is just going to extend a partial of our create

04:27.510 --> 04:28.530
reservation.

04:28.530 --> 04:34.140
And then lastly, we have the delete route here that takes the param and removes the reservation.

04:34.140 --> 04:36.120
So we're going to continue building this out.

04:36.120 --> 04:40.620
But it's nice that we have all of this boilerplate already complete and of course we have a reservation

04:40.620 --> 04:43.710
service here that is just filled in with stub methods.

04:43.920 --> 04:48.660
So what we're going to do is we're going to go ahead and take all of the files in this reservations

04:48.660 --> 04:52.290
directory and move them up into the source directory.

04:52.290 --> 04:55.620
So when we do this, it'll ask us to replace the existing files.

04:55.620 --> 04:57.420
I'll go ahead and replace them.

04:57.420 --> 04:59.880
And now we're ready to start actually using our.

04:59.940 --> 05:06.180
Our abstract repository so we can fill out this reservation service and actually interact with a database

05:06.180 --> 05:06.900
directly here.

05:06.990 --> 05:13.500
Go ahead and open up the reservations module because since we replaced this with the Nestjs command,

05:13.500 --> 05:18.220
we're going to have to re add our imports array here and add the database module.

05:18.240 --> 05:24.300
I'll go ahead and change the import here to app slash common and then we can go ahead in our source

05:24.300 --> 05:30.590
directory and create our actual reservations dot repository, dot ts.

05:30.600 --> 05:36.690
And so this will be an injectable class because we will be injecting this into our reservation service.

05:36.690 --> 05:42.210
So we'll go ahead and export our class here called Reservations Repository.

05:42.210 --> 05:48.870
And this is going to go ahead and extend that abstract repository that we created before.

05:48.870 --> 05:51.390
And I'll go ahead and change this to app slash common.

05:51.390 --> 05:56.970
And you can see here that the compiler is complaining because we have not actually exported the abstract

05:56.970 --> 05:57.900
repository.

05:57.900 --> 06:07.600
So make sure in our source folder we open up the index.ts and open up the database Index.ts and actually

06:07.600 --> 06:11.470
export everything from abstract repository.

06:11.470 --> 06:17.920
So if you recall back in our reservations repository, the abstract repository here expects the document

06:17.920 --> 06:24.580
to be passed in which extends the abstract document that has the underscore ID, which is of type object

06:24.610 --> 06:25.120
ID.

06:25.480 --> 06:29.080
So we need to pass in the reservation schema here.

06:29.080 --> 06:33.520
So to do that, I'm going to go ahead and rename the entities folder here.

06:33.520 --> 06:40.750
I like to just call it models and inside I will change the reservation dot entity here to be reservation

06:40.750 --> 06:46.990
dot schema and we're going to go ahead and define the schema for what a reservation document actually

06:46.990 --> 06:47.920
looks like.

06:47.920 --> 06:55.300
So to do this, we'll go ahead and add a decorator here called ADD schema from Nestjs Mongoose.

06:55.300 --> 07:00.610
And I'm going to pass in an options object here and set the version key to false.

07:00.610 --> 07:04.090
I don't want versioning on my documents in this project.

07:04.090 --> 07:08.740
And then we're also going to change the reservation here to be called the reservation document.

07:08.740 --> 07:17.380
And we know, of course, this will actually extend the abstract document that we can import from the

07:17.380 --> 07:18.760
app slash common.

07:18.760 --> 07:23.560
And then inside we're going to define the properties that exist on a given reservation.

07:23.560 --> 07:29.050
We already know we'll have the underscore ID, so we'll continually come back and add to this document

07:29.050 --> 07:31.060
as we build out our microservices.

07:31.090 --> 07:35.500
However, for now we can add some basic information about this reservation.

07:35.590 --> 07:42.100
So the first thing I want to add here is a timestamp, which will be a date and actually be the time

07:42.100 --> 07:44.530
that this reservation was created.

07:44.530 --> 07:49.210
I'm also going to add a start date, which will be another date here, which will be when the reservation

07:49.210 --> 07:53.080
begins, and then we'll add an end date, which will be when the reservation ends.

07:53.080 --> 07:56.410
Now we don't have any idea of authentication or users quite yet.

07:56.440 --> 08:01.990
However, I know eventually that I'm going to want to associate this reservation with a given user ID,

08:02.290 --> 08:04.390
so this will have a type of string.

08:04.390 --> 08:11.260
So next this reservation is going to be tied to a particular hosts user so that the user who actually

08:11.260 --> 08:14.640
posted this document, we want to be able to associate it back to them.

08:14.650 --> 08:14.980
Okay.

08:14.980 --> 08:20.170
And lastly, this reservation is going to be for a given place in our application.

08:20.170 --> 08:26.620
Now, places will be where you actually stay for this given reservation and places will be its own microservices

08:26.620 --> 08:27.880
in our application.

08:27.880 --> 08:33.430
However, for now, we want to be able to associate a given reservation with a place so we will label

08:33.430 --> 08:37.180
it place ID of type string so that we can associate it with.

08:37.180 --> 08:37.390
Okay.

08:37.390 --> 08:42.250
And lastly, we're going to have a property to actually associate this reservation with its invoice

08:42.250 --> 08:43.150
in our system.

08:43.150 --> 08:48.160
So we'll have another microservice that actually takes care of invoicing and billing the user.

08:48.160 --> 08:52.420
And we want an ID to be able to associate this reservation with that invoice.

08:52.420 --> 08:56.890
So we'll assign an invoice ID here and this will also be of type string.

08:56.890 --> 09:01.000
So for now, this is everything we need to create our reservation document.

09:01.000 --> 09:04.660
And we're getting an error here that the abstract document was not exported.

09:04.660 --> 09:13.120
So we'll have to go back to our index.ts for our database and make sure we export everything from the

09:13.120 --> 09:17.500
abstract schema here so that we satisfy this.

09:17.500 --> 09:23.200
Now, back in the reservations repository, we can finally provide here for some type information the

09:23.200 --> 09:26.620
reservation document that we just created.

09:26.920 --> 09:27.310
Okay.

09:27.310 --> 09:31.300
So next we need to actually tell Mongoose about this document.

09:31.300 --> 09:38.290
And in order to do that, we need to decorate each of these properties here with the app prop decorator

09:38.290 --> 09:40.420
from Nestjs Mongoose.

09:40.420 --> 09:47.860
So after we've done that, we need to actually export a new const here called reservation schema.

09:48.010 --> 09:57.520
And this is going to be schema factory from Nestjs Mongoose dot create for class and then pass in the

09:57.520 --> 09:59.830
reservation document that we just created.

10:00.030 --> 10:02.210
And you'll see where we use this soon enough.

10:02.220 --> 10:06.840
So back in the reservations repository, there's a bit more work we have to do.

10:06.870 --> 10:16.500
We need to actually create this protected read only logger and set it to new logger from Nestjs common.

10:16.500 --> 10:21.950
And we can pass in the name of the repository here to give it some context.

10:21.960 --> 10:26.970
So now that we have that logger that the abstract repository can actually use, we need to define a

10:26.970 --> 10:34.350
constructor here where we actually inject the model from Mongoose, which of course we know the abstract

10:34.350 --> 10:40.440
repository will need to actually use and manipulate the documents.

10:40.440 --> 10:49.170
So in order to get this, we need to call at inject model from Nestjs Mongoose and then pass in an injection

10:49.170 --> 10:52.110
token that we will soon define.

10:52.560 --> 10:59.160
So we're going to choose the reservation document.name as the token here, and then we can call this

10:59.160 --> 11:05.260
variable reservation model which will be set to model from Mongoose.

11:05.780 --> 11:08.960
And then pass in the reservation document.

11:09.080 --> 11:15.440
So now all we have to do to give this to the abstract repository is called super here and then pass

11:15.440 --> 11:17.420
in the reservation model.

11:17.450 --> 11:22.610
Now finally, we can go back to our reservations module here and for our providers array, we're going

11:22.610 --> 11:26.310
to pass in the newly created reservations repository.

11:26.330 --> 11:29.220
So we can actually inject it in our application.

11:29.240 --> 11:34.880
Now if we go back to our terminal where our app is running, you can see that it's complaining that

11:34.880 --> 11:39.500
it can't resolve the dependencies of the reservations repository.

11:39.560 --> 11:44.810
So it's essentially saying that it doesn't recognize the reservation document model we're trying to

11:44.810 --> 11:45.490
inject.

11:45.500 --> 11:51.380
And the reason for this is that we haven't actually told Mongoose about this schema here.

11:51.410 --> 11:55.550
Now, in order to accomplish this, we'll go back to our Libs common folder.

11:55.550 --> 12:03.980
In the database module, we're going to add a new static method here called Static for feature.

12:03.980 --> 12:12.120
And this is going to take a variable here called models, which will be a model definition from Nestjs

12:12.120 --> 12:13.680
Mongoose array.

12:13.680 --> 12:23.970
And all we're going to do in here is return Mongoose module dot for feature where we pass in these models.

12:23.970 --> 12:31.170
And so we're just abstracting this schema initialization process away from the implementation.

12:31.170 --> 12:34.230
In this case, it'll be our reservations module.

12:34.410 --> 12:41.700
So to actually use this, we'll just call database module for feature and pass in an array of schemas

12:41.700 --> 12:42.090
here.

12:42.090 --> 12:48.480
In our case we only have the one, so it's a single object where we provide the name and this name is

12:48.480 --> 12:52.440
the injection token that we use to inject this model.

12:52.440 --> 12:58.290
And of course, if you remember in our reservations repository, this was the name of the reservations

12:58.290 --> 12:59.130
document.

12:59.670 --> 13:06.930
So we'll provide that name here by calling reservation document.name, and then finally, we need to

13:06.930 --> 13:09.030
provide the actual schema.

13:09.030 --> 13:16.440
And in this case, this is going to be the reservation schema that we created in our reservation schema

13:16.440 --> 13:17.310
file here.

13:17.340 --> 13:19.980
This create for class variable.

13:19.980 --> 13:24.390
So now if we go back to our terminal, we can see the app starts up successfully now.

13:24.750 --> 13:31.890
And now finally we can go back to our reservations service and actually add a constructor here and finally

13:31.890 --> 13:37.110
inject the read only reservations repository.

13:37.900 --> 13:41.050
Of type reservations repository.

13:41.320 --> 13:47.320
And now we can finally use this repository to fill out these CRUD methods and actually persist data

13:47.320 --> 13:49.090
to our MongoDB database.

13:49.090 --> 13:52.870
So in the create function here, instead of returning the string.

13:52.960 --> 14:00.610
We'll return this dot reservations repository, dot, create and pass in this DTO.

14:00.790 --> 14:06.280
Now this is going to complain because of our type checking that the Create reservation DTO is missing

14:06.280 --> 14:10.120
a number of properties that exist on the reservation schema.

14:10.450 --> 14:16.720
So let's go ahead and take a look at the reservation DTO, which by default is empty here.

14:16.930 --> 14:23.350
So let's go back to the schema itself and we can just copy all of these properties and paste them into

14:23.350 --> 14:24.370
the DTO.

14:24.730 --> 14:30.250
Now we're not going to need the time stamp from the user because we'll generate that on the server.

14:30.280 --> 14:35.020
We'll keep the start date and end date and get rid of the property keys here.

14:35.020 --> 14:37.570
I'm also going to get rid of the user ID.

14:37.570 --> 14:43.870
This is going to come off of the JSON web token that the user will provide for authentication once we

14:43.870 --> 14:44.830
implement that.

14:45.220 --> 14:50.440
So we can just leave it empty for now and we'll hardcode it and then finally we'll have the place and

14:50.440 --> 14:51.340
invoice ID.

14:51.670 --> 14:58.960
So now back in the reservation service, instead of passing in the DTO, we can spread the DTO and then

14:58.960 --> 15:01.810
provide the time stamp as a new date.

15:02.080 --> 15:08.440
And then the user ID, like I said, will be coming off of the JSON web token that the user will eventually

15:08.440 --> 15:09.460
provide for.

15:09.460 --> 15:12.130
Now we'll just hard code this to one, two, three.

15:12.550 --> 15:17.680
So now that our create function is done, we can fill out the find all pretty easily.

15:17.710 --> 15:26.800
We'll just return this dot reservations repository dot find and pass in an empty filter here to get

15:26.800 --> 15:27.730
all the documents.

15:27.850 --> 15:33.070
Find one here we can call this dot reservations repository dot find one.

15:33.280 --> 15:36.940
So by default the ID passed in is a number from Nestjs.

15:36.970 --> 15:42.020
However, there should be a type string which matches our underscore ID.

15:42.260 --> 15:50.090
So now for our find one for our underscore ID, we'll just pass in the ID field here and we can change

15:50.090 --> 15:55.100
the name to underscore ID So now we can find a reservation by its ID.

15:55.430 --> 15:57.710
Now an update will do something similar.

15:57.710 --> 16:00.710
We'll change this to underscore ID of type string.

16:01.310 --> 16:05.960
And we will return this dot reservations repository.

16:05.990 --> 16:07.990
Find one and update.

16:08.000 --> 16:12.230
So our filter query here will be for the underscore ID.

16:12.500 --> 16:15.860
Then for the second argument, we'll actually provide the update itself.

16:15.890 --> 16:22.250
In this case I want to use the dollar sign set property here which will allow us to override existing

16:22.250 --> 16:24.350
properties on this document.

16:24.350 --> 16:32.000
So now we can actually provide the update reservation DTO, which could potentially contain anything

16:32.000 --> 16:34.520
that already exists on the Create Reservation.

16:34.520 --> 16:38.510
DTO because we're extending it here as a partial type.

16:38.510 --> 16:43.820
And finally, for remove here, we can change this to a string as well.

16:44.120 --> 16:51.860
The underscore ID and call this dot reservations repository dot find one and delete where we just pass

16:51.860 --> 16:53.360
in the underscore ID.

16:53.660 --> 17:00.050
Now lastly, back in our reservations controller here, all we have to do is just get rid of the plus

17:00.050 --> 17:01.590
for the ID here.

17:01.590 --> 17:06.750
So that keeps TypeScript happy and we can see we have no errors in our terminal, so we're ready to

17:06.750 --> 17:08.790
test out our new API.

17:08.820 --> 17:16.920
And I'm in Postman here and I've have the URL set to localhost 3000 slash reservations where if you

17:16.920 --> 17:20.610
remember this is where we defined this controller to live on.

17:20.610 --> 17:22.560
So we're going to test each of these routes off.

17:22.560 --> 17:29.700
First will be the post call to actually create the reservation and we pass in a JSON body here with

17:29.700 --> 17:31.290
all of these properties.

17:31.290 --> 17:35.070
So we have the start date, end date, place ID and invoice ID.

17:35.400 --> 17:43.620
So if I execute this post request, you can see we get a 201 created response back and we get the newly

17:43.620 --> 17:46.320
created document back with all of our information.

17:46.740 --> 17:54.330
Next, let's actually try to get all of the reservations with this get find all So we'll call get.

17:55.290 --> 17:58.770
And you can see I have an array of reservations I've created.

17:58.800 --> 18:04.650
I've created this one twice so we can see it created both times here and back and back in this array

18:04.650 --> 18:06.720
at two response 200.

18:06.810 --> 18:16.110
And now to test out our find one route here we will provide the actual ID as part of the route and you

18:16.110 --> 18:19.560
can see we extract that id using the params decorator.

18:19.560 --> 18:25.020
So we're going to take an ID of one of these documents here and add it to the route here.

18:25.020 --> 18:30.930
So now if we get this single document, we can see it's pulling back that single document based on the

18:30.930 --> 18:32.010
ID we provide.

18:32.010 --> 18:39.450
Next, let's try to update a single reservation using the patch route where we have the ID and then

18:39.450 --> 18:43.320
the update command so we can go back here.

18:43.350 --> 18:51.120
We can keep this existing ID, change this to patch, and now I'm just going to change the start date

18:51.120 --> 18:52.020
only.

18:52.020 --> 18:56.670
I'm going to say it starts on the 22nd here instead of the 20th.

18:56.670 --> 19:02.310
And if we send this off and now you can see the start date is changed to the 22nd.

19:02.340 --> 19:08.250
If I launch a get request for this reservation, again, you can see our newly updated start date.

19:08.250 --> 19:09.960
So Patch is working great.

19:09.960 --> 19:16.440
And then finally for delete we provide the ID as a parameter as well.

19:16.440 --> 19:25.140
So let's try this out by calling delete route on this reservation and it has succeeded with 200.

19:25.170 --> 19:25.710
Okay.

19:25.740 --> 19:32.340
So now if we run a get for this reservation, we should expect to see we get that 404 that's part of

19:32.340 --> 19:34.980
a repository where we throw this error.

19:34.980 --> 19:40.710
If it's not found, which is exactly what we'd expect to see because this reservation no longer exists.

19:40.710 --> 19:44.100
So in this lecture we've implemented full CRUD functionality.

19:44.130 --> 19:47.370
However, one thing I want to add right now is validation.

19:47.370 --> 19:54.540
Right now, if I try to send a post request to create a new reservation, I can just provide total garbage.

19:54.540 --> 20:01.620
I can say the start date is 32 and we don't provide any other properties.

20:01.620 --> 20:06.060
If I send this request off to the database, it actually succeeds.

20:06.060 --> 20:11.580
And you can see here that the document gets created without some very important properties.

20:11.580 --> 20:13.260
And this is not what we want.

20:13.290 --> 20:19.850
We want to provide some validation so that the user can't just give us whatever they want to our server.

20:19.860 --> 20:22.080
Let's implement this in the next lecture.
