Major Changes: - Moved legacy system to Legacy/ folder for archival - Built new modular architecture with strict separation of concerns - Created core system: Module, EventBus, ModuleLoader, Router - Added Application bootstrap with auto-start functionality - Implemented development server with ES6 modules support - Created comprehensive documentation and project context - Converted SBS-7-8 content to JSON format - Copied all legacy games and content to new structure New Architecture Features: - Sealed modules with WeakMap private data - Strict dependency injection system - Event-driven communication only - Inviolable responsibility patterns - Auto-initialization without commands - Component-based UI foundation ready Technical Stack: - Vanilla JS/HTML/CSS only - ES6 modules with proper imports/exports - HTTP development server (no file:// protocol) - Modular CSS with component scoping - Comprehensive error handling and debugging Ready for Phase 2: Converting legacy modules to new architecture 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
179 lines
6.3 KiB
JavaScript
179 lines
6.3 KiB
JavaScript
#!/usr/bin/env node
|
|
// tools/log-server.js - Serveur simple pour visualiser les logs
|
|
const express = require('express');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const { exec } = require('child_process');
|
|
|
|
const app = express();
|
|
const PORT = 3001;
|
|
|
|
// Servir les fichiers statiques depuis la racine du projet
|
|
app.use(express.static(path.join(__dirname, '..')));
|
|
|
|
// Route pour servir les fichiers de log
|
|
app.use('/logs', express.static(path.join(__dirname, '..', 'logs')));
|
|
|
|
// Liste des fichiers de log disponibles
|
|
app.get('/api/logs', (req, res) => {
|
|
try {
|
|
const logsDir = path.join(__dirname, '..', 'logs');
|
|
const files = fs.readdirSync(logsDir)
|
|
.filter(file => file.endsWith('.log'))
|
|
.map(file => {
|
|
const filePath = path.join(logsDir, file);
|
|
const stats = fs.statSync(filePath);
|
|
return {
|
|
name: file,
|
|
size: stats.size,
|
|
modified: stats.mtime.toISOString(),
|
|
url: `http://localhost:${PORT}/tools/logs-viewer.html?file=${file}`
|
|
};
|
|
})
|
|
.sort((a, b) => new Date(b.modified) - new Date(a.modified));
|
|
|
|
res.json({ files });
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
// Page d'accueil avec liste des logs
|
|
app.get('/', (req, res) => {
|
|
res.send(`
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Log Viewer Server</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }
|
|
h1 { color: #333; }
|
|
.log-list { background: white; padding: 20px; border-radius: 5px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
|
|
.log-item {
|
|
padding: 10px;
|
|
border-bottom: 1px solid #eee;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
.log-item:hover { background: #f8f9fa; }
|
|
.log-name { font-weight: bold; color: #2c5aa0; }
|
|
.log-info { font-size: 0.9em; color: #666; }
|
|
.view-btn {
|
|
background: #007bff;
|
|
color: white;
|
|
padding: 5px 15px;
|
|
text-decoration: none;
|
|
border-radius: 3px;
|
|
font-size: 0.9em;
|
|
}
|
|
.view-btn:hover { background: #0056b3; }
|
|
.realtime-btn {
|
|
background: #28a745;
|
|
color: white;
|
|
padding: 10px 20px;
|
|
text-decoration: none;
|
|
border-radius: 5px;
|
|
display: inline-block;
|
|
margin-bottom: 20px;
|
|
}
|
|
.realtime-btn:hover { background: #218838; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>📊 SEO Generator - Log Viewer</h1>
|
|
|
|
<a href="/tools/logs-viewer.html" class="realtime-btn">🔴 Logs en temps réel</a>
|
|
|
|
<div class="log-list">
|
|
<h2>Fichiers de log disponibles</h2>
|
|
<div id="logFiles">Chargement...</div>
|
|
</div>
|
|
|
|
<script>
|
|
async function loadLogFiles() {
|
|
try {
|
|
const response = await fetch('/api/logs');
|
|
const data = await response.json();
|
|
|
|
const container = document.getElementById('logFiles');
|
|
if (data.files.length === 0) {
|
|
container.innerHTML = '<p>Aucun fichier de log trouvé</p>';
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = data.files.map(file => {
|
|
const sizeKB = Math.round(file.size / 1024);
|
|
const date = new Date(file.modified).toLocaleString('fr-FR');
|
|
|
|
return \`
|
|
<div class="log-item">
|
|
<div>
|
|
<div class="log-name">\${file.name}</div>
|
|
<div class="log-info">\${sizeKB} KB • \${date}</div>
|
|
</div>
|
|
<a href="\${file.url}" class="view-btn" target="_blank">Voir</a>
|
|
</div>
|
|
\`;
|
|
}).join('');
|
|
} catch (error) {
|
|
document.getElementById('logFiles').innerHTML =
|
|
'<p style="color: red;">Erreur: ' + error.message + '</p>';
|
|
}
|
|
}
|
|
|
|
loadLogFiles();
|
|
</script>
|
|
</body>
|
|
</html>
|
|
`);
|
|
});
|
|
|
|
// Fonction pour ouvrir automatiquement le dernier log
|
|
function openLatestLog() {
|
|
try {
|
|
const logsDir = path.join(__dirname, '..', 'logs');
|
|
const files = fs.readdirSync(logsDir)
|
|
.filter(file => file.endsWith('.log'))
|
|
.map(file => {
|
|
const filePath = path.join(logsDir, file);
|
|
const stats = fs.statSync(filePath);
|
|
return {
|
|
name: file,
|
|
modified: stats.mtime
|
|
};
|
|
})
|
|
.sort((a, b) => b.modified - a.modified);
|
|
|
|
if (files.length > 0) {
|
|
const latestFile = files[0].name;
|
|
const url = `http://localhost:${PORT}/tools/logs-viewer.html?file=${latestFile}`;
|
|
|
|
// Ouvrir dans le navigateur par défaut
|
|
// Utiliser powershell Start-Process pour ouvrir l'URL dans le navigateur
|
|
const command = 'powershell.exe Start-Process';
|
|
|
|
exec(`${command} "${url}"`, (error) => {
|
|
if (error) {
|
|
console.log(`⚠️ Impossible d'ouvrir automatiquement: ${error.message}`);
|
|
console.log(`🌐 Ouvrez manuellement: ${url}`);
|
|
} else {
|
|
console.log(`🌐 Ouverture automatique du dernier log: ${latestFile}`);
|
|
}
|
|
});
|
|
} else {
|
|
console.log(`📊 Aucun log disponible - accédez à http://localhost:${PORT}/tools/logs-viewer.html`);
|
|
}
|
|
} catch (error) {
|
|
console.log(`⚠️ Erreur lors de l'ouverture: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`🚀 Log server running at http://localhost:${PORT}`);
|
|
console.log(`📊 Logs viewer: http://localhost:${PORT}/tools/logs-viewer.html`);
|
|
console.log(`📁 Logs directory: ${path.join(__dirname, '..', 'logs')}`);
|
|
|
|
// Attendre un peu que le serveur soit prêt, puis ouvrir le navigateur
|
|
setTimeout(openLatestLog, 1000);
|
|
}); |