import { sign as jwtSign, verify as jwtVerify } from 'hono/jwt'; const { JWT_SECRET } = process.env; if (!JWT_SECRET || JWT_SECRET.length < 32) { throw new Error('JWT_SECRET must be set and at least 32 characters long. Generate one with: openssl rand -base64 32'); } function parseExpiration(expiration: string): number { const match = expiration.match(/^(\d+)([smhd])$/); if (!match) { throw new Error(`Invalid expiration format: ${expiration}`); } const value = parseInt(match[1]!, 10); const unit = match[2]; const multipliers: Record = { s: 1, m: 60, h: 60 * 60, d: 60 * 60 * 24, }; return Math.floor(Date.now() / 1000) + value * multipliers[unit!]!; } export async function sign(payload: any, expiration = '30d') { const now = Math.floor(Date.now() / 1000); const exp = parseExpiration(expiration); const jti = crypto.randomUUID(); const data = { ...payload, exp, iat: now, jti }; return jwtSign(data, JWT_SECRET!); } export async function verify(token: string): Promise { return jwtVerify(token, JWT_SECRET!, 'HS256'); }