diff --git a/.editorconfig b/.editorconfig index 3920760a..b543c09f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,3 +5,6 @@ end_of_line = lf indent_style = space indent_size = 2 max_line_length = 80 + +[*.rs] +indent_size = 4 diff --git a/crates/tuono/src/build.rs b/crates/tuono/src/build.rs new file mode 100644 index 00000000..a3202961 --- /dev/null +++ b/crates/tuono/src/build.rs @@ -0,0 +1,84 @@ +use fs_extra::dir::{copy, CopyOptions}; +use spinners::{Spinner, Spinners}; +use std::path::PathBuf; +use std::thread::sleep; +use std::time::Duration; + +use crate::app::App; +use crate::mode::Mode; + +pub fn build(mut app: App, ssg: bool, no_js_emit: bool) { + if no_js_emit { + println!("Rust build successfully finished"); + return; + } + + if ssg && app.has_dynamic_routes() { + // TODO: allow dynamic routes static generation + println!("Cannot statically build dynamic routes"); + return; + } + + app.build_tuono_config() + .expect("Failed to build tuono.config.ts"); + + let mut app_build_spinner = Spinner::new(Spinners::Dots, "Building app...".into()); + + app.check_server_availability(Mode::Prod); + + app.build_react_prod(); + + // Remove the spinner + app_build_spinner.stop_with_message("\u{2705}Build completed".into()); + + if ssg { + let mut app_build_static_spinner = + Spinner::new(Spinners::Dots, "Static site generation".into()); + + let static_dir = PathBuf::from("out/static"); + + if static_dir.is_dir() { + std::fs::remove_dir_all(&static_dir).expect("Failed to clear the out/static folder"); + } + + std::fs::create_dir(&static_dir).expect("Failed to create static output dir"); + + copy( + "./out/client", + static_dir, + &CopyOptions::new().overwrite(true).content_only(true), + ) + .expect("Failed to clone assets into static output folder"); + + // Start the server + #[allow(clippy::zombie_processes)] + let mut rust_server = app.run_rust_server(); + + let reqwest_client = reqwest::blocking::Client::builder() + .user_agent("") + .build() + .expect("Failed to build reqwest client"); + + // Wait for server + let mut is_server_ready = false; + let config = app.config.as_ref().unwrap(); + + while !is_server_ready { + let server_url = format!("http://{}:{}", config.server.host, config.server.port); + if reqwest_client.get(&server_url).send().is_ok() { + is_server_ready = true; + } + sleep(Duration::from_secs(1)); + } + + for (_, route) in app.route_map { + route.save_ssg_file(&reqwest_client); + } + + // Close server + let _ = rust_server.kill(); + + app_build_static_spinner + .stop_with_message("\u{2705}Static site generation completed".into()); + } +} diff --git a/crates/tuono/src/cli.rs b/crates/tuono/src/cli.rs index de05360c..520933cf 100644 --- a/crates/tuono/src/cli.rs +++ b/crates/tuono/src/cli.rs @@ -1,11 +1,9 @@ -use fs_extra::dir::{copy, CopyOptions}; use std::path::PathBuf; -use std::thread::sleep; -use std::time::Duration; use clap::{Parser, Subcommand}; use crate::app::App; +use crate::build; use crate::mode::Mode; use crate::scaffold_project; use crate::source_builder::{bundle_axum_source, check_tuono_folder, create_client_entry_files}; @@ -77,78 +75,9 @@ pub fn app() -> std::io::Result<()> { watch::watch().unwrap(); } Actions::Build { ssg, no_js_emit } => { - let mut app = init_tuono_folder(Mode::Prod)?; + let app = init_tuono_folder(Mode::Prod)?; - if no_js_emit { - println!("Rust build successfully finished"); - return Ok(()); - } - - if ssg && app.has_dynamic_routes() { - // TODO: allow dynamic routes static generation - println!("Cannot statically build dynamic routes"); - return Ok(()); - } - - app.build_tuono_config() - .expect("Failed to build tuono.config.ts"); - - app.check_server_availability(Mode::Prod); - - app.build_react_prod(); - - if ssg { - println!("SSG: generation started"); - - let static_dir = PathBuf::from("out/static"); - - if static_dir.is_dir() { - std::fs::remove_dir_all(&static_dir) - .expect("Failed to clear the out/static folder"); - } - - std::fs::create_dir(&static_dir).expect("Failed to create static output dir"); - - copy( - "./out/client", - static_dir, - &CopyOptions::new().overwrite(true).content_only(true), - ) - .expect("Failed to clone assets into static output folder"); - - // the process is killed below so we don't really need to use wait() function - #[allow(clippy::zombie_processes)] - let mut rust_server = app.run_rust_server(); - - let reqwest = reqwest::blocking::Client::builder() - .user_agent("") - .build() - .expect("Failed to build reqwest client"); - - // Wait for server - let mut is_server_ready = false; - - let config = app.config.as_ref().unwrap(); - - while !is_server_ready { - let server_url = - format!("http://{}:{}", config.server.host, config.server.port); - if reqwest.get(server_url).send().is_ok() { - is_server_ready = true - } - // TODO: add maximum tries - sleep(Duration::from_secs(1)) - } - - for (_, route) in app.route_map { - route.save_ssg_file(&reqwest) - } - - // Close server - let _ = rust_server.kill(); - }; - - println!("Build successfully finished"); + build::build(app, ssg, no_js_emit); } Actions::New { folder_name, diff --git a/crates/tuono/src/lib.rs b/crates/tuono/src/lib.rs index 3d56a996..5ed9c123 100644 --- a/crates/tuono/src/lib.rs +++ b/crates/tuono/src/lib.rs @@ -4,6 +4,7 @@ //! You can find the full documentation at [tuono.dev](https://tuono.dev/) mod app; +mod build; pub mod cli; mod mode; mod route;