import { BadRequestException, Injectable, PipeTransform } from '@nestjs/common'; import type { ZodTypeAny, z } from 'zod'; /** * Validates request bodies against a shared Zod schema. Failures become a * 400 with field-level details: { field: [i18nKey, …] } — the web client * renders the keys next to the matching inputs. */ @Injectable() export class ZodValidationPipe implements PipeTransform { constructor(private readonly schema: Schema) {} transform(value: unknown): z.infer { const result = this.schema.safeParse(value); if (result.success) return result.data; const details: Record = {}; for (const issue of result.error.issues) { const field = issue.path.join('.') || '_'; (details[field] ??= []).push(issue.message); } throw new BadRequestException({ code: 'bad_request', details }); } }