Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Selfmade method decorator erasing all metadata, how I can resolve it?

Im using NestJS and nestjs/swagger module for simple api documentation, but I have trouble because I need validate Response from my service.

Thats why I create my selfmade method decorator, but I have big trouble, when I using it - all metadata from another decoratos is loosing and swagger module cant show good documentation.

Code of my decorator

export function validate(classValidatorEntity: any): MethodDecorator {
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
    const origMethod = descriptor.value;
    descriptor.value = async function() {
      const result = await origMethod.apply(this, arguments);
      console.log(result); // validationFunc(result) in original method
      return result;
    };
  };
}

and example of code of some controller method

  @Post('test')
  @ApiOkResponse({
    type: someResDto
  })
  @ResponseValidator(ActualizeFlightQueueResponseDto)
  public async test(@Body() body: someReqDto): Promise<someResDto> {
    return {result: true}
  }

If my decorator in the top (first) - all metadata is loosing. If my daecorator is last - I loosing data from @Body() decorator....

I dont know what to do, and how i need to rewrite my own decorator.

like image 552
painfull_coder Avatar asked Jan 21 '26 09:01

painfull_coder


1 Answers

Metadata is associated to the specific descriptor.value, you have to re-apply metadata associated from the origMethod to the new descriptor.value

First define a metadata copyMetadata method

const copyMetadata = (source: Object, target: Object): void => {
  for (const key of Reflect.getMetadataKeys(source)) {
    Reflect.defineMetadata(key, Reflect.getMetadata(key,source), target);
  }
}

Then re-apply the metadata to the new descriptor.value

export function validate(classValidatorEntity: any): MethodDecorator {
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
    const origMethod = descriptor.value;
    descriptor.value = async function() {
      const result = await origMethod.apply(this, arguments);
      console.log(result); // validationFunc(result) in original method
      return result;
    };
    copyMetadata(origMethod, descriptor.value);
  };
}
like image 168
k7k0 Avatar answered Jan 23 '26 09:01

k7k0