use serde::{Deserialize, Serialize};
pub const DEFAULT_HMR_PORT: u16 = 31313;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum HmrMessage {
FullReload,
HotReload { module_path: String },
KeepWindow,
}
pub fn hmr_config() -> Option<u16> {
let hmr_enabled = std::env::var("VELOX_HMR").as_deref() == Ok("1");
if !hmr_enabled {
return None;
}
let port = std::env::var("VELOX_HMR_PORT")
.ok()
.and_then(|s| s.parse::<u16>().ok())
.unwrap_or(DEFAULT_HMR_PORT);
Some(port)
}
pub fn run_hmr_client(port: u16, tx: std::sync::mpsc::Sender<HmrMessage>) {
std::thread::spawn(move || {
let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
loop {
match std::net::TcpStream::connect(("127.0.0.1", port)) {
Ok(stream) => {
eprintln!(
"[velox] HMR client connected to dev server on port {}",
port
);
let reader = std::io::BufReader::new(stream);
for line in std::io::BufRead::lines(reader) {
match line {
Ok(json) => match serde_json::from_str::<HmrMessage>(&json) {
Ok(msg) => {
if tx.send(msg.clone()).is_err() {
return;
}
if msg == HmrMessage::FullReload {
std::process::exit(0);
}
}
Err(e) => {
eprintln!("[velox] HMR: failed to parse message: {}", e);
}
},
Err(e) => {
eprintln!("[velox] HMR connection error: {}", e);
break;
}
}
}
}
Err(e) => {
eprintln!(
"[velox] HMR client: connection to port {} failed: {} — retrying...",
port, e
);
}
}
std::thread::sleep(std::time::Duration::from_millis(500));
}
}));
});
}