40 lines
1.4 KiB
TypeScript
40 lines
1.4 KiB
TypeScript
import { NextResponse } from "next/server";
|
|||
|
|
import bcrypt from "bcryptjs";
|
||
|
|
import { z } from "zod";
|
||
|
|
import { prisma } from "@/lib/prisma";
|
||
|
|
|
||
|
|
const signupSchema = z.object({
|
||
|
|
name: z.string().trim().min(1, "Name is required").max(80),
|
||
|
|
email: z.string().trim().toLowerCase().email("Enter a valid email"),
|
||
|
|
password: z.string().min(8, "Password must be at least 8 characters"),
|
||
|
|
age: z.number().int().min(18, "You must be 18 or older to join").max(120),
|
||
|
|
});
|
||
|
|
|
||
|
|
export async function POST(request: Request) {
|
||
|
|
const body = await request.json().catch(() => null);
|
||
|
|
if (!body) {
|
||
|
|
return NextResponse.json({ error: "Invalid request body" }, { status: 400 });
|
||
|
|
}
|
||
|
|
|
||
|
|
const parsed = signupSchema.safeParse(body);
|
||
|
|
if (!parsed.success) {
|
||
|
|
const message = parsed.error.issues[0]?.message ?? "Invalid input";
|
||
|
|
return NextResponse.json({ error: message }, { status: 400 });
|
||
|
|
}
|
||
|
|
|
||
|
|
const { name, email, password, age } = parsed.data;
|
||
|
|
|
||
|
|
const existing = await prisma.user.findUnique({ where: { email } });
|
||
|
|
if (existing) {
|
||
|
|
return NextResponse.json({ error: "An account with that email already exists" }, { status: 409 });
|
||
|
|
}
|
||
|
|
|
||
|
|
const passwordHash = await bcrypt.hash(password, 12);
|
||
|
|
|
||
|
|
const user = await prisma.user.create({
|
||
|
|
data: { name, email, age, passwordHash },
|
||
|
|
select: { id: true, email: true, name: true },
|
||
|
|
});
|
||
|
|
|
||
|
|
return NextResponse.json({ user }, { status: 201 });
|
||
|
|
}
|