import { Hono } from "hono"; import { validator } from "hono/validator"; import type { AccountServiceInterface } from "../service/AccountServiceInterface"; import { loginSchema, registerSchema } from "../validation/AccountValidation"; import { BadSchemaError } from "../../../errors"; import { createRateLimit } from "../../../middleware/rateLimiter"; const loginRateLimit = createRateLimit({ windowMs: 15 * 60 * 1000, maxAttempts: 5, keyGenerator: (c) => { const ip = c.req.header("x-forwarded-for") || c.req.header("x-real-ip") || "127.0.0.1"; return `login:${ip}`; }, }); export default function toRoutes( accountService: AccountServiceInterface, ): Hono { const app = new Hono(); app.post( "/login", loginRateLimit, validator("json", (value) => { const parsed = loginSchema.safeParse(value); if (!parsed.success) { throw new BadSchemaError(parsed.error.message); } return parsed.data; }), async (ctx) => { const { username, password } = ctx.req.valid("json"); const account = await accountService.login(username, password); return ctx.json({ success: true, accountId: account.id, username: account.username, }); }, ); app.post( "/register", validator("json", (value) => { const parsed = registerSchema.safeParse(value); if (!parsed.success) { throw new BadSchemaError(parsed.error.message); } return parsed.data; }), async (ctx) => { const { username, password } = ctx.req.valid("json"); const account = await accountService.register(username, password); return ctx.json({ success: true, accountId: account.id, username: account.username, }); }, ); return app; }