From bcb2c91823eae183b381bb834a3a6ca24961109e Mon Sep 17 00:00:00 2001 From: Valerio Ageno <51341197+Valerioageno@users.noreply.github.com> Date: Tue, 26 Nov 2024 21:37:00 +0100 Subject: [PATCH] fix: windows path resolution (#167) --- crates/tuono/Cargo.toml | 2 +- crates/tuono/src/app.rs | 134 ++++++++++++++++---- crates/tuono/src/watch.rs | 14 +- crates/tuono_lib/Cargo.toml | 4 +- crates/tuono_lib/src/ssr.rs | 15 ++- crates/tuono_lib_macros/Cargo.toml | 2 +- packages/fs-router-vite-plugin/package.json | 2 +- packages/lazy-fn-vite-plugin/package.json | 2 +- packages/router/package.json | 2 +- packages/tuono/package.json | 2 +- 10 files changed, 144 insertions(+), 35 deletions(-) diff --git a/crates/tuono/Cargo.toml b/crates/tuono/Cargo.toml index a2112a26..0034d3fa 100644 --- a/crates/tuono/Cargo.toml +++ b/crates/tuono/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tuono" -version = "0.14.2" +version = "0.14.3" edition = "2021" authors = ["V. Ageno "] description = "Superfast React fullstack framework" diff --git a/crates/tuono/src/app.rs b/crates/tuono/src/app.rs index 198000dc..dd813943 100644 --- a/crates/tuono/src/app.rs +++ b/crates/tuono/src/app.rs @@ -16,6 +16,16 @@ use crate::route::Route; const IGNORE_EXTENSIONS: [&str; 3] = ["css", "scss", "sass"]; const IGNORE_FILES: [&str; 1] = ["__root"]; +#[cfg(target_os = "windows")] +const ROUTES_FOLDER_PATH: &str = "\\src\\routes"; +#[cfg(target_os = "windows")] +const BUILD_JS_SCRIPT: &str = ".\\node_modules\\.bin\\tuono-build-prod.cmd"; + +#[cfg(not(target_os = "windows"))] +const ROUTES_FOLDER_PATH: &str = "/src/routes"; +#[cfg(not(target_os = "windows"))] +const BUILD_JS_SCRIPT: &str = "./node_modules/.bin/tuono-build-prod"; + #[derive(Debug)] pub struct App { pub route_map: HashMap, @@ -33,7 +43,7 @@ fn has_app_state(base_path: PathBuf) -> std::io::Result { impl App { pub fn new() -> Self { - let base_path = std::env::current_dir().unwrap(); + let base_path = std::env::current_dir().expect("Failed to read current_dir"); let mut app = App { route_map: HashMap::new(), @@ -47,18 +57,31 @@ impl App { } fn collect_routes(&mut self) { - glob(self.base_path.join("src/routes/**/*.*").to_str().unwrap()) - .expect("Failed to read glob pattern") - .for_each(|entry| { - if self.should_collect_route(&entry) { - self.collect_route(entry) - } - }) + glob( + self.base_path + .join("src/routes/**/*.*") + .to_str() + .expect("Failed to glob routes folder"), + ) + .expect("Failed to read glob pattern") + .for_each(|entry| { + if self.should_collect_route(&entry) { + self.collect_route(entry) + } + }) } fn should_collect_route(&self, entry: &Result) -> bool { - let file_extension = entry.as_ref().unwrap().extension().unwrap(); - let file_name = entry.as_ref().unwrap().file_stem().unwrap(); + let file_extension = entry + .as_ref() + .unwrap() + .extension() + .expect("Failed to read file extension"); + let file_name = entry + .as_ref() + .unwrap() + .file_stem() + .expect("Failed to read file name"); if IGNORE_EXTENSIONS.iter().any(|val| val == &file_extension) { return false; @@ -71,17 +94,23 @@ impl App { } fn collect_route(&mut self, path_buf: Result) { - let entry = path_buf.unwrap(); - let base_path_str = self.base_path.to_str().unwrap(); + let entry = path_buf.expect("Failed to read glob path"); + + let base_path_str = self + .base_path + .to_str() + .expect("Failed to read as str base_path"); let path = entry .to_str() - .unwrap() - .replace(&format!("{base_path_str}/src/routes"), "") + .expect("Failed to read entry as str") + .replace(&format!("{base_path_str}{ROUTES_FOLDER_PATH}"), "") + // Cleanup windows paths + .replace("\\", "/") .replace(".rs", "") .replace(".mdx", "") .replace(".tsx", ""); - if entry.extension().unwrap() == "rs" { + if entry.extension().expect("failed to read entry extension") == "rs" { if let Entry::Vacant(route_map) = self.route_map.entry(path.clone()) { let mut route = Route::new(path); route.update_axum_info(); @@ -103,7 +132,7 @@ impl App { } pub fn build_react_prod(&self) { - Command::new("./node_modules/.bin/tuono-build-prod") + Command::new(BUILD_JS_SCRIPT) .output() .expect("Failed to build the react source"); } @@ -145,8 +174,27 @@ mod tests { #[test] fn should_collect_routes() { let mut app = App::new(); - app.base_path = "/home/user/Documents/tuono".into(); + #[cfg(target_os = "windows")] + let base_path = "\\home\\user\\Documents\\tuono"; + #[cfg(not(target_os = "windows"))] + let base_path = "/home/user/Documents/tuono"; + + app.base_path = base_path.into(); + + #[cfg(target_os = "windows")] + let routes = [ + "\\home\\user\\Documents\\tuono\\src\\routes\\about.rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\index.rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\posts\\index.rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\posts\\[post].rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\posts\\handle-this.rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\posts\\handle-this\\[post].rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\posts\\UPPERCASE.rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\sitemap.xml.rs", + ]; + + #[cfg(not(target_os = "windows"))] let routes = [ "/home/user/Documents/tuono/src/routes/about.rs", "/home/user/Documents/tuono/src/routes/index.rs", @@ -193,8 +241,25 @@ mod tests { #[test] fn should_create_multi_level_axum_paths() { let mut app = App::new(); - app.base_path = "/home/user/Documents/tuono".into(); + #[cfg(target_os = "windows")] + let base_path = "\\home\\user\\Documents\\tuono"; + + #[cfg(not(target_os = "windows"))] + let base_path = "/home/user/Documents/tuono"; + + app.base_path = base_path.into(); + + #[cfg(target_os = "windows")] + let routes = [ + "\\home\\user\\Documents\\tuono\\src\\routes\\about.rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\index.rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\posts\\index.rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\posts\\any-post.rs", + "\\home\\user\\Documents\\tuono\\src\\routes\\posts\\[post].rs", + ]; + + #[cfg(not(target_os = "windows"))] let routes = [ "/home/user/Documents/tuono/src/routes/about.rs", "/home/user/Documents/tuono/src/routes/index.rs", @@ -219,7 +284,7 @@ mod tests { assert_eq!( app.route_map .get(path) - .unwrap() + .expect("Failed to get route path") .axum_info .as_ref() .unwrap() @@ -271,8 +336,23 @@ mod tests { #[test] fn should_correctly_parse_routes_with_server_handler() { let mut app = App::new(); - app.base_path = "/home/user/Documents/tuono".into(); + #[cfg(target_os = "windows")] + let base_path = "\\home\\user\\Documents\\tuono"; + + #[cfg(not(target_os = "windows"))] + let base_path = "/home/user/Documents/tuono"; + + app.base_path = base_path.into(); + + #[cfg(target_os = "windows")] + let routes = [ + "\\home\\user\\Documents\\tuono\\src\\routes\\about.rs", + "\\home\\user\\Documents/tuono\\src\\routes\\about.tsx", + "\\home\\user\\Documents\\tuono\\src\\routes\\index.tsx", + ]; + + #[cfg(not(target_os = "windows"))] let routes = [ "/home/user/Documents/tuono/src/routes/about.rs", "/home/user/Documents/tuono/src/routes/about.tsx", @@ -289,9 +369,19 @@ mod tests { .into_iter() .for_each(|(path, expected_has_server_handler)| { if expected_has_server_handler { - assert!(app.route_map.get(path).unwrap().axum_info.is_some()) + assert!(app + .route_map + .get(path) + .expect("Failed to get route path") + .axum_info + .is_some()) } else { - assert!(app.route_map.get(path).unwrap().axum_info.is_none()) + assert!(app + .route_map + .get(path) + .expect("Failed to get route path") + .axum_info + .is_none()) } }) } diff --git a/crates/tuono/src/watch.rs b/crates/tuono/src/watch.rs index 1ab080d4..fc81e834 100644 --- a/crates/tuono/src/watch.rs +++ b/crates/tuono/src/watch.rs @@ -9,10 +9,20 @@ use watchexec_supervisor::job::{start_job, Job}; use crate::mode::Mode; use crate::source_builder::bundle_axum_source; +#[cfg(target_os = "windows")] +const DEV_WATCH_BIN_SRC: &str = "node_modules\\.bin\\tuono-dev-watch.cmd"; +#[cfg(target_os = "windows")] +const DEV_SSR_BIN_SRC: &str = "node_modules\\.bin\\tuono-dev-ssr.cmd"; + +#[cfg(not(target_os = "windows"))] +const DEV_WATCH_BIN_SRC: &str = "node_modules/.bin/tuono-dev-watch"; +#[cfg(not(target_os = "windows"))] +const DEV_SSR_BIN_SRC: &str = "node_modules/.bin/tuono-dev-ssr"; + fn watch_react_src() -> Job { start_job(Arc::new(Command { program: Program::Exec { - prog: "node_modules/.bin/tuono-dev-watch".into(), + prog: DEV_WATCH_BIN_SRC.into(), args: vec![], }, options: Default::default(), @@ -34,7 +44,7 @@ fn build_rust_src() -> Job { fn build_react_ssr_src() -> Job { start_job(Arc::new(Command { program: Program::Exec { - prog: "node_modules/.bin/tuono-dev-ssr".into(), + prog: DEV_SSR_BIN_SRC.into(), args: vec![], }, options: Default::default(), diff --git a/crates/tuono_lib/Cargo.toml b/crates/tuono_lib/Cargo.toml index 85a6575a..6aff63b4 100644 --- a/crates/tuono_lib/Cargo.toml +++ b/crates/tuono_lib/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tuono_lib" -version = "0.14.2" +version = "0.14.3" edition = "2021" authors = ["V. Ageno "] description = "Superfast React fullstack framework" @@ -31,7 +31,7 @@ either = "1.13.0" tower-http = {version = "0.6.0", features = ["fs"]} colored = "2.1.0" -tuono_lib_macros = {path = "../tuono_lib_macros", version = "0.14.2"} +tuono_lib_macros = {path = "../tuono_lib_macros", version = "0.14.3"} # Match the same version used by axum tokio-tungstenite = "0.24.0" futures-util = { version = "0.3", default-features = false, features = ["sink", "std"] } diff --git a/crates/tuono_lib/src/ssr.rs b/crates/tuono_lib/src/ssr.rs index 2c89ff97..a468aaf0 100644 --- a/crates/tuono_lib/src/ssr.rs +++ b/crates/tuono_lib/src/ssr.rs @@ -9,6 +9,16 @@ use std::path::PathBuf; /// update the SSR result without reloading the whole server. pub struct Js; +#[cfg(target_os = "windows")] +const PROD_BUNDLE_PATH: &str = ".\\out\\server\\prod-server.js"; +#[cfg(target_os = "windows")] +const DEV_BUNDLE_PATH: &str = ".\\.tuono\\server\\dev-server.js"; + +#[cfg(not(target_os = "windows"))] +const PROD_BUNDLE_PATH: &str = "./out/server/prod-server.js"; +#[cfg(not(target_os = "windows"))] +const DEV_BUNDLE_PATH: &str = "./.tuono/server/dev-server.js"; + impl Js { pub fn render_to_string(payload: Option<&str>) -> Result { let mode = GLOBAL_MODE.get().expect("Failed to get GLOBAL_MODE"); @@ -27,7 +37,7 @@ impl ProdJs { thread_local! { pub static SSR: RefCell> = RefCell::new( Ssr::from( - read_to_string(PathBuf::from("./out/server/prod-server.js")).expect("Server bundle not found"), "" + read_to_string(PathBuf::from(PROD_BUNDLE_PATH)).expect("Server bundle not found"), "" ).unwrap() ) } @@ -38,8 +48,7 @@ struct DevJs; impl DevJs { pub fn render_to_string(params: Option<&str>) -> Result { Ssr::from( - read_to_string(PathBuf::from("./.tuono/server/dev-server.js")) - .expect("Server bundle not found"), + read_to_string(PathBuf::from(DEV_BUNDLE_PATH)).expect("Server bundle not found"), "", ) .unwrap() diff --git a/crates/tuono_lib_macros/Cargo.toml b/crates/tuono_lib_macros/Cargo.toml index 00060895..82a0a371 100644 --- a/crates/tuono_lib_macros/Cargo.toml +++ b/crates/tuono_lib_macros/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tuono_lib_macros" -version = "0.14.2" +version = "0.14.3" edition = "2021" description = "Superfast React fullstack framework" homepage = "https://tuono.dev" diff --git a/packages/fs-router-vite-plugin/package.json b/packages/fs-router-vite-plugin/package.json index 66c5ea20..6bdf1ce1 100644 --- a/packages/fs-router-vite-plugin/package.json +++ b/packages/fs-router-vite-plugin/package.json @@ -1,6 +1,6 @@ { "name": "tuono-fs-router-vite-plugin", - "version": "0.14.2", + "version": "0.14.3", "description": "Plugin for the tuono's file system router. Tuono is the react/rust fullstack framework", "homepage": "https://tuono.dev", "scripts": { diff --git a/packages/lazy-fn-vite-plugin/package.json b/packages/lazy-fn-vite-plugin/package.json index 2403214d..d51943b5 100644 --- a/packages/lazy-fn-vite-plugin/package.json +++ b/packages/lazy-fn-vite-plugin/package.json @@ -1,6 +1,6 @@ { "name": "tuono-lazy-fn-vite-plugin", - "version": "0.14.2", + "version": "0.14.3", "description": "Plugin for the tuono's lazy fn. Tuono is the react/rust fullstack framework", "homepage": "https://tuono.dev", "scripts": { diff --git a/packages/router/package.json b/packages/router/package.json index 83f68d0d..c57fb674 100644 --- a/packages/router/package.json +++ b/packages/router/package.json @@ -1,6 +1,6 @@ { "name": "tuono-router", - "version": "0.14.2", + "version": "0.14.3", "description": "React routing component for the framework tuono. Tuono is the react/rust fullstack framework", "homepage": "https://tuono.dev", "scripts": { diff --git a/packages/tuono/package.json b/packages/tuono/package.json index 00014316..15fd9919 100644 --- a/packages/tuono/package.json +++ b/packages/tuono/package.json @@ -1,6 +1,6 @@ { "name": "tuono", - "version": "0.14.2", + "version": "0.14.3", "description": "Superfast React fullstack framework", "homepage": "https://tuono.dev", "scripts": {