Created
September 7, 2022 14:14
-
-
Save josephdpurcell/fc04cfd428a6ee9d7ffb64685e4fe3a6 to your computer and use it in GitHub Desktop.
Get ArgumentMetadata in NestJS createParamDecorator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ArgumentMetadata, createParamDecorator, ExecutionContext } from '@nestjs/common'; | |
import { METADATA__PARAM_TYPE } from '../constants'; // METADATA__PARAM_TYPE = 'myType' | |
import { paramTypeEnhancer } from './param-type.enhancer'; | |
export const MyDecorator = createParamDecorator( | |
async (data: unknown, ctx: ExecutionContext): Promise<any> => { | |
const metatype = Reflect.getOwnMetadata(METADATA__PARAM_TYPE, ctx.getHandler()); | |
// We build the argument metadata that @nestjs/class-validator is expecting. | |
// Specifically, we specify the type as "custom" -- this is a special value | |
// coming from NestJS and all custom decorators are "custom". The data is | |
// left undefined (only a @Query or @Param type would have data). Last, the | |
// metatype is the reference to the type. | |
const argument: ArgumentMetadata = { | |
type: 'custom', | |
data: undefined, | |
metatype: metatype, | |
}; | |
// Do processing here. You can even return a promise. | |
// Often you want access to the request which can be done like this: | |
const request = ctx.switchToHttp().getRequest(); | |
}, | |
[paramTypeEnhancer], | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ParamDecoratorEnhancer } from '@nestjs/common'; | |
import { METADATA__PARAM_TYPE } from '../constants'; // METADATA__PARAM_TYPE = 'myType' | |
/** | |
* This enhancer grabs the Typescript type of the parameter and shoves it into | |
* the metadata. We do this because the CustomParamFactory does not have access | |
* to the type of param. | |
*/ | |
export const paramTypeEnhancer: ParamDecoratorEnhancer = ( | |
target: Record<string, unknown>, | |
propertyKey: string, | |
parameterIndex: number, | |
): void => { | |
// Typescript adds the "design:paramtypes" metadata with an array of class | |
// types where the keys are the method argument index and the value is the | |
// class type. | |
const paramTypes = Reflect.getOwnMetadata('design:paramtypes', target, propertyKey); | |
// We can use the parameterIndex to retrieve the specific type we want. | |
const metatype = paramTypes[parameterIndex]; | |
// Now, we assign the parameter type to the metadata at a key we know. | |
Reflect.defineMetadata(METADATA__PARAM_TYPE, metatype, target[propertyKey]); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment