import fs from "fs"; import path from "path"; import bcrypt from "bcryptjs"; const DATA_DIR = path.join(process.cwd(), "data"); const USERS_FILE = path.join(DATA_DIR, "users.json"); export interface UserRow { id: number; username: string; email: string; password_hash: string; created_at: string; } export interface UserPublic { id: number; username: string; email: string; created_at: string; } function ensureDataDir() { if (!fs.existsSync(DATA_DIR)) { fs.mkdirSync(DATA_DIR, { recursive: true }); } } function readUsers(): UserRow[] { ensureDataDir(); if (!fs.existsSync(USERS_FILE)) { return []; } try { const raw = fs.readFileSync(USERS_FILE, "utf-8"); return JSON.parse(raw); } catch { return []; } } function writeUsers(users: UserRow[]) { ensureDataDir(); fs.writeFileSync(USERS_FILE, JSON.stringify(users, null, 2), "utf-8"); } let nextId = 0; function getNextId(): number { if (nextId === 0) { const users = readUsers(); nextId = users.reduce((max, u) => Math.max(max, u.id), 0) + 1; } return nextId++; } export function createUser(username: string, email: string, password: string): UserPublic { const users = readUsers(); if (users.find((u) => u.email === email || u.username === username)) { throw new Error("A user with that email or username already exists."); } const password_hash = bcrypt.hashSync(password, 10); const newUser: UserRow = { id: getNextId(), username, email, password_hash, created_at: new Date().toISOString(), }; users.push(newUser); writeUsers(users); return { id: newUser.id, username: newUser.username, email: newUser.email, created_at: newUser.created_at, }; } export function authenticateUser(email: string, password: string): UserPublic { const users = readUsers(); const user = users.find((u) => u.email === email); if (!user) { throw new Error("Invalid email or password."); } if (!bcrypt.compareSync(password, user.password_hash)) { throw new Error("Invalid email or password."); } return { id: user.id, username: user.username, email: user.email, created_at: user.created_at, }; } export function getUserById(id: number): UserPublic | null { const users = readUsers(); const user = users.find((u) => u.id === id); if (!user) return null; return { id: user.id, username: user.username, email: user.email, created_at: user.created_at, }; }