"use server"; import bcrypt from "bcryptjs"; import { AuthError } from "next-auth"; import { prisma } from "@/lib/db"; import { signIn, signOut } from "@/auth"; import { LoginSchema, SignupSchema } from "@/lib/validation/auth"; export type SignupState = { error?: string; } | undefined; export type LoginState = { error?: string; } | undefined; export async function login( _prevState: LoginState, formData: FormData ): Promise { const parsed = LoginSchema.safeParse({ email: formData.get("email"), password: formData.get("password"), }); if (!parsed.success) { return { error: parsed.error.issues[0]?.message ?? "Invalid input." }; } try { await signIn("credentials", { email: parsed.data.email, password: parsed.data.password, redirectTo: "/", }); } catch (error) { if (error instanceof AuthError) { return { error: "Incorrect email or password." }; } throw error; } } export async function signup( _prevState: SignupState, formData: FormData ): Promise { const parsed = SignupSchema.safeParse({ name: formData.get("name"), email: formData.get("email"), password: formData.get("password"), }); if (!parsed.success) { return { error: parsed.error.issues[0]?.message ?? "Invalid input." }; } const { name, email, password } = parsed.data; const existing = await prisma.user.findUnique({ where: { email } }); if (existing) { return { error: "An account with that email already exists." }; } const passwordHash = await bcrypt.hash(password, 12); await prisma.user.create({ data: { name, email, passwordHash } }); try { // Signs the user in and redirects to "/" on success. NextAuth throws a // framework-handled redirect internally, so nothing after this runs. await signIn("credentials", { email, password, redirectTo: "/" }); } catch (error) { if (error instanceof AuthError) { return { error: "Account created, but sign-in failed. Try logging in." }; } throw error; } } export async function logout() { await signOut({ redirectTo: "/login" }); }