Spaces:
Runtime error
Runtime error
| from fastapi import FastAPI, HTTPException, WebSocket | |
| from fastapi.responses import HTMLResponse | |
| from pydantic import BaseModel | |
| import uvicorn | |
| import logging | |
| from typing import Dict, List, Any | |
| import json | |
| from database_engineer import AutomaticDatabaseEngineer | |
| app = FastAPI(title="Ingénieur DB Automatique", version="1.0.0") | |
| db_engineer = AutomaticDatabaseEngineer() | |
| class DatabaseConnection(BaseModel): | |
| db_type: str | |
| host: str = "localhost" | |
| port: int = None | |
| database: str | |
| username: str = None | |
| password: str = None | |
| class SQLQuery(BaseModel): | |
| connection_id: str | |
| query: str | |
| auto_fix: bool = True | |
| def engineer_interface(): | |
| return """ | |
| <!DOCTYPE html> | |
| <html lang="fr"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Ingénieur DB Automatique</title> | |
| <style> | |
| :root { | |
| --primary: #2563eb; | |
| --secondary: #1e40af; | |
| --success: #10b981; | |
| --warning: #f59e0b; | |
| --danger: #ef4444; | |
| } | |
| body { | |
| font-family: 'Segoe UI', system-ui, sans-serif; | |
| margin: 0; | |
| padding: 20px; | |
| background: #f8fafc; | |
| } | |
| .container { | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| } | |
| .card { | |
| background: white; | |
| border-radius: 10px; | |
| padding: 20px; | |
| margin-bottom: 20px; | |
| box-shadow: 0 2px 10px rgba(0,0,0,0.1); | |
| } | |
| .connection-form { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 15px; | |
| } | |
| .query-editor { | |
| width: 100%; | |
| height: 200px; | |
| font-family: monospace; | |
| padding: 10px; | |
| border: 1px solid #ddd; | |
| border-radius: 5px; | |
| } | |
| .btn { | |
| padding: 10px 20px; | |
| border: none; | |
| border-radius: 5px; | |
| cursor: pointer; | |
| font-weight: bold; | |
| } | |
| .btn-primary { background: var(--primary); color: white; } | |
| .btn-success { background: var(--success); color: white; } | |
| .btn-warning { background: var(--warning); color: white; } | |
| .result-panel { | |
| background: #1e293b; | |
| color: white; | |
| padding: 15px; | |
| border-radius: 5px; | |
| margin-top: 10px; | |
| font-family: monospace; | |
| max-height: 400px; | |
| overflow-y: auto; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <h1>🧠 Ingénieur Base de Données Automatique</h1> | |
| <div class="card"> | |
| <h2>🔌 Connexion Base de Données</h2> | |
| <div class="connection-form"> | |
| <select id="dbType"> | |
| <option value="sqlite">SQLite</option> | |
| <option value="mysql">MySQL</option> | |
| <option value="postgresql">PostgreSQL</option> | |
| </select> | |
| <input type="text" id="host" placeholder="Host (localhost)"> | |
| <input type="number" id="port" placeholder="Port"> | |
| <input type="text" id="database" placeholder="Nom base" required> | |
| <input type="text" id="username" placeholder="Utilisateur"> | |
| <input type="password" id="password" placeholder="Mot de passe"> | |
| <button class="btn btn-primary" onclick="connectDatabase()">Se connecter</button> | |
| </div> | |
| </div> | |
| <div class="card"> | |
| <h2>⚡ Exécuteur Intelligent de Requêtes</h2> | |
| <textarea class="query-editor" id="queryInput" placeholder="Entrez votre requête SQL ici..."></textarea> | |
| <div style="margin-top: 10px;"> | |
| <button class="btn btn-success" onclick="executeQuery()">Exécuter avec Correction Auto</button> | |
| <button class="btn btn-warning" onclick="analyzeQuery()">Analyser la Requête</button> | |
| <label><input type="checkbox" id="autoFix" checked> Correction automatique</label> | |
| </div> | |
| <div class="result-panel" id="queryResult"></div> | |
| </div> | |
| <div class="card"> | |
| <h2>🚀 Optimisation Automatique</h2> | |
| <button class="btn btn-primary" onclick="optimizeDatabase()">Optimiser Base de Données</button> | |
| <button class="btn btn-success" onclick="autoMigration()">Migration Intelligente</button> | |
| <button class="btn btn-warning" onclick="startMonitoring()">Surveillance Temps Réel</button> | |
| <div class="result-panel" id="optimizationResult"></div> | |
| </div> | |
| </div> | |
| <script> | |
| let currentConnectionId = null; | |
| async function connectDatabase() { | |
| const params = { | |
| db_type: document.getElementById('dbType').value, | |
| host: document.getElementById('host').value, | |
| port: document.getElementById('port').value, | |
| database: document.getElementById('database').value, | |
| username: document.getElementById('username').value, | |
| password: document.getElementById('password').value | |
| }; | |
| try { | |
| const response = await fetch('/api/connect', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/json'}, | |
| body: JSON.stringify(params) | |
| }); | |
| const data = await response.json(); | |
| if (data.success) { | |
| currentConnectionId = data.connection_id; | |
| showResult('queryResult', `✅ Connecté: ${data.connection_id}`); | |
| } else { | |
| showResult('queryResult', `❌ Erreur: ${data.error}`); | |
| } | |
| } catch (error) { | |
| showResult('queryResult', `❌ Erreur: ${error}`); | |
| } | |
| } | |
| async function executeQuery() { | |
| if (!currentConnectionId) { | |
| alert('Veuillez d\'abord vous connecter à une base de données'); | |
| return; | |
| } | |
| const query = document.getElementById('queryInput').value; | |
| const autoFix = document.getElementById('autoFix').checked; | |
| try { | |
| const response = await fetch('/api/execute', { | |
| method: 'POST', | |
| headers: {'Content-Type': 'application/json'}, | |
| body: JSON.stringify({ | |
| connection_id: currentConnectionId, | |
| query: query, | |
| auto_fix: autoFix | |
| }) | |
| }); | |
| const data = await response.json(); | |
| showResult('queryResult', JSON.stringify(data, null, 2)); | |
| } catch (error) { | |
| showResult('queryResult', `❌ Erreur: ${error}`); | |
| } | |
| } | |
| async function optimizeDatabase() { | |
| if (!currentConnectionId) { | |
| alert('Veuillez d\'abord vous connecter à une base de données'); | |
| return; | |
| } | |
| try { | |
| const response = await fetch(`/api/optimize/${currentConnectionId}`, { | |
| method: 'POST' | |
| }); | |
| const data = await response.json(); | |
| showResult('optimizationResult', JSON.stringify(data, null, 2)); | |
| } catch (error) { | |
| showResult('optimizationResult', `❌ Erreur: ${error}`); | |
| } | |
| } | |
| function showResult(panelId, content) { | |
| document.getElementById(panelId).textContent = content; | |
| } | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| async def connect_database(connection: DatabaseConnection): | |
| try: | |
| connection_id = await db_engineer.connect_database( | |
| connection.db_type, | |
| connection.dict() | |
| ) | |
| return {"success": True, "connection_id": connection_id} | |
| except Exception as e: | |
| return {"success": False, "error": str(e)} | |
| async def execute_query(query: SQLQuery): | |
| result = await db_engineer.execute_and_fix_query( | |
| query.connection_id, | |
| query.query, | |
| query.auto_fix | |
| ) | |
| return result | |
| async def optimize_database(connection_id: str): | |
| result = await db_engineer.auto_optimize_database(connection_id) | |
| return result | |
| async def migrate_database(connection_id: str, target_schema: Dict): | |
| result = await db_engineer.intelligent_migration(connection_id, target_schema) | |
| return result | |
| async def websocket_monitor(websocket: WebSocket, connection_id: str): | |
| await websocket.accept() | |
| try: | |
| while True: | |
| monitoring_data = await db_engineer.real_time_monitoring(connection_id) | |
| await websocket.send_json(monitoring_data) | |
| await asyncio.sleep(5) # Update every 5 seconds | |
| except Exception as e: | |
| logging.error(f"WebSocket error: {e}") | |
| if __name__ == "__main__": | |
| uvicorn.run(app, host="0.0.0.0", port=8000) |