typescript - Egen metoddekorerare som raderar all metadata, hur kan jag lösa det?


Jag använder NestJS och nestjs/swagger-modulen för enkel API-dokumentation, men jag har problem eftersom jag behöver validera responsen från min tjänst.

Det är därför jag skapar min egen metoddekoration, men jag har stora problem när jag använder den - all metadata från andra dekoratorer försvinner och swagger-modulen kan inte visa bra dokumentation.

Koden för min dekoratör

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;
    };
  };
}

och ett exempel på kod för någon kontrollermetod

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

Om min dekoratör är högst upp (först) - förloras all metadata. Om min dekoratör är sist - förlorar jag data från @Body() dekoratören....

Jag vet inte vad jag ska göra, och hur jag behöver skriva om min egen dekoratör.

Svar #1

Metadata är kopplat till den specifika descriptor.value, du måste återapplicera metadata kopplat från origMethod till den nya descriptor.value

Först definiera en metadata copyMetadata-metod

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

Applicera sedan metadata igen på den nya 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);
  };
}