Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | /**
* Validation Middleware
*
* Validates request body against a Zod schema.
*/
import { NextRequest, NextResponse } from 'next/server';
import { ZodSchema } from 'zod';
import { validationErrorResponse, type ApiErrorResponse } from '../responses';
import type { RouteContext, ValidatedHandler } from './types';
/**
* Validation middleware
*
* Wraps a handler to validate the request body against a Zod schema.
* If validation fails, returns a 400 error with validation details.
*
* @example
* ```ts
* const createProductSchema = z.object({
* title: z.string().min(1),
* price: z.number().positive(),
* });
*
* export const POST = withValidation(createProductSchema)(
* async (request, context, data) => {
* // data is typed and validated
* const product = await prisma.product.create({ data });
* return createdResponse(product);
* }
* );
* ```
*/
export function withValidation<V>(schema: ZodSchema<V>) {
return <T>(handler: ValidatedHandler<T, V>) => {
return async (
request: Request,
context?: RouteContext
): Promise<NextResponse<T | ApiErrorResponse>> => {
let body: unknown;
try {
body = await request.json();
} catch {
return validationErrorResponse('Invalid JSON body');
}
const result = schema.safeParse(body);
if (!result.success) {
const details = result.error.issues.map((issue) => ({
field: issue.path.join('.') || '_root',
message: issue.message,
code: issue.code }));
return validationErrorResponse('Validation failed', details);
}
return handler(request as NextRequest, context, result.data);
};
};
}
/**
* Parse request body as JSON (without validation)
*
* @example
* ```ts
* export const POST = async (request) => {
* const body = await parseBody(request);
* if (body.error) return body.error;
* // body.data is the parsed JSON
* };
* ```
*/
export async function parseBody<T = unknown>(
request: Request
): Promise<{ data: T; error?: never } | { data?: never; error: NextResponse }> {
try {
const data = (await request.json()) as T;
return { data };
} catch {
return { error: validationErrorResponse('Invalid JSON body') };
}
}
|