Files
omnisupport-ai/backend/db.js
fcarraUniSa 0db1f2cea8 Update db.js
2026-02-17 14:28:25 +01:00

136 lines
5.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 */ }
// MIGRATION: Add 'attachments' to tickets if not exists
try {
await pool.query("ALTER TABLE tickets ADD COLUMN attachments JSON DEFAULT NULL");
console.log("✅ Added attachments column to tickets");
} catch (e) { /* Column likely exists */ }
// MIGRATION: Add 'attachments' to ticket_messages if not exists
try {
await pool.query("ALTER TABLE ticket_messages ADD COLUMN attachments JSON DEFAULT NULL");
console.log("✅ Added attachments column to ticket_messages");
} 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, "attachmentsEnabled": true, "maxFileSizeMb": 5, "allowedFileTypes": "jpg,png,pdf"}',
'{"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);
}
};