import { BadRequestException, ValidationError, ValidationPipe, } from "@nestjs/common"; type FrontendValidationError = { field: string; message: string; }; const constraintMessages: Record = { isString: "باید به‌صورت متن ارسال شود.", isNotEmpty: "وارد کردن این فیلد الزامی است.", isArray: "باید به‌صورت فهرست ارسال شود.", arrayMinSize: "حداقل یک قطعه آسیب‌دیده باید ارسال شود.", isBoolean: "باید درست یا نادرست باشد.", isInt: "باید یک عدد صحیح باشد.", isEnum: "مقدار واردشده معتبر نیست.", nestedValidation: "اطلاعات این بخش معتبر نیست.", isMoneyAmountString: "باید مبلغ صحیح و غیرمنفی به تومان باشد.", }; function flattenValidationErrors( errors: ValidationError[], parentPath = "", ): FrontendValidationError[] { return errors.flatMap((error) => { const field = parentPath ? /^\d+$/.test(error.property) ? `${parentPath}[${error.property}]` : `${parentPath}.${error.property}` : error.property; const ownErrors = Object.keys(error.constraints ?? {}).map((constraint) => ({ field, message: constraintMessages[constraint] ?? "مقدار واردشده معتبر نیست.", })); return [...ownErrors, ...flattenValidationErrors(error.children ?? [], field)]; }); } /** * Endpoint-scoped because this application deliberately has no global * ValidationPipe. It preserves DTO validation while returning a stable, * Persian payload that the frontend can render by field. */ export const submitExpertReplyValidationPipe = new ValidationPipe({ transform: true, whitelist: true, exceptionFactory: (errors: ValidationError[]) => { const validationErrors = flattenValidationErrors(errors); return new BadRequestException({ message: "اطلاعات ارسالی پاسخ کارشناسی معتبر نیست.", error: "EXPERT_REPLY_VALIDATION_ERROR", code: "EXPERT_REPLY_VALIDATION_ERROR", validationErrors, }); }, });