WEBVTT

00:00.080 --> 00:08.060
Let's go ahead and now define a new Prisma folder, which is where we're going to host our schema.prisma

00:08.060 --> 00:14.330
file, which is again the database schema for this service and the source of truth for our schema.

00:14.690 --> 00:21.050
This is also the default location that the Prisma CLI will look for for any database migrations.

00:21.050 --> 00:24.050
So we're going to keep all of that code in the Prisma folder.

00:24.080 --> 00:29.060
Now let's go ahead and define firstly the generator client.

00:29.060 --> 00:34.610
So this is going to define the actual client library that we're utilizing in our code.

00:34.610 --> 00:41.210
And the client that Prisma will call when it needs to generate types based off of the schema that we

00:41.210 --> 00:42.140
defined here.

00:42.140 --> 00:45.050
So we provide the provider key here.

00:45.050 --> 00:50.510
And note I do have syntax highlighting available for this Prisma file.

00:50.510 --> 00:56.240
This is because I have a extension called Prisma in VS code.

00:56.240 --> 01:01.520
So simply install this extension if you want this syntax highlighting which tells you when your schema

01:01.520 --> 01:03.920
is an error and why it's an error.

01:03.920 --> 01:06.620
So you can see here it's looking for the provider.

01:06.620 --> 01:11.600
And the provider is going to be the client library name we're using.

01:11.960 --> 01:16.130
And that's going to be Prisma client JS.

01:16.130 --> 01:19.550
So typically this would be a complete client definition here.

01:19.550 --> 01:24.650
And this is all we would need to generate client types in a simple project.

01:24.650 --> 01:30.410
However our setup is going to be a little bit different because we're running in this mono repo.

01:30.410 --> 01:36.590
And remember we're going to actually be generating these types in our Docker container when we're running

01:36.590 --> 01:40.190
in production, which is actually a different runtime, right?

01:40.190 --> 01:47.750
Our Docker image is based off of Node Alpine, which in my case is obviously a different runtime.

01:47.750 --> 01:51.980
I'm running on Mac OS and this is going to be in Linux.

01:51.980 --> 01:59.180
So we need to do a couple of things to get our client types generated properly in all environments.

01:59.180 --> 02:05.510
The first is going to be defining a custom output path to where our client types are going to be generated

02:05.510 --> 02:06.020
to.

02:06.050 --> 02:12.110
Now, by default, the client types that Prisma generates here are going to be generated in the root

02:12.110 --> 02:14.630
node modules of our application.

02:14.630 --> 02:16.160
However, we don't want this.

02:16.160 --> 02:23.390
We want these client types to go into our reservations node modules and then our code to utilize just

02:23.390 --> 02:27.440
the client types for reservations and not our other services.

02:27.440 --> 02:32.810
So we're going to tell Prisma client to generate these types to the node modules.

02:32.810 --> 02:36.920
One directory up which is going to be in the reservation service.

02:37.010 --> 02:44.360
And then we have to define a custom Prisma client path, which is not going to be at Prisma slash client.

02:44.360 --> 02:48.650
Instead it's going to be Dot Prisma client.

02:48.650 --> 02:54.230
And this is going to be key for our code to be able to reference Prisma client in the correct place.

02:54.230 --> 02:56.840
We need to use this dot here.

02:57.200 --> 03:01.820
So now we're going to be generating these types to just our reservation service.

03:01.820 --> 03:06.470
The final step is to input a binary targets array.

03:06.470 --> 03:12.950
And this is going to be and this is going to be the engine binary targets for Prisma client JS.

03:12.950 --> 03:17.990
So typically if you're just running on Windows or Mac you'll have no issues.

03:17.990 --> 03:23.870
You don't need to specify this, but in our case we want to generate binary targets for both our native

03:23.870 --> 03:26.900
runtime where we're actually running locally.

03:26.900 --> 03:29.330
So in my case Mac I'll use native.

03:29.330 --> 03:34.550
So we still generate a binary for our local development, which is going to be key when we're developing

03:34.550 --> 03:35.300
locally.

03:35.300 --> 03:41.960
But also we need to specify the binary target for this alpine image, where we know our code is actually

03:41.960 --> 03:43.190
going to be running in.

03:43.190 --> 03:48.170
To do this, we need to specify Linux muscle.

03:48.940 --> 03:54.250
Open SSL dash 3.0. x.

03:54.250 --> 04:02.350
And this is going to specify the correct binary target engine for Prisma client JS to generate our types

04:02.350 --> 04:03.040
against.

04:03.040 --> 04:08.350
So now our client is ready to generate the correct types for both of our runtimes.

04:08.350 --> 04:11.080
And it's going to generate them to the correct place.

04:11.080 --> 04:15.520
Let's go ahead and now define the data source DB.

04:15.910 --> 04:21.880
And this is going to be the actual database connection details for how Prisma client will connect to

04:21.880 --> 04:22.990
the database.

