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>
This commit is contained in:
donald
2025-12-05 18:29:29 +08:00
commit 78efac64e2
23 changed files with 3059 additions and 0 deletions

134
scripts/init-database.js Normal file
View File

@@ -0,0 +1,134 @@
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();