import { Metadata } from "next" import { hash } from "bcryptjs" import { createId } from "@paralleldrive/cuid2" import { eq } from "drizzle-orm" import type { ActionState } from "@/shared/types/action-state" import { RegisterForm } from "@/modules/auth/components/register-form" export const metadata: Metadata = { title: "Register - Next_Edu", description: "Create an account", } const normalizeBcryptHash = (value: string) => { if (value.startsWith("$2")) return value if (value.startsWith("$")) return `$2b${value}` return `$2b$${value}` } export default function RegisterPage() { async function registerAction(formData: FormData): Promise { "use server" const databaseUrl = process.env.DATABASE_URL if (!databaseUrl) return { success: false, message: "DATABASE_URL 未配置" } try { const [{ db }, { users }] = await Promise.all([ import("@/shared/db"), import("@/shared/db/schema"), ]) const name = String(formData.get("name") ?? "").trim() const email = String(formData.get("email") ?? "").trim().toLowerCase() const password = String(formData.get("password") ?? "") if (!email) return { success: false, message: "请输入邮箱" } if (!password) return { success: false, message: "请输入密码" } if (password.length < 6) return { success: false, message: "密码至少 6 位" } const existing = await db.query.users.findFirst({ where: eq(users.email, email), columns: { id: true }, }) if (existing) return { success: false, message: "该邮箱已注册" } const hashedPassword = normalizeBcryptHash(await hash(password, 10)) await db.insert(users).values({ id: createId(), name: name.length ? name : null, email, password: hashedPassword, role: "student", }) return { success: true, message: "账户创建成功" } } catch (error) { const isProd = process.env.NODE_ENV === "production" const anyErr = error as unknown as { code?: string message?: string sqlMessage?: string cause?: unknown } const cause1 = anyErr?.cause as | { code?: string; message?: string; sqlMessage?: string; cause?: unknown } | undefined const cause2 = (cause1?.cause ?? undefined) as | { code?: string; message?: string; sqlMessage?: string } | undefined const code = String(cause2?.code ?? cause1?.code ?? anyErr?.code ?? "").trim() const msg = String( cause2?.sqlMessage ?? cause1?.sqlMessage ?? anyErr?.sqlMessage ?? cause2?.message ?? cause1?.message ?? anyErr?.message ?? "" ).trim() const msgLower = msg.toLowerCase() if ( code === "ER_DUP_ENTRY" || msgLower.includes("duplicate") || msgLower.includes("unique") ) { return { success: false, message: "该邮箱已注册" } } if ( code === "ER_NO_SUCH_TABLE" || msgLower.includes("doesn't exist") || msgLower.includes("unknown column") ) { return { success: false, message: "数据库未初始化或未迁移,请先运行 npm run db:migrate", } } if (code === "ER_ACCESS_DENIED_ERROR") { return { success: false, message: "数据库账号/权限错误,请检查 DATABASE_URL" } } if (code === "ECONNREFUSED" || code === "ENOTFOUND") { return { success: false, message: "数据库连接失败,请检查 DATABASE_URL 与网络" } } if (!isProd && msg) { return { success: false, message: `创建账户失败:${msg}` } } return { success: false, message: "创建账户失败,请稍后重试" } } } return }