04:23.260 --> 04:27.640
So we have a provider here to give it the actual database we're using.

04:27.640 --> 04:30.250
We can see all the different types it supports.

04:30.250 --> 04:38.170
We're going to choose Postgres SQL and then provide a URL, which is going to be how we connect to the

04:38.170 --> 04:39.190
database.

04:39.190 --> 04:46.600
So we can call the M function here to actually read in an environment variable using the dot env library,

04:46.600 --> 04:50.710
which we already know we have available thanks to nest config.

04:51.040 --> 04:53.950
So we need to pull off the environment variable.

04:53.950 --> 04:56.500
I'll use database URL here.

04:56.500 --> 05:01.990
So we'll make sure we have this environment variable both when we're running our app and generating

05:01.990 --> 05:04.060
migrations later on.

05:04.060 --> 05:10.450
Let's go ahead and finish completing our schema first by defining our actual database schema.

05:10.480 --> 05:14.950
Now which is going to represent the tables inside of our database.

05:14.950 --> 05:21.970
So firstly we can define a new table with the model which is going to be the name of the table.

05:21.970 --> 05:25.180
And it's going to map to a TypeScript entity.

05:25.180 --> 05:28.330
So we're going to have a model called reservation.

05:28.330 --> 05:32.140
So now we need to find the properties on this reservation.

05:32.140 --> 05:35.380
And that's going to map to the columns on the database table.

05:35.380 --> 05:40.150
So firstly I'll have an ID and that's going to uniquely identify the reservation.

05:40.150 --> 05:41.980
It's going to be our primary key.

05:41.980 --> 05:46.450
And it will have a index on it automatically then.

05:46.450 --> 05:50.530
So we can specify this is going to be an integer.

05:50.620 --> 05:55.840
And then we can also specify a default value for it using at default.

05:55.840 --> 06:03.490
And then we can call auto increment to have this value automatically increase every time a new entity

06:03.490 --> 06:08.230
is inserted into the database, so we don't actually have to set it ourselves.

06:08.530 --> 06:13.810
Finally, we can mark it as the primary key, which is going to have a unique index applied to it,

06:13.810 --> 06:21.370
meaning we can't have two of the same reservations with the same ID by using the ad ID decorator here.

06:21.820 --> 06:22.330
All right.

06:22.330 --> 06:27.280
So let's go ahead and include the rest of the properties on a reservation that we know we have.

06:27.280 --> 06:34.000
So we have a timestamp which is when the reservation is created I'll have this as type date time in

06:34.000 --> 06:35.020
the database.

06:35.990 --> 06:44.120
Then we have start date, another date time, and finally we have end date of date time.

06:44.420 --> 06:45.650
And just crack this.

06:45.650 --> 06:47.990
This should be start date here.

06:48.560 --> 06:54.860
And now we have the user ID that's associated with this reservation that will be of type integer.

06:55.400 --> 06:59.990
And finally we have the invoice ID of type string.

07:00.110 --> 07:03.230
So now we have modeled our actual data.

07:03.230 --> 07:06.260
And these are all the properties on a given reservation.

07:06.260 --> 07:10.370
This is going to be the table in Postgres with all of the columns.

07:10.370 --> 07:17.870
And now what we can do is actually generate a Prisma migration based off of this schema in its current

07:17.870 --> 07:24.350
state to get our databases schema that we know is running locally in line with this definition here.

07:24.350 --> 07:31.550
Now, to be able to run this migration, I'm going to go ahead and add a new command to our package.json

07:31.550 --> 07:37.400
in reservations, since this command will need to follow a couple of steps.

07:37.400 --> 07:40.550
Let's go ahead and add a new script for it.

07:40.550 --> 07:44.360
So in our package.json I'll have a new migrate script here.

07:44.360 --> 07:51.680
Now the first thing we need to do before executing our database migration is actually specify the database

07:51.680 --> 07:52.550
URL.

07:52.730 --> 08:00.050
Now, as I said before, by default Prisma is going to look for this database URL using the dot env

08:00.050 --> 08:05.720
library, which we know is going to look at the dot env here by default.

08:05.720 --> 08:13.580
Now I want to specify a different dot m file for the dot env library to look for when we execute this

08:13.580 --> 08:16.910
migration, and we look for this database URL.

08:16.910 --> 08:23.900
Now the reason why this is, is because I want to keep this dot m file for our running Docker container.

08:23.930 --> 08:29.690
Now the reason why this is, is because the connection string to our Postgres database is going to be

08:29.690 --> 08:38.270
different when we're running locally on our machine here versus when we're inside of Docker and utilizing

08:38.270 --> 08:39.320
this dot env.

08:39.320 --> 08:46.070
And that's because we know when our container is running inside of Docker using Docker compose.

08:46.070 --> 08:53.660
We access this Postgres database here using this host name here in Docker networking the Postgres host

08:53.660 --> 08:54.290
name.

