From 950217ed3ca93a0aa0e964c2a8474ffc13c71912 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 3 Dec 2025 05:28:29 +0900 Subject: feat(auth): add user registration endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement POST /api/auth/register endpoint with: - Argon2 password hashing - Zod validation for username (1-255 chars) and password (8-255 chars) - Duplicate username check (returns 409 Conflict) - Returns created user with id, username, and createdAt 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- pkgs/server/src/routes/auth.ts | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 pkgs/server/src/routes/auth.ts (limited to 'pkgs/server/src/routes/auth.ts') diff --git a/pkgs/server/src/routes/auth.ts b/pkgs/server/src/routes/auth.ts new file mode 100644 index 0000000..3906d65 --- /dev/null +++ b/pkgs/server/src/routes/auth.ts @@ -0,0 +1,50 @@ +import { createUserSchema } from "@kioku/shared"; +import * as argon2 from "argon2"; +import { eq } from "drizzle-orm"; +import { Hono } from "hono"; +import { db, users } from "../db"; +import { Errors } from "../middleware"; + +const auth = new Hono(); + +auth.post("/register", async (c) => { + const body = await c.req.json(); + + const parsed = createUserSchema.safeParse(body); + if (!parsed.success) { + throw Errors.validationError(parsed.error.issues[0]?.message); + } + + const { username, password } = parsed.data; + + // Check if username already exists + const existingUser = await db + .select({ id: users.id }) + .from(users) + .where(eq(users.username, username)) + .limit(1); + + if (existingUser.length > 0) { + throw Errors.conflict("Username already exists", "USERNAME_EXISTS"); + } + + // Hash password with Argon2 + const passwordHash = await argon2.hash(password); + + // Create user + const [newUser] = await db + .insert(users) + .values({ + username, + passwordHash, + }) + .returning({ + id: users.id, + username: users.username, + createdAt: users.createdAt, + }); + + return c.json({ user: newUser }, 201); +}); + +export { auth }; -- cgit v1.2.3-70-g09d2