import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import mysql from 'mysql2/promise'; import dotenv from 'dotenv'; import bcrypt from 'bcryptjs'; // 載入環境變數 dotenv.config(); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // 資料庫配置 const dbConfig = { host: process.env.DB_HOST || 'mysql.theaken.com', port: parseInt(process.env.DB_PORT) || 33306, user: process.env.DB_USER || 'A102', password: process.env.DB_PASSWORD || 'Bb123456', database: process.env.DB_NAME || 'db_A102', multipleStatements: true }; async function initDatabase() { let connection; try { console.log('🔄 Connecting to database...'); console.log(` Host: ${dbConfig.host}:${dbConfig.port}`); console.log(` Database: ${dbConfig.database}`); connection = await mysql.createConnection(dbConfig); console.log('✅ Connected successfully\n'); // 讀取 SQL 檔案 const sqlPath = path.join(__dirname, '../docs/db_schema.sql'); console.log('📖 Reading SQL file:', sqlPath); let sqlContent = fs.readFileSync(sqlPath, 'utf8'); // 生成管理者密碼 hash const adminPassword = process.env.ADMIN_PASSWORD || 'Admin@123456'; const adminHash = await bcrypt.hash(adminPassword, 10); console.log('🔐 Generated admin password hash'); // 替換 SQL 中的密碼 hash sqlContent = sqlContent.replace(/\$2a\$10\$YourBcryptHashHere/g, adminHash); // 分割 SQL 語句 const statements = sqlContent .split(';') .map(stmt => stmt.trim()) .filter(stmt => stmt.length > 0 && !stmt.startsWith('--')); console.log(`\n📝 Found ${statements.length} SQL statements\n`); // 執行每個語句 for (let i = 0; i < statements.length; i++) { const statement = statements[i]; // 跳過註解和空白 if (statement.startsWith('--') || statement.trim() === '') { continue; } try { // 顯示正在執行的語句類型 let action = 'Executing'; if (statement.toUpperCase().includes('CREATE TABLE')) { const match = statement.match(/CREATE TABLE(?:\s+IF NOT EXISTS)?\s+`?(\w+)`?/i); if (match) { action = `Creating table: ${match[1]}`; } } else if (statement.toUpperCase().includes('CREATE VIEW')) { const match = statement.match(/CREATE.*VIEW\s+`?(\w+)`?/i); if (match) { action = `Creating view: ${match[1]}`; } } else if (statement.toUpperCase().includes('INSERT INTO')) { const match = statement.match(/INSERT INTO\s+`?(\w+)`?/i); if (match) { action = `Inserting data into: ${match[1]}`; } } console.log(` [${i + 1}/${statements.length}] ${action}`); await connection.execute(statement); } catch (error) { // 如果是 "already exists" 錯誤,只顯示警告 if (error.message.includes('already exists')) { console.log(` ⚠️ Already exists, skipping...`); } else { console.error(` ❌ Error: ${error.message}`); } } } console.log('\n✅ Database initialization completed successfully!\n'); // 顯示建立的資料表 const [tables] = await connection.execute('SHOW TABLES'); console.log('📊 Tables in database:'); tables.forEach((table, index) => { const tableName = Object.values(table)[0]; console.log(` ${index + 1}. ${tableName}`); }); console.log('\n🔐 Default admin credentials:'); console.log(` Email: ${process.env.ADMIN_EMAIL || 'admin@example.com'}`); console.log(` Password: ${adminPassword}`); console.log('\n⚠️ Please change the admin password after first login!\n'); } catch (error) { console.error('\n❌ Database initialization failed:'); console.error(' Error:', error.message); if (error.code) { console.error(' Error Code:', error.code); } process.exit(1); } finally { if (connection) { await connection.end(); console.log('🔌 Database connection closed\n'); } } } // 執行初始化 console.log('\n╔════════════════════════════════════════════╗'); console.log('║ 5 Why Analyzer - Database Initialization ║'); console.log('╚════════════════════════════════════════════╝\n'); initDatabase();