From 4aa99beaff70674e3cbe62d22eab77924b8bc1f4 Mon Sep 17 00:00:00 2001 From: "Myan V." <155415707+myanvoos@users.noreply.github.com> Date: Thu, 21 Nov 2024 21:45:08 +1300 Subject: [PATCH] Better error handling for target ports conflict (#126) * feat: add error message when port 3000 is already in use * feat: expand port availability checking * refactor: improve port extraction code modularity * fix: formatting * fix: clippy * fix: move port checking logic to tuono crate * fix(tuono): make main async * fix: tokio panicking when testing CLI * feat: working port conflict detection in crate tuono * fix: passing format and lint checks * refactor: refactor cli by making it non-async * refactor: move port constants to module scope and remove unnecessary Result return type from port checker --- crates/tuono/src/cli.rs | 34 ++++++++++++++++++++++++++++++++++ crates/tuono/src/watch.rs | 2 +- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/crates/tuono/src/cli.rs b/crates/tuono/src/cli.rs index 27f96a20..f00b3bd1 100644 --- a/crates/tuono/src/cli.rs +++ b/crates/tuono/src/cli.rs @@ -11,6 +11,9 @@ use crate::scaffold_project; use crate::source_builder::{bundle_axum_source, check_tuono_folder, create_client_entry_files}; use crate::watch; +const TUONO_PORT: u16 = 3000; +const VITE_PORT: u16 = 3001; + #[derive(Subcommand, Debug)] enum Actions { /// Start the development environment @@ -47,12 +50,41 @@ fn init_tuono_folder(mode: Mode) -> std::io::Result<()> { Ok(()) } +fn check_ports(mode: Mode) { + let rust_listener = std::net::TcpListener::bind(format!("0.0.0.0:{TUONO_PORT}")); + + if let Err(_e) = rust_listener { + eprintln!("Error: Failed to bind to port {}", TUONO_PORT); + eprintln!( + "Please ensure that port {} is not already in use by another process or application.", + TUONO_PORT + ); + std::process::exit(1); + } + + if mode == Mode::Dev { + let vite_listener = std::net::TcpListener::bind(format!("0.0.0.0:{VITE_PORT}")); + + if let Err(_e) = vite_listener { + eprintln!("Error: Failed to bind to port {}", VITE_PORT); + eprintln!( + "Please ensure that port {} is not already in use by another process or application.", + VITE_PORT + ); + std::process::exit(1); + } + } +} + pub fn app() -> std::io::Result<()> { let args = Args::parse(); match args.action { Actions::Dev => { + check_ports(Mode::Dev); + init_tuono_folder(Mode::Dev)?; + watch::watch().unwrap(); } Actions::Build { ssg } => { @@ -68,6 +100,8 @@ pub fn app() -> std::io::Result<()> { app.build_react_prod(); if ssg { + check_ports(Mode::Prod); + println!("SSG: generation started"); let static_dir = PathBuf::from("out/static"); diff --git a/crates/tuono/src/watch.rs b/crates/tuono/src/watch.rs index 8a1b1dc9..1ab080d4 100644 --- a/crates/tuono/src/watch.rs +++ b/crates/tuono/src/watch.rs @@ -77,7 +77,7 @@ pub async fn watch() -> Result<()> { if should_reload_rust_server { println!(" Reloading..."); run_server.stop(); - bundle_axum_source(Mode::Dev).expect("Failed to bunlde rust source"); + bundle_axum_source(Mode::Dev).expect("Failed to bundle rust source"); run_server.start(); }