use clap::Parser;
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[command(name = "servile", about = "Serve a directory over HTTP with live-reload")]
pub struct Config {
#[arg(long, default_value = "127.0.0.1")]
pub host: String,
#[arg(long, default_value_t = 8080)]
pub port: u16,
#[arg(default_value = ".")]
pub dir: PathBuf,
#[arg(long, default_value_t = 200)]
pub debounce: u64,
}
#[tokio::main]
async fn main() {
let config = Config::parse();
let addr = format!("{}:{}", config.host, config.port);
let app = servile_cli::build_router(&config.dir, config.debounce);
let listener = tokio::net::TcpListener::bind(&addr)
.await
.unwrap_or_else(|e| panic!("failed to bind to {addr}: {e}"));
eprintln!("serving {} on http://{addr}", config.dir.display());
axum::serve(listener, app).await.unwrap();
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_defaults() {
let config = Config::parse_from(["servile"]);
assert_eq!(config.host, "127.0.0.1");
assert_eq!(config.port, 8080);
assert_eq!(config.dir, PathBuf::from("."));
assert_eq!(config.debounce, 200);
}
#[test]
fn parse_custom_args() {
let config = Config::parse_from([
"servile",
"--host", "0.0.0.0",
"--port", "3000",
"--debounce", "500",
"/tmp/site",
]);
assert_eq!(config.host, "0.0.0.0");
assert_eq!(config.port, 3000);
assert_eq!(config.dir, PathBuf::from("/tmp/site"));
assert_eq!(config.debounce, 500);
}
}