From 5425d7768c9b2c971c52cf4e7160d0a372186244 Mon Sep 17 00:00:00 2001 From: enzotar Date: Thu, 26 Feb 2026 16:19:33 -0800 Subject: [PATCH] feat: dev server improvements - recursive watching, auto-open browser - Recursive file watching: catches imported file changes from registry/ - Auto-detect project root: walks up to find registry/ or examples/ dir - Auto-open browser on startup (xdg-open/open/cmd) - Verified HMR live reload: 0ms recompile on file save --- compiler/ds-cli/src/main.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/compiler/ds-cli/src/main.rs b/compiler/ds-cli/src/main.rs index 7570356..7cd4a6c 100644 --- a/compiler/ds-cli/src/main.rs +++ b/compiler/ds-cli/src/main.rs @@ -347,10 +347,28 @@ h2 {{ color: #f87171; margin-bottom: 16px; }} } }).expect("Failed to create file watcher"); - watcher.watch(&watch_dir, RecursiveMode::NonRecursive) + watcher.watch(&watch_dir, RecursiveMode::Recursive) .expect("Failed to watch directory"); - println!("👁 Watching {} for changes", watch_dir.display()); + // Also watch project root (for registry/components etc.) + // Walk up from watch_dir to find a directory containing examples/ or registry/ + let mut project_root = watch_dir.clone(); + for _ in 0..5 { + if project_root.join("registry").is_dir() || project_root.join("examples").is_dir() { + if project_root != watch_dir { + let _ = watcher.watch(&project_root, RecursiveMode::Recursive); + println!("👁 Also watching {} (project root)", project_root.display()); + } + break; + } + if let Some(parent) = project_root.parent() { + project_root = parent.to_path_buf(); + } else { + break; + } + } + + println!("👁 Watching {} for changes (recursive)", watch_dir.display()); println!(); // Debounce: coalesce rapid events @@ -418,6 +436,15 @@ h2 {{ color: #f87171; margin-bottom: 16px; }} println!(" Press Ctrl+C to stop"); println!(); + // Auto-open browser + let url = format!("http://localhost:{port}"); + #[cfg(target_os = "linux")] + { let _ = std::process::Command::new("xdg-open").arg(&url).spawn(); } + #[cfg(target_os = "macos")] + { let _ = std::process::Command::new("open").arg(&url).spawn(); } + #[cfg(target_os = "windows")] + { let _ = std::process::Command::new("cmd").args(["/C", "start", &url]).spawn(); } + for request in server.incoming_requests() { let url = request.url().to_string();