import fs from 'fs'; import path from 'path'; import initSqlJs, { Database, Statement } from 'sql.js'; // Simple SQLite via sql.js persisted to a single file const DATA_DIR = path.join(process.cwd(), 'data'); const DB_FILE = path.join(DATA_DIR, 'metoyou.sqlite'); function ensureDataDir() { if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true }); } let SQL: any = null; let db: Database | null = null; export async function initDB(): Promise { if (db) return; SQL = await initSqlJs({ locateFile: (file: string) => require.resolve('sql.js/dist/sql-wasm.wasm') }); ensureDataDir(); if (fs.existsSync(DB_FILE)) { const fileBuffer = fs.readFileSync(DB_FILE); db = new SQL.Database(new Uint8Array(fileBuffer)); } else { db = new SQL.Database(); } // Initialize schema db.run(` CREATE TABLE IF NOT EXISTS users ( id TEXT PRIMARY KEY, username TEXT UNIQUE NOT NULL, passwordHash TEXT NOT NULL, displayName TEXT NOT NULL, createdAt INTEGER NOT NULL ); `); persist(); } function persist(): void { if (!db) return; const data = db.export(); const buffer = Buffer.from(data); fs.writeFileSync(DB_FILE, buffer); } export interface AuthUser { id: string; username: string; passwordHash: string; displayName: string; createdAt: number; } export async function getUserByUsername(username: string): Promise { if (!db) await initDB(); const stmt: Statement = db!.prepare('SELECT id, username, passwordHash, displayName, createdAt FROM users WHERE username = ? LIMIT 1'); stmt.bind([username]); let row: AuthUser | null = null; if (stmt.step()) { const r = stmt.getAsObject() as any; row = { id: String(r.id), username: String(r.username), passwordHash: String(r.passwordHash), displayName: String(r.displayName), createdAt: Number(r.createdAt), }; } stmt.free(); return row; } export async function getUserById(id: string): Promise { if (!db) await initDB(); const stmt: Statement = db!.prepare('SELECT id, username, passwordHash, displayName, createdAt FROM users WHERE id = ? LIMIT 1'); stmt.bind([id]); let row: AuthUser | null = null; if (stmt.step()) { const r = stmt.getAsObject() as any; row = { id: String(r.id), username: String(r.username), passwordHash: String(r.passwordHash), displayName: String(r.displayName), createdAt: Number(r.createdAt), }; } stmt.free(); return row; } export async function createUser(user: AuthUser): Promise { if (!db) await initDB(); const stmt = db!.prepare('INSERT INTO users (id, username, passwordHash, displayName, createdAt) VALUES (?, ?, ?, ?, ?)'); stmt.bind([user.id, user.username, user.passwordHash, user.displayName, user.createdAt]); stmt.step(); stmt.free(); persist(); }