const { Pool } = require('pg'); const config = { user: process.env.DB_USER, password: process.env.DB_PASSWORD, host: process.env.DB_HOST, port: process.env.DB_PORT, database: process.env.USERS_DB || process.env.DB_NAME, max: 10, idleTimeoutMillis: 30000, connectionTimeoutMillis: 5000 }; const pool = new Pool(config); pool.on('error', (err) => { console.error('[DB] Pool error:', err.message); }); async function query(text, params) { const start = Date.now(); try { const result = await pool.query(text, params); const duration = Date.now() - start; if (duration > 100) { console.warn(`[DB] Slow query (${duration}ms):`, text.substring(0, 80)); } return result; } catch (err) { console.error('[DB] Query failed:', err.message, '| code:', err.code); throw err; } } async function getClient() { return await pool.connect(); } async function initDb() { await pool.query('SELECT NOW()'); try { await pool.query(`CREATE EXTENSION IF NOT EXISTS pgcrypto;`); } catch (err) { console.warn('[DB] Could not create pgcrypto extension:', err.message); } await pool.query(` CREATE TABLE IF NOT EXISTS users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), username VARCHAR(50) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, is_active BOOLEAN DEFAULT TRUE, created_at TIMESTAMP DEFAULT NOW(), telegram_id VARCHAR(50) UNIQUE ); CREATE INDEX IF NOT EXISTS idx_users_username ON users(username); CREATE INDEX IF NOT EXISTS idx_users_telegram_id ON users(telegram_id); `); await pool.query(` CREATE TABLE IF NOT EXISTS sessions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, session_code VARCHAR(64) NOT NULL, encoded_username TEXT NOT NULL DEFAULT '', ip_address INET, user_agent TEXT, browser VARCHAR(100), os VARCHAR(100), device_type VARCHAR(50), location_country VARCHAR(100), location_city VARCHAR(100), created_at TIMESTAMP DEFAULT NOW(), last_active TIMESTAMP DEFAULT NOW(), is_revoked BOOLEAN DEFAULT FALSE ); CREATE INDEX IF NOT EXISTS idx_sessions_code ON sessions(session_code); CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON sessions(user_id); `); } async function checkPostgres() { try { await pool.query('SELECT NOW()'); return true; } catch { return false; } } module.exports = { pool, query, getClient, initDb, checkPostgres };