Files
pmomusic/pmoapp/src/lib.rs

264 lines
7.9 KiB
Rust
Raw Normal View History

//! # pmoapp - Application web UPnP pour PMOMusic
//!
2025-10-06 11:54:32 +02:00
//! Cette crate fournit l'application web frontend pour le contrôle et la visualisation
//! des devices UPnP MediaRenderer, intégrée via RustEmbed pour être servie par pmoserver.
//!
//! ## Vue d'ensemble
//!
//! `pmoapp` est une application Vue.js 3 moderne avec TypeScript qui offre une interface
//! utilisateur pour :
//! - Visualiser les logs système en temps réel (Server-Sent Events)
//! - Contrôler les devices UPnP MediaRenderer
//! - Afficher et formater automatiquement le XML dans les logs
//!
//! ## Fonctionnalités
//!
2025-10-06 11:54:32 +02:00
//! ### 📦 Frontend intégré
//! - Application web compilée et embarquée dans le binaire Rust
//! - Aucun fichier statique externe à gérer en production
//! - Intégration via `RustEmbed` pour une distribution simplifiée
//!
//! ### 🎨 Interface utilisateur
//! - **LogView** : Visualisation des logs en temps réel avec filtres par niveau
//! - **Auto-scroll** : Défilement automatique des nouveaux logs (désactivable)
//! - **Formatage XML** : Détection et coloration syntaxique automatique du XML
//! - **Design responsive** : Compatible desktop et mobile
//! - **Thème sombre** : Style inspiré de VS Code pour une meilleure lisibilité
//!
//! ### 🚀 Zero configuration
//! - Pas besoin de serveur web séparé pour les assets
//! - Les fichiers sont servis directement depuis la mémoire du binaire
//! - Configuration automatique du routing Vue Router
//!
//! ## Architecture
//!
//! ### Stack technique
//!
//! - **Frontend** : Vue.js 3 avec Composition API
//! - **Langage** : TypeScript
//! - **Build** : Vite (rapide, moderne, HMR)
//! - **Routing** : Vue Router
//! - **Markdown** : Marked.js pour le rendu
//! - **Sécurité** : DOMPurify pour la sanitization HTML
//!
//! ### Structure des fichiers
//!
//! ```text
//! pmoapp/
//! ├── Cargo.toml # Dépendances Rust (rust-embed)
//! ├── src/
//! │ └── lib.rs # Point d'entrée Rust (ce fichier)
//! └── webapp/
//! ├── src/
//! │ ├── main.ts # Point d'entrée Vue.js
//! │ ├── App.vue # Composant racine
//! │ ├── router/ # Configuration Vue Router
//! │ └── components/
//! │ ├── LogView.vue # Visualiseur de logs SSE
//! │ └── ...
//! ├── dist/ # Build output (généré, non versionné)
//! ├── package.json # Dépendances npm
//! └── vite.config.ts # Configuration Vite
//! ```
//!
//! ## Workflow de build
//!
//! ### 1. Build de la webapp (Vue.js)
//!
//! ```bash
//! # Installation des dépendances
//! cd pmoapp/webapp
//! npm install
//!
//! # Build de production
//! npm run build
//! # Génère : webapp/dist/index.html, assets/*.js, assets/*.css
//! ```
//!
//! ### 2. Compilation Rust
//!
//! ```bash
//! cargo build
//! # RustEmbed inclut automatiquement les fichiers de webapp/dist/
//! ```
//!
//! ### 3. Utilisation avec Makefile
//!
//! ```bash
//! # Build complet (webapp + Rust)
//! make build
//!
//! # Ou juste la webapp
//! make webapp
//!
//! # Clean
//! make clean
//! ```
//!
//! ## Utilisation
//!
2025-10-06 11:54:32 +02:00
//! ### Exemple basique
//!
//! ```rust,no_run
//! use pmoapp::Webapp;
//! use pmoserver::ServerBuilder;
//!
2025-10-06 11:54:32 +02:00
//! #[tokio::main]
//! async fn main() {
//! let mut server = ServerBuilder::new("MyApp")
//! .http_port(8080)
//! .build();
//!
//! // Ajouter la webapp comme Single Page Application
//! server.add_spa::<Webapp>("/app").await;
//!
//! // Ajouter une redirection de la racine vers /app
//! server.add_redirect("/", "/app").await;
//!
//! server.start().await;
//! server.wait().await;
//! }
//! ```
//!
2025-10-06 11:54:32 +02:00
//! ### Exemple avec logs SSE
//!
//! ```rust,no_run
//! use pmoapp::Webapp;
//! use pmoserver::{ServerBuilder, logs::{LogState, SseLayer}};
//! use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
//!
//! #[tokio::main]
//! async fn main() {
//! // Configuration des logs avec SSE
//! let log_state = LogState::new(1000); // Buffer de 1000 logs
//! tracing_subscriber::registry()
//! .with(tracing_subscriber::fmt::layer())
//! .with(SseLayer::new(log_state.clone()))
//! .init();
//!
//! let mut server = ServerBuilder::new("MyApp").build();
//!
//! // Endpoints SSE pour les logs
//! server.add_handler_with_state("/log-sse", pmoserver::logs::log_sse, log_state.clone()).await;
//! server.add_handler_with_state("/log-dump", pmoserver::logs::log_dump, log_state).await;
//!
//! // Webapp (consommera les logs via /log-sse)
//! server.add_spa::<Webapp>("/app").await;
//! server.add_redirect("/", "/app").await;
//!
//! server.start().await;
//! server.wait().await;
//! }
//! ```
//!
//! ## Développement
//!
//! ### Mode développement Vue.js
//!
//! Pour développer la webapp avec Hot Module Replacement :
//!
//! ```bash
//! cd pmoapp/webapp
//! npm run dev
//! # Serveur de dev sur http://localhost:5173
//! ```
//!
//! ### Rebuild après modifications
//!
//! Après avoir modifié le code Vue.js :
//!
//! ```bash
//! # Rebuild webapp + recompile Rust
//! make build
//!
//! # Ou séparément
//! make webapp # Build Vue.js seulement
//! cargo build # Recompile Rust (intègre le nouveau dist/)
//! ```
//!
//! ## Composants Vue.js
//!
//! ### LogView
//!
//! Composant principal pour la visualisation des logs :
//!
//! - **Connexion SSE** : Stream temps réel via EventSource
//! - **Filtrage** : Par niveau (TRACE, DEBUG, INFO, WARN, ERROR)
//! - **Auto-scroll** : Activable/désactivable
//! - **Formatage** : Markdown + détection XML automatique
//! - **Buffer** : Limite à 1000 logs en mémoire
//! - **Déduplication** : Évite les logs en double
//!
//! ### Formatage XML
//!
//! Le composant LogView détecte automatiquement le XML dans les messages :
//!
//! ```
//! Input: "INFO: <?xml version=\"1.0\"?><scpd>...</scpd>"
//! Output: Bloc de code avec coloration syntaxique XML
//! ```
//!
//! - Détection via regex : `<?xml` ou balises courantes (`<scpd>`, `<service>`, etc.)
//! - Conversion en bloc markdown : ` ```xml ... ``` `
//! - Rendu avec coloration et scrollbar pour le XML long
//!
//! ## Intégration avec pmoupnp
//!
//! La webapp communique avec les devices UPnP via les endpoints HTTP fournis par
//! `pmoserver` et `pmoupnp` :
//!
//! - `/log-sse` : Stream de logs (Server-Sent Events)
//! - `/log-dump` : Historique des logs
//! - `/device/*/description.xml` : Descripteurs UPnP
//! - `/service/*/control` : Endpoints de contrôle SOAP
//! - `/service/*/event` : Souscription aux événements UPnP
//!
//! ## Notes de déploiement
//!
//! ### Taille du binaire
//!
//! La webapp ajoutera ~150KB au binaire (compressé avec gzip par RustEmbed).
//!
//! ### Cache du navigateur
//!
//! Les assets sont servis avec des hashes dans les noms de fichiers
//! (`index-BBZcSinC.js`) pour un cache busting automatique.
//!
//! ### Compatibilité navigateurs
//!
//! - Chrome/Edge : ✅ Moderne
//! - Firefox : ✅ Moderne
//! - Safari : ✅ iOS 13+
//! - IE11 : ❌ Non supporté (utilise ES modules)
//!
//! ## Voir aussi
//!
2025-10-06 11:54:32 +02:00
//! - [`pmoserver`] : Serveur HTTP Axum pour servir la webapp
//! - [`pmoupnp`] : Bibliothèque UPnP MediaRenderer
//! - [Vue.js Documentation](https://vuejs.org/)
//! - [Vite Documentation](https://vitejs.dev/)
use rust_embed::RustEmbed;
/// Structure représentant l'application web embarquée.
///
/// Cette structure utilise `RustEmbed` pour inclure tous les fichiers
/// du répertoire `webapp/dist` dans le binaire au moment de la compilation.
///
/// ## Exemple
///
/// ```rust,no_run
/// use pmoapp::Webapp;
/// use pmoserver::ServerBuilder;
///
/// # async fn example() {
/// let mut server = ServerBuilder::new("MyApp").build();
///
/// // Ajouter la webapp comme SPA sur le chemin /app
/// server.add_spa::<Webapp>("/app").await;
/// # }
/// ```
#[derive(RustEmbed, Clone)]
#[folder = "webapp/dist"]
pub struct Webapp;