forked from Shared/esg
98 lines
2.5 KiB
TypeScript
98 lines
2.5 KiB
TypeScript
import { ValidationError } from 'class-validator';
|
|
import { NormalizedErrorDto } from '../dto/normalized-error.dto';
|
|
|
|
export interface ValidationFieldError {
|
|
field: string;
|
|
constraints: string[];
|
|
}
|
|
|
|
export function flattenValidationErrors(
|
|
errors: ValidationError[],
|
|
parentPath = '',
|
|
): ValidationFieldError[] {
|
|
const result: ValidationFieldError[] = [];
|
|
|
|
for (const error of errors) {
|
|
const field = parentPath ? `${parentPath}.${error.property}` : error.property;
|
|
|
|
if (error.constraints) {
|
|
result.push({
|
|
field,
|
|
constraints: Object.values(error.constraints),
|
|
});
|
|
}
|
|
|
|
if (error.children?.length) {
|
|
result.push(...flattenValidationErrors(error.children, field));
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
export function buildValidationErrorResponse(errors: ValidationError[]): {
|
|
normalizedError: NormalizedErrorDto;
|
|
details: ValidationFieldError[];
|
|
} {
|
|
const details = flattenValidationErrors(errors);
|
|
const summary =
|
|
details.length > 0
|
|
? details.map((d) => `${d.field}: ${d.constraints.join(', ')}`).join('; ')
|
|
: 'Request validation failed';
|
|
|
|
return {
|
|
normalizedError: {
|
|
code: 'VALIDATION_ERROR',
|
|
message: summary,
|
|
details,
|
|
},
|
|
details,
|
|
};
|
|
}
|
|
|
|
export function formatHttpExceptionMessage(exception: unknown): string {
|
|
if (!(exception && typeof exception === 'object' && 'getResponse' in exception)) {
|
|
return exception instanceof Error ? exception.message : String(exception);
|
|
}
|
|
|
|
const response = (exception as { getResponse: () => unknown }).getResponse();
|
|
|
|
if (typeof response === 'string') {
|
|
return response;
|
|
}
|
|
|
|
if (typeof response !== 'object' || response === null) {
|
|
return exception instanceof Error ? exception.message : 'Request failed';
|
|
}
|
|
|
|
const body = response as {
|
|
message?: string | string[];
|
|
error?: unknown;
|
|
};
|
|
|
|
if (isNormalizedError(body.error)) {
|
|
return body.error.message;
|
|
}
|
|
|
|
if (Array.isArray(body.message)) {
|
|
return body.message.join('; ');
|
|
}
|
|
|
|
if (typeof body.message === 'string' && body.message.length > 0) {
|
|
return body.message;
|
|
}
|
|
|
|
return exception instanceof Error ? exception.message : 'Request failed';
|
|
}
|
|
|
|
export function isNormalizedError(value: unknown): value is NormalizedErrorDto {
|
|
return (
|
|
typeof value === 'object' &&
|
|
value !== null &&
|
|
'code' in value &&
|
|
'message' in value &&
|
|
typeof (value as NormalizedErrorDto).code === 'string' &&
|
|
typeof (value as NormalizedErrorDto).message === 'string'
|
|
);
|
|
}
|