diff --git a/crates/tuono/Cargo.toml b/crates/tuono/Cargo.toml index bf71ef21..d433a94e 100644 --- a/crates/tuono/Cargo.toml +++ b/crates/tuono/Cargo.toml @@ -5,15 +5,12 @@ edition = "2021" authors = ["V. Ageno "] description = "Superfast React fullstack framework" homepage = "https://tuono.dev" -keywords = [ "react", "typescript", "fullstack", "web", "ssr"] +keywords = ["react", "typescript", "fullstack", "web", "ssr"] repository = "/~https://github.com/tuono-labs/tuono" readme = "../../README.md" license-file = "../../LICENSE.md" categories = ["web-programming"] -include = [ - "src/*.rs", - "Cargo.toml" -] +include = ["src/*.rs", "Cargo.toml"] [lib] name = "tuono" @@ -29,7 +26,7 @@ serde = { version = "1.0.202", features = ["derive"] } watchexec-supervisor = "3.0.0" glob = "0.3.1" regex = "1.10.4" -reqwest = {version = "0.12.4", features =["blocking", "json"]} +reqwest = { version = "0.12.4", features = ["blocking", "json"] } serde_json = "1.0" fs_extra = "1.3.0" http = "1.1.0" diff --git a/crates/tuono/src/app.rs b/crates/tuono/src/app.rs index 1f1bef0b..be569ece 100644 --- a/crates/tuono/src/app.rs +++ b/crates/tuono/src/app.rs @@ -6,6 +6,7 @@ use std::collections::{hash_map::Entry, HashMap}; use std::fs::File; use std::io::prelude::*; use std::io::BufReader; +use std::path::Path; use std::path::PathBuf; use std::process::Child; use std::process::Command; @@ -138,9 +139,18 @@ impl App { } pub fn build_react_prod(&self) { - Command::new(BUILD_JS_SCRIPT) + if !Path::new(BUILD_JS_SCRIPT).exists() { + eprintln!("Failed to find the build script. Please run `npm install`"); + std::process::exit(1); + } + let output = Command::new(BUILD_JS_SCRIPT) .output() .expect("Failed to build the react source"); + if !output.status.success() { + eprintln!("Failed to build the react source"); + eprintln!("Error: {}", String::from_utf8_lossy(&output.stderr)); + std::process::exit(1); + } } pub fn run_rust_server(&self) -> Child { @@ -154,6 +164,10 @@ impl App { } pub fn build_tuono_config(&self) -> Result { + if !Path::new(BUILD_TUONO_CONFIG).exists() { + eprintln!("Failed to find the build script. Please run `npm install`"); + std::process::exit(1); + } Command::new(BUILD_TUONO_CONFIG) .stdin(Stdio::piped()) .stdout(Stdio::piped()) diff --git a/crates/tuono/src/watch.rs b/crates/tuono/src/watch.rs index fc81e834..e2fbf489 100644 --- a/crates/tuono/src/watch.rs +++ b/crates/tuono/src/watch.rs @@ -1,3 +1,4 @@ +use std::path::Path; use std::sync::Arc; use watchexec_supervisor::command::{Command, Program}; @@ -20,6 +21,10 @@ const DEV_WATCH_BIN_SRC: &str = "node_modules/.bin/tuono-dev-watch"; const DEV_SSR_BIN_SRC: &str = "node_modules/.bin/tuono-dev-ssr"; fn watch_react_src() -> Job { + if !Path::new(DEV_SSR_BIN_SRC).exists() { + eprintln!("Failed to find script to run dev watch. Please run `npm install`"); + std::process::exit(1); + } start_job(Arc::new(Command { program: Program::Exec { prog: DEV_WATCH_BIN_SRC.into(), @@ -42,6 +47,10 @@ fn build_rust_src() -> Job { } fn build_react_ssr_src() -> Job { + if !Path::new(DEV_SSR_BIN_SRC).exists() { + eprintln!("Failed to find script to run dev ssr. Please run `npm install`"); + std::process::exit(1); + } start_job(Arc::new(Command { program: Program::Exec { prog: DEV_SSR_BIN_SRC.into(), diff --git a/crates/tuono/tests/cli_tests.rs b/crates/tuono/tests/cli_build.rs similarity index 78% rename from crates/tuono/tests/cli_tests.rs rename to crates/tuono/tests/cli_build.rs index 5bc194b1..54b4469b 100644 --- a/crates/tuono/tests/cli_tests.rs +++ b/crates/tuono/tests/cli_build.rs @@ -12,7 +12,7 @@ const GET_API_FILE: &str = r"#[tuono_lib::api(GET)]"; fn it_successfully_create_the_index_route() { let temp_tuono_project = TempTuonoProject::new(); - temp_tuono_project.add_route("./src/routes/index.rs"); + temp_tuono_project.add_file("./src/routes/index.rs"); let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); test_tuono_build @@ -38,7 +38,7 @@ fn it_successfully_create_the_index_route() { fn it_successfully_create_an_api_route() { let temp_tuono_project = TempTuonoProject::new(); - temp_tuono_project.add_api("./src/routes/api/health_check.rs", POST_API_FILE); + temp_tuono_project.add_file_with_content("./src/routes/api/health_check.rs", POST_API_FILE); let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); test_tuono_build @@ -67,7 +67,7 @@ fn it_successfully_create_an_api_route() { fn it_successfully_create_multiple_api_for_the_same_file() { let temp_tuono_project = TempTuonoProject::new(); - temp_tuono_project.add_api( + temp_tuono_project.add_file_with_content( "./src/routes/api/health_check.rs", &format!("{POST_API_FILE}{GET_API_FILE}"), ); @@ -100,9 +100,9 @@ fn it_successfully_create_multiple_api_for_the_same_file() { fn it_successfully_create_catch_all_routes() { let temp_tuono_project = TempTuonoProject::new(); - temp_tuono_project.add_route("./src/routes/[...all_routes].rs"); + temp_tuono_project.add_file("./src/routes/[...all_routes].rs"); - temp_tuono_project.add_api( + temp_tuono_project.add_file_with_content( "./src/routes/api/[...all_apis].rs", &format!("{POST_API_FILE}"), ); @@ -140,3 +140,36 @@ fn it_successfully_create_catch_all_routes() { assert!(temp_main_rs_content .contains(r#".route("/__tuono/data/*all_routes", get(dyn_catch_all_all_routes::tuono__internal__api))"#)); } + +#[test] +#[serial] +fn it_fails_without_installed_build_config_script() { + TempTuonoProject::new(); + + let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); + test_tuono_build + .arg("build") + .assert() + .failure() + .stderr("Failed to find the build script. Please run `npm install`\n"); +} + +#[test] +#[serial] +fn it_fails_without_installed_build_script() { + let temp_tuono_project = TempTuonoProject::new(); + + temp_tuono_project + .add_file_with_content("./node_modules/.bin/tuono-build-config", "#!/bin/bash"); + Command::new("chmod") + .arg("+x") + .arg("./node_modules/.bin/tuono-build-config") + .assert() + .success(); + let mut test_tuono_build = Command::cargo_bin("tuono").unwrap(); + test_tuono_build + .arg("build") + .assert() + .failure() + .stderr("Failed to find the build script. Please run `npm install`\n"); +} diff --git a/crates/tuono/tests/utils.rs b/crates/tuono/tests/utils.rs index f46ceb52..0396669e 100644 --- a/crates/tuono/tests/utils.rs +++ b/crates/tuono/tests/utils.rs @@ -28,17 +28,17 @@ impl TempTuonoProject { self.temp_dir.path() } - pub fn add_route<'a>(&self, path: &'a str) { + pub fn add_file<'a>(&self, path: &'a str) -> File { let path = PathBuf::from(path); create_all( path.parent().expect("Route path does not have any parent"), false, ) .expect("Failed to create parent route directory"); - File::create(path).expect("Failed to create the route file"); + File::create(path).expect("Failed to create the route file") } - pub fn add_api<'a>(&self, path: &'a str, content: &'a str) { + pub fn add_file_with_content<'a>(&self, path: &'a str, content: &'a str) { let path = PathBuf::from(path); create_all( path.parent().expect("Route path does not have any parent"),