Files
5why-analyzer/scripts/init-database.js
donald 78efac64e2 Initial commit: 5 Why Root Cause Analyzer v1.0.0
Phase 0 & Phase 2 completed:
- Project structure setup
- Environment configuration (.env, .gitignore)
- Enterprise-grade dependencies (bcrypt, helmet, mysql2, etc.)
- Complete database schema with 8 tables + 2 views
- Database initialization scripts
- Comprehensive documentation

Database Tables:
- users (user management with 3-tier permissions)
- analyses (analysis records)
- analysis_perspectives (multi-angle analysis)
- analysis_whys (detailed 5 Why records)
- llm_configs (LLM API configurations)
- system_settings (system parameters)
- audit_logs (security audit trail)
- sessions (session management)

Tech Stack:
- Backend: Node.js + Express
- Frontend: React 18 + Vite + Tailwind CSS
- Database: MySQL 9.4.0
- AI: Ollama API (qwen2.5:3b)

Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 18:29:29 +08:00

135 lines
4.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.

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();