import { NextResponse } from "next/server"; import { hash } from "bcryptjs"; import crypto from "crypto"; import { z } from "zod"; import { prisma } from "@/lib/prisma"; import { sendEmail } from "@/lib/email"; const registerSchema = z.object({ email: z.email("Invalid email address"), password: z.string().min(8, "Password must be at least 8 characters"), name: z.string().min(1).optional(), }); export async function POST(request: Request) { try { const body: unknown = await request.json(); const parsed = registerSchema.safeParse(body); if (!parsed.success) { return NextResponse.json( { error: parsed.error.issues[0]?.message ?? "Invalid input" }, { status: 400 } ); } const { email, password, name } = parsed.data; const normalizedEmail = email.toLowerCase(); const existing = await prisma.user.findUnique({ where: { email: normalizedEmail }, }); if (existing) { return NextResponse.json( { error: "An account with this email already exists" }, { status: 409 } ); } const passwordHash = await hash(password, 12); const user = await prisma.user.create({ data: { email: normalizedEmail, passwordHash, name: name ?? null, subscription: { create: { tier: "FREE", sessionsLimit: 20, }, }, }, select: { id: true, email: true, name: true, createdAt: true, }, }); // Send verification email (non-blocking — don't fail registration on email errors) try { const rawToken = crypto.randomBytes(32).toString("hex"); const tokenHash = crypto .createHash("sha256") .update(rawToken) .digest("hex"); await prisma.emailVerificationToken.create({ data: { userId: user.id, token: tokenHash, expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // 24 hours }, }); const verifyUrl = `https://agentlens.vectry.tech/verify-email?token=${rawToken}`; await sendEmail({ to: user.email, subject: "Verify your AgentLens email", html: `

Verify your email

Thanks for signing up for AgentLens. Click the link below to verify your email address.

Verify Email

This link expires in 24 hours. If you didn't create an account, you can safely ignore this email.

`, }); } catch (emailError) { console.error("[register] Failed to send verification email:", emailError); } return NextResponse.json(user, { status: 201 }); } catch { return NextResponse.json( { error: "Internal server error" }, { status: 500 } ); } }