I have a NestJS TS application that has an xml endpoint. I want to validate an xml body. Here's how I went with parsing xml to js object:
@Injectable()
export class XmlToJsInterceptor implements NestInterceptor {
constructor(private parser: CxmlParserService) {}
public intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
const req: XmlRequest<unknown> = context.switchToHttp().getRequest();
if (req.rawBody) {
req.xml = this.parser.convertXMLToObject(req.rawBody) as unknown;
}
return next.handle();
}
}
export const XmlBody = createParamDecorator((data: unknown, ctx: ExecutionContext): unknown => {
const request: XmlRequest<unknown> = ctx.switchToHttp().getRequest();
return request.xml;
});
And I use it like this:
@UseInterceptors(XmlToJsInterceptor)
@Controller('/endpoint')
export class MyController {
@Post('/')
@HttpCode(HttpStatus.OK)
async handleEndpoint(
@XmlBody() body: MyClassValidator,
): Promise<void> {
Now I want to use class-validator to check if xml request has a proper structure. I thought to extend XmlBody nestjs param decorator to include validation and manually call class-validator like this:
export const XmlBody = createParamDecorator((data: unknown, ctx: ExecutionContext): unknown => {
const request: XmlRequest<unknown> = ctx.switchToHttp().getRequest();
const validatedConfig = plainToClass(HOWDO_I_GET_PARAM_CLASS, request.xml, {
enableImplicitConversion: true,
});
const errors = validateSync(validatedConfig, { skipMissingProperties: false });
if (errors.length > 0) {
throw new Error(errors.toString());
}
return request.xml;
});
But I don't know to get typescript class from annotated parameter.