avl_console/
lib.rs

1//! # AVL Console - Developer Portal & Web Dashboard
2//!
3//! **World-class developer portal** for AVL Cloud Platform.
4//!
5//! ## Features
6//!
7//! - **Dashboard**: Real-time resource overview with WebSocket updates
8//! - **AvilaDB Explorer**: Interactive query editor with syntax highlighting
9//! - **Storage Browser**: Full S3-compatible file management
10//! - **Observability**: Metrics, logs, traces with advanced filtering
11//! - **Billing**: Cost tracking, usage analytics, budget alerts
12//! - **API Explorer**: Interactive API testing with OpenAPI specs
13//! - **User Management**: Teams, permissions, audit logs
14//!
15//! ## Architecture
16//!
17//! ```text
18//! ┌─────────────────────────────────────────────────┐
19//! │              AVL Console Frontend               │
20//! │  (Server-Side Rendered + Real-Time WebSocket)   │
21//! └─────────────────────────────────────────────────┘
22//!                        ↓
23//! ┌─────────────────────────────────────────────────┐
24//! │              Axum REST API Layer                │
25//! │  (Authentication, Rate Limiting, CORS)          │
26//! └─────────────────────────────────────────────────┘
27//!                        ↓
28//! ┌──────────────┬──────────────┬──────────────────┐
29//! │   AvilaDB    │   Storage    │   Observability  │
30//! │   Explorer   │   Browser    │   Dashboard      │
31//! └──────────────┴──────────────┴──────────────────┘
32//! ```
33//!
34//! ## Quick Start
35//!
36//! ```rust,no_run
37//! use avl_console::{Console, ConsoleConfig};
38//! use std::net::SocketAddr;
39//!
40//! #[tokio::main]
41//! async fn main() -> anyhow::Result<()> {
42//!     let config = ConsoleConfig::from_env()?;
43//!     let console = Console::new(config).await?;
44//!     let addr: SocketAddr = "127.0.0.1:8080".parse()?;
45//!
46//!     console.serve(addr).await?;
47//!     Ok(())
48//! }
49//! ```
50
51pub mod api;
52pub mod auth;
53pub mod config;
54pub mod dashboard;
55pub mod database;
56pub mod error;
57pub mod middleware;
58pub mod observability;
59pub mod storage;
60pub mod billing;
61pub mod templates;
62pub mod websocket;
63pub mod state;
64pub mod query_builder;
65pub mod monitoring;
66pub mod teams;
67pub mod ai_assistant;
68pub mod ai_engine;
69
70use std::net::SocketAddr;
71use std::sync::Arc;
72
73use axum::Router;
74use tower::ServiceBuilder;
75use tower_http::{
76    services::ServeDir,
77    trace::TraceLayer,
78    compression::CompressionLayer,
79    cors::CorsLayer,
80};
81
82pub use config::ConsoleConfig;
83pub use error::{ConsoleError, Result};
84pub use state::AppState;
85
86/// AVL Console - Main application structure
87///
88/// Manages the entire console lifecycle including:
89/// - HTTP server with Axum
90/// - WebSocket connections for real-time updates
91/// - Authentication and authorization
92/// - Resource management (databases, storage, etc.)
93#[derive(Clone)]
94pub struct Console {
95    state: Arc<AppState>,
96    config: ConsoleConfig,
97}
98
99impl Console {
100    /// Create a new Console instance
101    ///
102    /// # Example
103    ///
104    /// ```rust,no_run
105    /// # use avl_console::{Console, ConsoleConfig};
106    /// # async fn example() -> anyhow::Result<()> {
107    /// let config = ConsoleConfig::default();
108    /// let console = Console::new(config).await?;
109    /// # Ok(())
110    /// # }
111    /// ```
112    pub async fn new(config: ConsoleConfig) -> Result<Self> {
113        let state = Arc::new(AppState::new(&config).await?);
114
115        Ok(Self { state, config })
116    }
117
118    /// Build the Axum router with all routes and middleware
119    pub fn router(&self) -> Router {
120        Router::new()
121            // API routes
122            .nest("/api", api::routes(self.state.clone()))
123            // Dashboard routes
124            .nest("/dashboard", dashboard::routes(self.state.clone()))
125            // Database explorer
126            .nest("/databases", database::routes(self.state.clone()))
127            // Storage browser
128            .nest("/storage", storage::routes(self.state.clone()))
129            // Observability
130            .nest("/observability", observability::routes(self.state.clone()))
131            // Billing
132            .nest("/billing", billing::routes(self.state.clone()))
133            // Query Builder
134            .nest("/query-builder", query_builder::router(self.state.clone()))
135            // Advanced Monitoring
136            .nest("/monitoring", monitoring::router(self.state.clone()))
137            // Team Management & RBAC
138            .nest("/teams", teams::router(self.state.clone()))
139            // AI Assistant
140            .nest("/ai-assistant", ai_assistant::router(self.state.clone()))
141            // WebSocket endpoint
142            .nest("/ws", websocket::routes(self.state.clone()))
143            // Static files
144            .nest_service("/static", ServeDir::new("static"))
145            // Root redirect to dashboard
146            .fallback(dashboard::index)
147            .layer(
148                ServiceBuilder::new()
149                    .layer(TraceLayer::new_for_http())
150                    .layer(CompressionLayer::new())
151                    .layer(CorsLayer::permissive())
152                    .layer(middleware::auth::AuthLayer::new(self.state.clone()))
153                    .layer(middleware::rate_limit::RateLimitLayer::new())
154            )
155    }
156
157    /// Start the console server
158    ///
159    /// # Example
160    ///
161    /// ```rust,no_run
162    /// # use avl_console::{Console, ConsoleConfig};
163    /// # use std::net::SocketAddr;
164    /// # async fn example() -> anyhow::Result<()> {
165    /// let console = Console::new(ConsoleConfig::default()).await?;
166    /// let addr: SocketAddr = "127.0.0.1:8080".parse()?;
167    /// console.serve(addr).await?;
168    /// # Ok(())
169    /// # }
170    /// ```
171    pub async fn serve(self, addr: impl Into<SocketAddr>) -> Result<()> {
172        let addr = addr.into();
173        let router = self.router();
174
175        tracing::info!("🖥️  AVL Console starting on http://{}", addr);
176        tracing::info!("📊 Dashboard: http://{}/dashboard", addr);
177        tracing::info!("🗄️  AvilaDB Explorer: http://{}/databases", addr);
178        tracing::info!("💾 Storage Browser: http://{}/storage", addr);
179        tracing::info!("📈 Observability: http://{}/observability", addr);
180        tracing::info!("🎨 Query Builder: http://{}/query-builder", addr);
181        tracing::info!("🔬 Advanced Monitoring: http://{}/monitoring", addr);
182        tracing::info!("👥 Team Management: http://{}/teams", addr);
183        tracing::info!("🤖 AI Assistant: http://{}/ai-assistant", addr);
184
185        let listener = tokio::net::TcpListener::bind(addr)
186            .await
187            .map_err(|e| ConsoleError::Server(e.to_string()))?;
188
189        axum::serve(listener, router)
190            .await
191            .map_err(|e| ConsoleError::Server(e.to_string()))?;
192
193        Ok(())
194    }
195
196    /// Get reference to application state
197    pub fn state(&self) -> &Arc<AppState> {
198        &self.state
199    }
200
201    /// Get configuration
202    pub fn config(&self) -> &ConsoleConfig {
203        &self.config
204    }
205}
206
207#[cfg(test)]
208mod tests {
209    use super::*;
210
211    #[tokio::test]
212    async fn test_console_creation() {
213        let config = ConsoleConfig::default();
214        let console = Console::new(config).await;
215        assert!(console.is_ok());
216    }
217}