If you're looking to streamline the process of discovering metadata on your handlers or Injectable classes, I've created a reusable module designed specifically for this purpose. By utilizing @nestjs-plus/common
from NPM and leveraging the DiscoveryService
, you can automatically retrieve all relevant handlers or classes based on a MetaData token of your choosing. The source code for this module can be found on Github. I will be updating the documentation in the near future, but there are already numerous examples available in the repository.
Underneath it all, the module utilizes the MetaDataScanner but presents a user-friendly API for ease of use. This could potentially reduce a significant amount of boilerplate in your specific use case, as demonstrated in examples within the @nestjs-plus/rabbitmq
module (also located in the same repository). These examples showcase how you can effectively utilize this functionality to enhance advanced features.
EDIT:
I have recently updated the library to also support scenarios involving the discovery of controllers and controller methods. You can explore a comprehensive test suite that mirrors your setup using the @Roles
decorator by following this link. After including the DiscoveryModule
in your imports and injecting the DiscoverService
, you can easily find all controller methods using the simplified
methodsAndControllerMethodsWithMeta
API.
// Inject the service
constructor(private readonly discover: DiscoveryService) { }
// Discover all controller methods decorated with guest roles or
// belonging to controllers with guest roles
const allMethods = this.discover.methodsAndControllerMethodsWithMeta<string[]>(
rolesMetaKey,
x => x.includes('guest')
);
Once you have retrieved all the desired methods, you have the flexibility to manipulate them as needed—such as creating a collection based on their RequestMethod
and path
.
const fullPaths = allGuestMethods.map(x => {
const controllerPath = Reflect.getMetadata(
PATH_METADATA,
x.component.metatype
);
const methodPath = Reflect.getMetadata(PATH_METADATA, x.handler);
const methodHttpVerb = Reflect.getMetadata(
METHOD_METADATA,
x.handler
);
return {
verb: methodHttpVerb,
path: `${controllerPath}/${methodPath}`
}
});
This would output results similar to those shown in the linked test suite:
expect(fullPaths).toContainEqual({verb: RequestMethod.GET, path: 'guest/route-path-one'});
expect(fullPaths).toContainEqual({verb: RequestMethod.GET, path: 'super/route-path-two'});
expect(fullPaths).toContainEqual({verb: RequestMethod.POST, path: 'admin/route-path-three'});
I welcome any feedback or insights regarding this approach/API.