08:54.290 --> 09:00.410
However, locally, when I just simply want to execute a migration without running in Docker, well,

09:00.410 --> 09:06.650
we know the address to Postgres will be at local host, the same that we've already supplied to pgadmin.

09:06.650 --> 09:11.540
So we're going to have two different connection strings to our database depending on where we're running

09:11.540 --> 09:13.250
locally or in Docker.

09:13.250 --> 09:18.650
So what I want to do is create a new dot m dot local to keep these two separate.

09:18.650 --> 09:22.430
Now let's go to go ahead and specify this database URL.

09:22.430 --> 09:31.940
So this is going to be PostgreSQL colon slash slash Postgres which is going to be the username and then

09:31.940 --> 09:32.630
the password.

09:32.630 --> 09:37.490
So that's the same here as we know at the host name of the database.

09:37.490 --> 09:40.310
So again that's localhost we're running locally.

09:40.310 --> 09:46.940
And we want to access the Docker container running on port 5432 where we're forwarding traffic to.

09:47.060 --> 09:52.820
And then finally the database name we're connecting to that'll be slash reservations.

09:52.820 --> 09:57.950
So now we have this database URL we can use when we're running migrations locally.

09:58.070 --> 10:00.560
Let's go ahead and back to our package.json.

10:00.560 --> 10:08.150
Now where we want to utilize this dot m cli library that we installed earlier to now write our migrate

10:08.150 --> 10:15.920
command so we can actually tell em where to look for for the dot m file using the dot m CLI.

10:15.950 --> 10:22.160
Now we can just say dot m dash e, which is going to be the environment file we now want.

10:22.160 --> 10:24.740
In our case that's dot m dot local.

10:25.070 --> 10:28.250
So now we have the correct database URL loaded in.

10:28.250 --> 10:32.810
We can now execute the actual Prisma command to migrate the database.

10:32.810 --> 10:36.440
And that will be using the correct dot m dot local.

10:36.440 --> 10:45.710
So we can simply run now npm prisma to execute the prisma cli based off of the dependency we have here.

10:45.710 --> 10:47.870
Migrate dev.

10:47.870 --> 10:54.950
Now dev is a special argument to the migrate command, which is going to actually generate the migration

10:54.950 --> 11:01.820
file for us in source code in the Prisma directory, so that we keep a running history of all of our

11:01.820 --> 11:07.700
migrations, which is going to be key when we run our app in production, we want to actually apply

11:07.700 --> 11:14.030
any new migrations against the database to always ensure that our database is in line with our schema.

11:14.030 --> 11:22.070
So now we can go ahead and test this command out by running npm run migrate.

11:22.100 --> 11:29.600
Now we can see the prisma cli here has connected to our database running locally, just as we'd expect.

11:29.600 --> 11:34.910
And it's asking us for a name for our migration because it's going to generate this migration file.

11:35.030 --> 11:35.480
I'll.

11:35.840 --> 11:38.360
So I'll call it reservation.

11:38.870 --> 11:44.780
Now we can see here it's applied this new migration file against our database and actually saved it

11:44.780 --> 11:45.890
to source code.

11:45.890 --> 11:51.530
And it has executed it and told us that our database is now in sync with our schema.

11:51.560 --> 11:58.010
Lastly, it's actually generated the Prisma client types to the correct folder that we've told it to

11:58.040 --> 12:01.640
here in our reservations folder, which is excellent.

12:02.030 --> 12:04.160
So let's go ahead and verify this.

12:04.190 --> 12:11.270
Firstly I'll refresh my databases and you can see I now have a reservations database created.

12:11.300 --> 12:14.210
I'll open up schemas tables.

12:14.210 --> 12:18.530
And now we can see the reservation table as we'd expect.

12:18.560 --> 12:20.330
I can right click it.

12:20.330 --> 12:22.820
Let's view all rows.

12:22.820 --> 12:24.770
So we have no data right now.

12:24.770 --> 12:31.400
But we can see all of the properties on the reservation we defined here as table columns.

12:31.400 --> 12:32.870
So this is excellent.

12:33.260 --> 12:36.320
Lastly let's take a look at the source code now.

12:36.320 --> 12:42.860
So if we look inside of reservations Prisma we see we have the new migrations folder here.

12:42.860 --> 12:51.050
And we have this new migration script that is the actual SQL that Prisma generated against the database.

12:51.050 --> 12:55.460
And this is going to be key because now we have a running history of all of the migrations.

12:55.460 --> 12:59.060
We need to keep our database in line with the schema.

12:59.060 --> 13:04.130
We can apply this SQL against any database running in production.

13:04.130 --> 13:07.700
When we start our app up to always ensure they're in line.

13:08.000 --> 13:14.210
Next up, let's go ahead and utilize these new Prisma client types that it has generated for us and

13:14.210 --> 13:19.070
start refactoring our code to utilize Prisma instead of MongoDB.
