Discovery service
A way to append decorators during system startup.
This improvement will be an opportunity to learn about a very interesting and useful tool. We could make that all non-public routes receive the @ApiUnauthorizedResponse()
decorator, which indicates that a route may return a response with the UNAUTHORIZED status. The same could be thought about the routes that require roles, and the @ApiForbiddenResponse()
decorator. To achieve this, we can leverage the DiscoveryService
, which allows for accessing references to all controllers and providers during system startup, which is quite useful for appending dynamic decorators, for instance. Let's then begin.
First, let's create a module to encapsule these documentation mappers.
Then, let's create a class for the Unauthorized mapper.
Please perform the following:
Alter the filename to end in .mapper
Add
@Injectable()
, so that it can be accessed by the Nest IoC container
Now, in the module, we should add this mapper to the providers
, and the DiscoveryModule
to the imports
, in order to use the DiscoveryService
.
The next step is to, back in the class, make it implement the OnApplicationBootstrap
interface. This forces the class to implement the namesake method, which executes when the app is starting. Now, the first step in this method will be to obtain a reference to the controllers
by using the DiscoveryService
, which we also should inject now.
We'll then iterate over each controller. Notice that they were returned inside wrappers.
Next, we'll obtain the instance
from inside each wrapper
, and then obtain the prototype
from the instance
. This will be necessary afterwards.
Some parts now will be a bit familiar. We should then use a reflector
to get the isPublic metadata from the controller itself. Here we have no access to the context
like we did inside the guards, so we should pass instance.constructor
. If the controller is public, simply return.
After that, we'll get the names of the controller's route handlers by using the metadataScanner
(also to be injected). This can be achieved using the prototype
. Sequentially, we may obtain references to the actual route handlers by accessing these names inside the controller instance
.
Nearing the end, we'll now iterate over each route
.
The same process will now be performed with each handler: if it's public, simply return.
Finally, to append this decorator to the route, use it without @, and use a second pair of parentheses, passing the route
.
And we're done! Now these routes will be automatically decorated for us.
Commit - Using discovery service to automatically document routes
Let's now create the Forbidden mapper. Please repeat the aforementioned procedure, and I'll detail then what will be different.
In this case, we'll check if the controller is protected, that is, if it requires roles.
If it is, all its routes will be marked with the decorator and this iteration ends.
If not, we'll then check each handler, and it won't be marked if it's not protected.
We have now covered both cases with dynamic documentation. Outstanding!
Commit - Documenting forbidden routes automatically
Last updated