Created
November 24, 2022 13:42
-
-
Save Setitch/e46baa1d608965da156525aa40359a22 to your computer and use it in GitHub Desktop.
BadRequest Interceptor for NodeJS to flatten (make easy script readable) validation errors from class-validator
This file contains 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 { BadRequestException, CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; | |
import { ValidationError } from 'class-validator'; | |
import { catchError, Observable, throwError } from 'rxjs'; | |
@Injectable() | |
export class BadRequestInterceptor implements NestInterceptor { | |
intercept(context: ExecutionContext, next: CallHandler): Observable<any> { | |
return next | |
.handle() | |
.pipe( | |
catchError(err => { | |
if (err instanceof BadRequestException) { | |
const message = ((err.getResponse() as any).message); | |
if (message instanceof Array) { | |
const flat: any = this.flattenErrors((message as ValidationError[]).filter(m => m instanceof ValidationError)); | |
return throwError(new BadRequestException(flat)); | |
// return throwError(new BadRequestException(validations.map(v => v))); | |
} | |
} | |
return throwError(err); | |
}), | |
); | |
} | |
flattenErrors(validations: ValidationError[], previousName: string[] = []) { | |
const ret: Record<string, any> = {}; | |
// console.log(validations); | |
validations.forEach((v) => { | |
if (!ret.hasOwnProperty(v.property)) ret[v.property] = []; | |
if (Object.values(v.constraints || {}).length !== 0) { // hide empty fields that are parents etc | |
ret[[...previousName, v.property].join('.')] = Object.values(v.constraints || {}); | |
} | |
// console.log('o', previousName, [...previousName, v.property].join('.'), Object.values(v.constraints || {})) | |
if (v.children && v.children.length > 0) { | |
const r = this.flattenErrors(v.children, [...previousName, v.property]); | |
for (const prop in r) { | |
if (!r.hasOwnProperty(prop)) continue; | |
if (r[prop] instanceof Array && r[prop].length === 0) continue; // hide empty fields that are parents etc | |
ret[prop] = (ret[prop]) ? [...ret[prop], ...r[prop]] : r[prop]; | |
// console.log('x', prop, ret[prop] ); | |
} | |
} | |
if (ret[v.property].length===0) { | |
delete ret[v.property]; | |
} | |
}, {} as any); | |
return ret; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For this to work one need to create file for new validation pipe that will override original one a bit
and use it as global validation pipe