import mysql from 'mysql2/promise'; import dotenv from 'dotenv'; import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; dotenv.config(); // Fix per __dirname in ES Modules const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Configurazione DB con gestione esplicita della porta e casting a numero const dbConfig = { host: process.env.DB_HOST || 'db', port: Number(process.env.DB_PORT) || 3306, user: process.env.DB_USER || 'omni_user', password: process.env.DB_PASSWORD || 'omni_pass', database: process.env.DB_NAME || 'omnisupport', waitForConnections: true, connectionLimit: 10, queueLimit: 0, multipleStatements: true // Necessario per eseguire schema.sql che contiene piΓΉ query }; const pool = mysql.createPool(dbConfig); export const query = async (sql, params) => { try { const [results] = await pool.execute(sql, params); return results; } catch (error) { console.error('Database query error:', error); throw error; } }; export const checkConnection = async () => { try { const connection = await pool.getConnection(); await connection.ping(); connection.release(); console.log(`βœ… Connected to MySQL Database at ${dbConfig.host}:${dbConfig.port}`); return true; } catch (error) { console.error(`❌ Database connection failed (${dbConfig.host}:${dbConfig.port}):`, error.message); return false; } }; export const initDb = async () => { try { console.log(`πŸ”Œ Attempting connection to database at ${dbConfig.host}:${dbConfig.port}...`); const isConnected = await checkConnection(); if (!isConnected) { console.error("❌ Skipping initialization due to connection failure."); return; } // Check if main tables exist const [agentsExist] = await pool.query("SHOW TABLES LIKE 'agents'"); const [settingsExist] = await pool.query("SHOW TABLES LIKE 'settings'"); // Scenario 1: DB completely initialized if (agentsExist.length > 0 && settingsExist.length > 0) { console.log('ℹ️ Database tables already exist. Checking for migrations...'); // MIGRATION: Add 'visibility' to kb_articles if not exists try { await pool.query("ALTER TABLE kb_articles ADD COLUMN visibility ENUM('public', 'internal') DEFAULT 'public'"); console.log("βœ… Added visibility column to kb_articles"); } catch (e) { /* Column likely exists */ } // MIGRATION: Add 'has_been_analyzed' to tickets if not exists try { await pool.query("ALTER TABLE tickets ADD COLUMN has_been_analyzed BOOLEAN DEFAULT FALSE"); console.log("βœ… Added has_been_analyzed column to tickets"); } catch (e) { /* Column likely exists */ } return; } // Scenario 2: Partial migration (Agents exist but Settings missing) if (agentsExist.length > 0 && settingsExist.length === 0) { console.log('⚠️ Settings table missing (Partial Migration). Creating...'); const createSettingsSql = ` CREATE TABLE IF NOT EXISTS settings ( id INT PRIMARY KEY DEFAULT 1, branding JSON, smtp JSON, email_templates JSON, features JSON, ai_config JSON ); INSERT INTO settings (id, branding, smtp, email_templates, features, ai_config) VALUES ( 1, '{"appName": "OmniSupport AI", "primaryColor": "#0284c7", "logoUrl": "https://via.placeholder.com/150"}', '{"host": "smtp.example.com", "port": 587, "user": "notifications@omnisupport.ai", "pass": "password", "secure": true, "fromEmail": "noreply@omnisupport.ai"}', '[{"id": "t1", "name": "Conferma Apertura Ticket", "trigger": "ticket_created", "audience": "client", "subject": "Ticket #{ticket_id} Creato", "body": "Grazie per averci contattato.", "isActive": true}]', '{"kbEnabled": true, "maxKbArticles": 50, "maxSupervisors": 2, "aiKnowledgeAgentEnabled": true, "maxAiGeneratedArticles": 10, "maxAgents": 10}', '{"provider": "gemini", "apiKey": "", "model": "gemini-3-flash-preview", "isActive": true, "agentName": "OmniSupport AI", "customPrompt": ""}' ); `; await pool.query(createSettingsSql); console.log('βœ… Settings table created successfully.'); return; } // Scenario 3: Fresh Install console.log('⚠️ Database empty. Running full schema.sql...'); const schemaPath = path.join(__dirname, 'schema.sql'); const schemaSql = fs.readFileSync(schemaPath, 'utf8'); await pool.query(schemaSql); console.log('βœ… Database initialized successfully with schema and seed data.'); console.log('πŸ‘€ Superadmin created: fcarra79@gmail.com'); } catch (error) { console.error('❌ Failed to initialize database:', error); } };