Okay, so now that we've generated the proto definitions for our services, let's go ahead and utilize
Proto to generate the TypeScript code.
We need to integrate it easily within our Nestjs app.
So the command we'll run will be proto C dash dash plugin equal to and then we'll give it the path to
our plugin.
So this will be in node modules, slash bin slash proto c dash gen dash ts underscore proto.
Then we'll specify where we want to generate the TypeScript code to by using the ts, underscore proto
out option.
And I'll just leave this equal to dot slash for the relative path.
And then finally we'll use dash dash ts underscore proto underscore opt equal to nestjs equal to true,
which is going to generate nestjs specific code for us.
Now let's specify the path to our proto file.
In this case it will be dot slash proto and then we'll start off with the auth dot Pro.
Now let's go ahead and run the same command and just swap out the path for the payments proto now and
finally we'll rerun it for the notifications proto.
So now if we go back to our project and open up the proto folder, we can see we have three new definition.
We have three new files created, one for each proto.
And if we look inside, we can see all of the interfaces.
And if we look inside, we can see all of this TypeScript code that has been generated for us based
off of the proto file that we created.
So in the arts we can see we have interfaces defined for each of the different message types that we
created in our orthophoto.
We also have interfaces for the client that will be calling our auth service and the controller that
will actually be implementing the auth service.
So this is going to make it very easy for us to write clean consistent code that is always in line with
our proto definition.
Now finally we have this function called auth service controller methods and this is actually a decorator
that we're going to be able to apply to our auth controller and all of the necessary metadata is going
to be automatically applied to our methods automatically so that when a message is sent to our service,
Nestjs will automatically know which method it should be sent to.
So this will all be taken care of for us under the hood thanks to Proto.
So next up let's go to the libs Source comm and folder.
And in here I want to create a new folder called Types.
So I've created this new types folder and I want to move all of the newly generated types into this
folder.
So let's move each of these files into the types folder.
And then we'll create an index.ts where we can export everything from each of these files so that we
can use it in our application.
So let's go ahead and do that.
Now you'll notice the compiler is complaining because we have some duplicated exports coming from these
files.
And this is actually coming from this const called Protobuf package.
Now, we're actually not going to be utilizing this constant in our app so we can just go ahead and
delete this altogether.
Let's go ahead and delete it from each definition.
So now that we've done that, I'll go to the root index.ts and export everything from the types folder.
Next, let's go to our DTO folder where we can open up our Create charge DTO.
Now, you may have been wondering why we had to duplicate our message types in our gRPC proto definitions.
For example, the create charge message has all the same properties on it besides the email as the create
charge.
DTO So why did we have to even duplicate this in the first place?
Well, the answer is because of the class validator metadata on the DTOs.
We still want our DTOs coming into our system to be validated using class validator and we can still
make this happen using gRPC.
However, we need DTOs with these decorators still applied.
So in order to make sure that our DTOs are always matching up with the message types that are generated,
which are really the source of truth for our data, we want to actually implement those interfaces.
So let's go ahead and do that.
We can say the create charge DTO will actually implement the create charge message from the types folder
and we can go to the card DTO and do the same thing here.
We're going to say that the card DTO will implement the card message.
So this means that if our gRPC proto definitions ever change and we regenerate these types, we'll know
right away if we have to update our DTOs as well and prevent any runtime errors.
Now of course we can see it's complaining because we still are using underscores in our DTO.
Let's go ahead and refactor this to use camel casing and we'll make sure that we translate this back
later on in our service layer.
Now in the Create Charge, DTO, we of course, we don't want to actually specify the email here in
the common DTO because this is only applicable in our payments.
Create charge DTO.
So to specify this we can use the omit keyword that will allow us to omit any properties from a type.
We just need to specify it here.
So we'll say we want to implement the create charge message except for the email property and now we
are type safe.
So now that we've updated our DTOs, let's go to our JWT auth guard in our common source auth folder.
Well, we'll refactor this to now use gRPC.
So the first thing we'll do is make sure we're actually implementing on module init from Nestjs common.
Then we'll make sure we'll change the injection token to be auth service name from types.
And this is simply a constant that's exported from our OTS and this is going to be the injection token
we'll use later on in the clients module when we set up this service in our corresponding module.
So for now, let's make sure we match the injection token here.
And then we'll go ahead and change the name of the variable to a client, because the type here will
also change to be a client.
gRPC from Nestjs Microservices.
So this is a little different than before.
We actually need to set the service that we want in the on module init method now.
So let's implement on module init.
And now in here we want to set our auth service.
So let's go ahead and declare a class variable called private auth service.
And this is type is going to be the auth service client that we saw earlier.
So we can see that this is the auth service client from TS which is going to have access to all of the
RPC methods in our auth Proto in this case the authenticate method.
So now an on module init, let's go ahead and set the auth service equal to this Dot client.
Dot get service and will provide the auth service.
Client type.
And then we provide the name of the service.
So in our case, this is going to be the auth service name that we've already used.
Now you might be wondering where this is coming from.
Well, this name of the auth service directly corresponds with the name of the auth service that we
define in our auth Proto.
So the auth service name here corresponds to the service that we're asking for.
And this is also the same exact name of our injection token.
So now that we've correctly set our auth service, let's go ahead and refactor our call to actually
use it.
We're going to be calling this off service.
And now we can directly call authenticate on it as if it was a local in-process method.
And the fact that it's an RPC call is completely abstracted away from us.
So we'll call authenticate and then we need to pass in the request message, which is going to be the
same exact object we're currently sending.
So let's just go ahead and remove the dot send.
And we'll keep this object that we are sending, which is the authentication property which contains
the JWT.
Now, one final change we're going to make is that when we get the response back from the auth service,
we actually want to set this equal to an object where we'll go ahead and spread all of the properties
from the response, which we know is the user.
However, now we want to make sure we explicitly set the underscore ID equal to response.id.
So you can see here we have all of the properties coming back from the user.
But remember in gRPC we can't use underscores, so we need to map the ID property from the user message
to the underscore ID that the rest of our application expects.
And now I'll just go up and remove all of the unused imports that we're no longer utilizing anymore.