import { Hono } from "hono";
import { zValidator } from "@hono/zod-validator";
import { setCookie, deleteCookie, getCookie } from "hono/cookie";
import { hash, verify } from "@node-rs/argon2";
import { uuidv7 } from "uuidv7";
import { signupSchema, loginSchema } from "@pijulab/shared";
import {
findUserByEmail,
findUserByUsername,
createUser,
createSession,
deleteSession,
} from "../db/queries.js";
import { sessionMiddleware } from "../middleware/auth.js";
export const authRouter = new Hono()
.post("/signup", zValidator("json", signupSchema), async (c) => {
const { username, email, password } = c.req.valid("json");
const [existingEmail, existingUsername] = await Promise.all([
findUserByEmail(email),
findUserByUsername(username),
]);
if (existingEmail) return c.json({ message: "Email already in use" }, 409);
if (existingUsername) return c.json({ message: "Username already taken" }, 409);
const passwordHash = await hash(password);
const userId = await createUser({ username, email, passwordHash });
const sessionId = uuidv7();
const expiresAt = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);
await createSession({ id: sessionId, userId, expiresAt });
setCookie(c, "pijulab_session", sessionId, {
httpOnly: true,
sameSite: "Lax",
path: "/",
expires: expiresAt,
});
return c.json({ id: userId, username, email }, 201);
})
.post("/login", zValidator("json", loginSchema), async (c) => {
const { email, password } = c.req.valid("json");
const user = await findUserByEmail(email);
if (!user) return c.json({ message: "Invalid email or password" }, 401);
const valid = await verify(user.password_hash, password);
if (!valid) return c.json({ message: "Invalid email or password" }, 401);
const sessionId = uuidv7();
const expiresAt = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000);
await createSession({ id: sessionId, userId: user.id, expiresAt });
setCookie(c, "pijulab_session", sessionId, {
httpOnly: true,
sameSite: "Lax",
path: "/",
expires: expiresAt,
});
return c.json({ id: user.id, username: user.username, email: user.email });
})
.post("/logout", sessionMiddleware, async (c) => {
const sessionId = getCookie(c, "pijulab_session");
if (sessionId) {
await deleteSession(sessionId);
}
deleteCookie(c, "pijulab_session", { path: "/" });
return c.json({ ok: true });
});