safe-parse-body.ts
1 import { NextResponse } from 'next/server' 2 import { z } from 'zod' 3 4 import { formatZodError } from '@/lib/validation/schemas' 5 6 type SafeResult<T> = { data: T; error?: never } | { data?: never; error: NextResponse } 7 8 /** 9 * Wraps `req.json()` so malformed/empty bodies return a 400 10 * instead of throwing an unhandled error (500). 11 */ 12 export async function safeParseBody<T = Record<string, unknown>>( 13 req: Request, 14 schema?: z.ZodType<T>, 15 ): Promise<SafeResult<T>> { 16 let raw: unknown 17 try { 18 raw = await req.json() 19 } catch { 20 return { error: NextResponse.json({ error: 'Invalid or missing request body' }, { status: 400 }) } 21 } 22 23 if (!schema) { 24 return { data: raw as T } 25 } 26 27 const parsed = schema.safeParse(raw) 28 if (!parsed.success) { 29 return { error: NextResponse.json(formatZodError(parsed.error), { status: 400 }) } 30 } 31 32 return { data: parsed.data } 33 }