diff --git a/.vscode/settings.json b/.vscode/settings.json index 1ebfd79ef..8c3e1f1a2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,8 +3,8 @@ "[toml]": { "editor.formatOnSave": false }, - "rust-analyzer.check.workspace": false, // "rust-analyzer.check.workspace": true, + "rust-analyzer.check.workspace": false, "rust-analyzer.check.features": "all", "rust-analyzer.cargo.features": "all", "rust-analyzer.check.allTargets": true diff --git a/Cargo.toml b/Cargo.toml index e603b3aff..fc806e989 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ members = [ "packages/playwright-tests/web", "packages/playwright-tests/fullstack", ] -exclude = ["examples/mobile_demo", "examples/openid_connect_demo",] +exclude = ["examples/mobile_demo", "examples/openid_connect_demo"] [workspace.package] version = "0.5.0-alpha.0" @@ -60,21 +60,21 @@ dioxus-lib = { path = "packages/dioxus-lib", version = "0.5.0-alpha.0" } dioxus-core = { path = "packages/core", version = "0.5.0-alpha.0" } dioxus-core-macro = { path = "packages/core-macro", version = "0.5.0-alpha.0" } dioxus-config-macro = { path = "packages/config-macro", version = "0.5.0-alpha.0" } -dioxus-router = { path = "packages/router", version = "0.5.0-alpha.0" } +dioxus-router = { path = "packages/router", version = "0.5.0-alpha.0" } dioxus-router-macro = { path = "packages/router-macro", version = "0.5.0-alpha.0" } -dioxus-html = { path = "packages/html", version = "0.5.0-alpha.0" } -dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.5.0-alpha.0" } +dioxus-html = { path = "packages/html", version = "0.5.0-alpha.0" } +dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.5.0-alpha.0" } dioxus-hooks = { path = "packages/hooks", version = "0.5.0-alpha.0" } dioxus-web = { path = "packages/web", version = "0.5.0-alpha.0" } dioxus-ssr = { path = "packages/ssr", version = "0.5.0-alpha.0", default-features = false } dioxus-desktop = { path = "packages/desktop", version = "0.5.0-alpha.0" } -dioxus-mobile = { path = "packages/mobile", version = "0.5.0-alpha.0" } +dioxus-mobile = { path = "packages/mobile", version = "0.5.0-alpha.0" } dioxus-interpreter-js = { path = "packages/interpreter", version = "0.5.0-alpha.0" } -dioxus-liveview = { path = "packages/liveview", version = "0.5.0-alpha.0" } -dioxus-autofmt = { path = "packages/autofmt", version = "0.5.0-alpha.0" } -dioxus-check = { path = "packages/check", version = "0.5.0-alpha.0" } -dioxus-rsx = { path = "packages/rsx", version = "0.5.0-alpha.0" } -dioxus-tui = { path = "packages/dioxus-tui", version = "0.5.0-alpha.0" } +dioxus-liveview = { path = "packages/liveview", version = "0.5.0-alpha.0" } +dioxus-autofmt = { path = "packages/autofmt", version = "0.5.0-alpha.0" } +dioxus-check = { path = "packages/check", version = "0.5.0-alpha.0" } +dioxus-rsx = { path = "packages/rsx", version = "0.5.0-alpha.0" } +dioxus-tui = { path = "packages/dioxus-tui", version = "0.5.0-alpha.0" } plasmo = { path = "packages/plasmo", version = "0.5.0-alpha.0" } dioxus-native-core = { path = "packages/native-core", version = "0.5.0-alpha.0" } dioxus-native-core-macro = { path = "packages/native-core-macro", version = "0.5.0-alpha.0" } @@ -84,7 +84,7 @@ dioxus-cli-config = { path = "packages/cli-config", version = "0.5.0-alpha.0" } generational-box = { path = "packages/generational-box", version = "0.5.0-alpha.0" } dioxus-hot-reload = { path = "packages/hot-reload", version = "0.5.0-alpha.0" } dioxus-fullstack = { path = "packages/fullstack", version = "0.5.0-alpha.0" } -dioxus_server_macro = { path = "packages/server-macro", version = "0.5.0-alpha.0", default-features = false} +dioxus_server_macro = { path = "packages/server-macro", version = "0.5.0-alpha.0", default-features = false } dioxus-ext = { path = "packages/extension", version = "0.4.0" } tracing = "0.1.37" tracing-futures = "0.2.5" @@ -100,16 +100,16 @@ thiserror = "1.0.40" prettyplease = { package = "prettier-please", version = "0.2", features = [ "verbatim", ] } -manganis-cli-support = { version = "0.2.0", features = [ - "webp", - "html", -] } +manganis-cli-support = { version = "0.2.0", features = ["webp", "html"] } manganis = { version = "0.2.0" } +interprocess = { version = "1.2.1" } +# interprocess = { git = "https://github.com/kotauskas/interprocess" } + lru = "0.12.2" async-trait = "0.1.77" axum = "0.7.0" -axum-server = {version = "0.6.0", default-features = false} +axum-server = { version = "0.6.0", default-features = false } tower = "0.4.13" http = "1.0.0" tower-http = "0.5.1" @@ -117,10 +117,24 @@ hyper = "1.0.0" hyper-rustls = "0.26.0" serde_json = "1.0.61" serde = "1.0.61" +syn = "2.0" +quote = "1.0" +proc-macro2 = "1.0" axum_session = "0.12.1" axum_session_auth = "0.12.1" axum-extra = "0.9.2" reqwest = "0.11.24" +owo-colors = "4.0.0" + +# Enable a small amount of optimization in debug mode +[profile.cli-dev] +inherits = "dev" +opt-level = 1 + +# Enable high optimizations for dependencies (incl. Bevy), but not for our code: +[profile.cli-dev.package."*"] +opt-level = 3 + # This is a "virtual package" # It is not meant to be published, but is used so "cargo run --example XYZ" works properly @@ -139,9 +153,9 @@ rust-version = "1.60.0" publish = false [dependencies] -manganis = { workspace = true, optional = true} -reqwest = { version = "0.11.9", features = ["json"], optional = true} -http-range = {version = "0.1.5", optional = true } +manganis = { workspace = true, optional = true } +reqwest = { version = "0.11.9", features = ["json"], optional = true } +http-range = { version = "0.1.5", optional = true } [dev-dependencies] dioxus = { workspace = true, features = ["router"] } @@ -155,7 +169,13 @@ form_urlencoded = "1.2.0" [target.'cfg(target_arch = "wasm32")'.dev-dependencies] getrandom = { version = "0.2.12", features = ["js"] } -tokio = { version = "1.16.1", default-features = false, features = ["sync", "macros", "io-util", "rt", "time"] } +tokio = { version = "1.16.1", default-features = false, features = [ + "sync", + "macros", + "io-util", + "rt", + "time", +] } [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] tokio = { version = "1.16.1", features = ["full"] } diff --git a/packages/autofmt/Cargo.toml b/packages/autofmt/Cargo.toml index 5815b8298..5765c0bbe 100644 --- a/packages/autofmt/Cargo.toml +++ b/packages/autofmt/Cargo.toml @@ -13,8 +13,8 @@ keywords = ["dom", "ui", "gui", "react"] [dependencies] dioxus-rsx = { workspace = true } proc-macro2 = { version = "1.0.6", features = ["span-locations"] } -quote = "1.0" -syn = { version = "2.0", features = ["full", "extra-traits", "visit"] } +quote = { workspace = true } +syn = { workspace = true, features = ["full", "extra-traits", "visit"] } serde = { version = "1.0.136", features = ["derive"] } prettyplease = { workspace = true } diff --git a/packages/check/Cargo.toml b/packages/check/Cargo.toml index 52b98cc44..9877ed27c 100644 --- a/packages/check/Cargo.toml +++ b/packages/check/Cargo.toml @@ -11,10 +11,10 @@ keywords = ["dom", "ui", "gui", "react"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -proc-macro2 = { version = "1.0.6", features = ["span-locations"] } -quote = "1.0" -syn = { version = "1.0.11", features = ["full", "extra-traits", "visit"] } -owo-colors = { version = "3.5.0", features = ["supports-colors"] } +proc-macro2 = { workspace = true, features = ["span-locations"] } +quote = {workspace = true } +syn = { workspace = true, features = ["full", "extra-traits", "visit"] } +owo-colors = { workspace = true, features = ["supports-colors"] } [dev-dependencies] indoc = "2.0.3" diff --git a/packages/check/src/check.rs b/packages/check/src/check.rs index d5fdd5f33..5022fea77 100644 --- a/packages/check/src/check.rs +++ b/packages/check/src/check.rs @@ -77,8 +77,8 @@ fn is_component_fn(item_fn: &syn::ItemFn) -> bool { fn get_closure_hook_body(local: &syn::Local) -> Option<&syn::Expr> { if let Pat::Ident(ident) = &local.pat { if is_hook_ident(&ident.ident) { - if let Some((_, expr)) = &local.init { - if let syn::Expr::Closure(closure) = &**expr { + if let Some(init) = &local.init { + if let syn::Expr::Closure(closure) = init.expr.as_ref() { return Some(&closure.body); } } diff --git a/packages/cli-config/src/config.rs b/packages/cli-config/src/config.rs index f84965a0f..1478d6ed3 100644 --- a/packages/cli-config/src/config.rs +++ b/packages/cli-config/src/config.rs @@ -301,8 +301,10 @@ pub struct WebProxyConfig { pub struct WebWatcherConfig { #[serde(default = "watch_path_default")] pub watch_path: Vec, + #[serde(default)] pub reload_html: bool, + #[serde(default = "true_bool")] pub index_on_404: bool, } diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index ba4c1f8cf..fc1668e50 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -21,7 +21,7 @@ log = "0.4.14" fern = { version = "0.6.0", features = ["colored"] } serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0.79" -toml = {workspace = true} +toml = { workspace = true } fs_extra = "1.2.0" cargo_toml = "0.18.0" futures-util = { workspace = true } @@ -78,7 +78,7 @@ toml_edit = "0.21.0" tauri-bundler = { version = "=1.4.*", features = ["native-tls-vendored"] } # formatting -syn = { version = "2.0" } +syn = { workspace = true } prettyplease = { workspace = true } manganis-cli-support = { workspace = true, features = ["webp", "html"] } @@ -90,7 +90,8 @@ dioxus-rsx = { workspace = true } dioxus-html = { workspace = true, features = ["hot-reload-context"] } dioxus-core = { workspace = true, features = ["serialize"] } dioxus-hot-reload = { workspace = true } -interprocess-docfix = { version = "1.2.2" } +interprocess = { workspace = true } +# interprocess-docfix = { version = "1.2.2" } ignore = "0.4.22" [features] diff --git a/packages/cli/build.rs b/packages/cli/build.rs deleted file mode 100644 index 050f38761..000000000 --- a/packages/cli/build.rs +++ /dev/null @@ -1,45 +0,0 @@ -//! Construct version in the `commit-hash date channel` format - -use std::{env, path::PathBuf, process::Command}; - -fn main() { - set_rerun(); - set_commit_info(); -} - -fn set_rerun() { - let mut manifest_dir = PathBuf::from( - env::var("CARGO_MANIFEST_DIR").expect("`CARGO_MANIFEST_DIR` is always set by cargo."), - ); - - while manifest_dir.parent().is_some() { - let head_ref = manifest_dir.join(".git/HEAD"); - if head_ref.exists() { - println!("cargo:rerun-if-changed={}", head_ref.display()); - return; - } - - manifest_dir.pop(); - } - - println!("cargo:warning=Could not find `.git/HEAD` from manifest dir!"); -} - -fn set_commit_info() { - let output = match Command::new("git") - .arg("log") - .arg("-1") - .arg("--date=short") - .arg("--format=%H %h %cd") - .output() - { - Ok(output) if output.status.success() => output, - _ => return, - }; - let stdout = String::from_utf8(output.stdout).unwrap(); - let mut parts = stdout.split_whitespace(); - let mut next = || parts.next().unwrap(); - println!("cargo:rustc-env=RA_COMMIT_HASH={}", next()); - println!("cargo:rustc-env=RA_COMMIT_SHORT_HASH={}", next()); - println!("cargo:rustc-env=RA_COMMIT_DATE={}", next()) -} diff --git a/packages/cli/rustfmt.toml b/packages/cli/rustfmt.toml new file mode 100644 index 000000000..c3c8c3753 --- /dev/null +++ b/packages/cli/rustfmt.toml @@ -0,0 +1 @@ +imports_granularity = "Crate" diff --git a/packages/cli/src/builder.rs b/packages/cli/src/builder.rs index 68e017dc0..6eb53bfa2 100644 --- a/packages/cli/src/builder.rs +++ b/packages/cli/src/builder.rs @@ -3,10 +3,9 @@ use crate::{ error::{Error, Result}, tools::Tool, }; +use anyhow::Context; use cargo_metadata::{diagnostic::Diagnostic, Message}; -use dioxus_cli_config::crate_root; -use dioxus_cli_config::CrateConfig; -use dioxus_cli_config::ExecutableType; +use dioxus_cli_config::{crate_root, CrateConfig, ExecutableType}; use indicatif::{ProgressBar, ProgressStyle}; use lazy_static::lazy_static; use manganis_cli_support::{AssetManifest, ManganisSupportGuard}; @@ -67,7 +66,6 @@ impl ExecWithRustFlagsSetter for subprocess::Exec { /// Note: `rust_flags` argument is only used for the fullstack platform. pub fn build( config: &CrateConfig, - _: bool, skip_assets: bool, rust_flags: Option, ) -> Result { @@ -103,6 +101,7 @@ pub fn build( let wasm_check_command = std::process::Command::new("rustup") .args(["show"]) .output()?; + let wasm_check_output = String::from_utf8(wasm_check_command.stdout).unwrap(); if !wasm_check_output.contains("wasm32-unknown-unknown") { log::info!("wasm32-unknown-unknown target not detected, installing.."); @@ -163,9 +162,10 @@ pub fn build( let input_path = warning_messages .output_location .as_ref() - .unwrap() + .context("No output location found")? .with_extension("wasm"); + log::info!("Running wasm-bindgen"); let bindgen_result = panic::catch_unwind(move || { // [3] Bindgen the final binary for use easy linking let mut bindgen_builder = Bindgen::new(); @@ -183,11 +183,13 @@ pub fn build( .generate(&bindgen_outdir) .unwrap(); }); + if bindgen_result.is_err() { return Err(Error::BuildFailed("Bindgen build failed! \nThis is probably due to the Bindgen version, dioxus-cli using `0.2.81` Bindgen crate.".to_string())); } // check binaryen:wasm-opt tool + log::info!("Running optimization with wasm-opt..."); let dioxus_tools = dioxus_config.application.tools.clone(); if dioxus_tools.contains_key("binaryen") { let info = dioxus_tools.get("binaryen").unwrap(); @@ -221,6 +223,8 @@ pub fn build( "Binaryen tool not found, you can use `dx tool add binaryen` to install it." ); } + } else { + log::info!("Skipping optimization with wasm-opt, binaryen tool not found."); } // [5][OPTIONAL] If tailwind is enabled and installed we run it to generate the CSS @@ -271,6 +275,8 @@ pub fn build( content_only: false, depth: 0, }; + + log::info!("Copying public assets to the output directory..."); if asset_dir.is_dir() { for entry in std::fs::read_dir(config.asset_dir())?.flatten() { let path = entry.path(); @@ -294,6 +300,7 @@ pub fn build( } } + log::info!("Processing assets"); let assets = if !skip_assets { let assets = asset_manifest(executable.executable(), config); process_assets(config, &assets)?; diff --git a/packages/cli/src/cli/build.rs b/packages/cli/src/cli/build.rs index 80962f005..83149d8cf 100644 --- a/packages/cli/src/cli/build.rs +++ b/packages/cli/src/cli/build.rs @@ -1,5 +1,4 @@ -use crate::assets::AssetConfigDropGuard; -use crate::server::fullstack; +use crate::{assets::AssetConfigDropGuard, server::fullstack}; use dioxus_cli_config::Platform; use super::*; @@ -58,7 +57,7 @@ impl Build { let build_result = match platform { Platform::Web => { // `rust_flags` are used by fullstack's client build. - crate::builder::build(&crate_config, false, self.build.skip_assets, rust_flags)? + crate::builder::build(&crate_config, self.build.skip_assets, rust_flags)? } Platform::Desktop => { // Since desktop platform doesn't use `rust_flags`, this @@ -83,7 +82,6 @@ impl Build { }; crate::builder::build( &web_config, - false, self.build.skip_assets, Some(client_rust_flags), )?; diff --git a/packages/cli/src/cli/cfg.rs b/packages/cli/src/cli/cfg.rs index c764d77d6..ec352d55e 100644 --- a/packages/cli/src/cli/cfg.rs +++ b/packages/cli/src/cli/cfg.rs @@ -85,8 +85,8 @@ pub struct ConfigOptsServe { #[clap(default_value_t = 8080)] pub port: u16, - /// Open the app in the default browser [default: false] - #[clap(long)] + /// Open the app in the default browser [default: true] + #[clap(long, default_value_t = true)] #[serde(default)] pub open: bool, diff --git a/packages/cli/src/cli/create.rs b/packages/cli/src/cli/create.rs index 73eda7d0b..dd4ae2802 100644 --- a/packages/cli/src/cli/create.rs +++ b/packages/cli/src/cli/create.rs @@ -2,7 +2,7 @@ use super::*; use cargo_generate::{GenerateArgs, TemplatePath}; #[derive(Clone, Debug, Default, Deserialize, Parser)] -#[clap(name = "create")] +#[clap(name = "new")] pub struct Create { /// Template path #[clap(default_value = "gh:dioxuslabs/dioxus-template", long)] diff --git a/packages/cli/src/cli/mod.rs b/packages/cli/src/cli/mod.rs index 21d1b63c6..5f1c07102 100644 --- a/packages/cli/src/cli/mod.rs +++ b/packages/cli/src/cli/mod.rs @@ -10,7 +10,6 @@ pub mod init; pub mod plugin; pub mod serve; pub mod translate; -pub mod version; use crate::{ cfg::{ConfigOptsBuild, ConfigOptsServe}, @@ -57,10 +56,11 @@ pub enum Commands { /// Build, watch & serve the Rust WASM app and all of its assets. Serve(serve::Serve), - /// Create a new project for Dioxus. - Create(create::Create), + /// Create a new project for Dioxus.a + New(create::Create), - /// Init a new project for Dioxus + /// Init a new project for Dioxus in an existing directory. + /// Will attempt to keep your project in a good state Init(init::Init), /// Clean output artifacts. @@ -69,10 +69,6 @@ pub enum Commands { /// Bundle the Rust desktop app and all of its assets. Bundle(bundle::Bundle), - /// Print the version of this extension - #[clap(name = "version")] - Version(version::Version), - /// Format some rsx #[clap(name = "fmt")] Autoformat(autoformat::Autoformat), @@ -97,11 +93,10 @@ impl Display for Commands { Commands::Build(_) => write!(f, "build"), Commands::Translate(_) => write!(f, "translate"), Commands::Serve(_) => write!(f, "serve"), - Commands::Create(_) => write!(f, "create"), + Commands::New(_) => write!(f, "create"), Commands::Init(_) => write!(f, "init"), Commands::Clean(_) => write!(f, "clean"), Commands::Config(_) => write!(f, "config"), - Commands::Version(_) => write!(f, "version"), Commands::Autoformat(_) => write!(f, "fmt"), Commands::Check(_) => write!(f, "check"), Commands::Bundle(_) => write!(f, "bundle"), diff --git a/packages/cli/src/cli/serve.rs b/packages/cli/src/cli/serve.rs index 4448e9b0b..a72fc19e6 100644 --- a/packages/cli/src/cli/serve.rs +++ b/packages/cli/src/cli/serve.rs @@ -61,24 +61,14 @@ impl Serve { let platform = platform.unwrap_or(crate_config.dioxus_config.application.default_platform); + // start the develop server + use server::{desktop, fullstack, web}; match platform { - Platform::Web => { - // start the develop server - server::web::startup( - self.serve.port, - crate_config.clone(), - self.serve.open, - self.serve.skip_assets, - ) - .await?; - } - Platform::Desktop => { - server::desktop::startup(crate_config.clone(), &serve_cfg).await?; - } - Platform::Fullstack => { - server::fullstack::startup(crate_config.clone(), &serve_cfg).await?; - } + Platform::Web => web::startup(crate_config.clone(), &serve_cfg).await?, + Platform::Desktop => desktop::startup(crate_config.clone(), &serve_cfg).await?, + Platform::Fullstack => fullstack::startup(crate_config.clone(), &serve_cfg).await?, } + Ok(()) } diff --git a/packages/cli/src/cli/version.rs b/packages/cli/src/cli/version.rs deleted file mode 100644 index 47ace1be3..000000000 --- a/packages/cli/src/cli/version.rs +++ /dev/null @@ -1,76 +0,0 @@ -use super::*; - -/// Print the version of this extension -#[derive(Clone, Debug, Parser)] -#[clap(name = "version")] -pub struct Version {} - -impl Version { - pub fn version(self) -> VersionInfo { - version() - } -} - -use std::fmt; - -/// Information about the git repository where rust-analyzer was built from. -pub struct CommitInfo { - pub short_commit_hash: &'static str, - pub commit_hash: &'static str, - pub commit_date: &'static str, -} - -/// Cargo's version. -pub struct VersionInfo { - /// rust-analyzer's version, such as "1.57.0", "1.58.0-beta.1", "1.59.0-nightly", etc. - pub version: &'static str, - - /// The release channel we were built for (stable/beta/nightly/dev). - /// - /// `None` if not built via rustbuild. - pub release_channel: Option<&'static str>, - - /// Information about the Git repository we may have been built from. - /// - /// `None` if not built from a git repo. - pub commit_info: Option, -} - -impl fmt::Display for VersionInfo { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.version)?; - - if let Some(ci) = &self.commit_info { - write!(f, " ({} {})", ci.short_commit_hash, ci.commit_date)?; - }; - Ok(()) - } -} - -/// Returns information about cargo's version. -pub const fn version() -> VersionInfo { - let version = match option_env!("CARGO_PKG_VERSION") { - Some(x) => x, - None => "0.0.0", - }; - - let release_channel = option_env!("CFG_RELEASE_CHANNEL"); - let commit_info = match ( - option_env!("RA_COMMIT_SHORT_HASH"), - option_env!("RA_COMMIT_HASH"), - option_env!("RA_COMMIT_DATE"), - ) { - (Some(short_commit_hash), Some(commit_hash), Some(commit_date)) => Some(CommitInfo { - short_commit_hash, - commit_hash, - commit_date, - }), - _ => None, - }; - - VersionInfo { - version, - release_channel, - commit_info, - } -} diff --git a/packages/cli/src/main.rs b/packages/cli/src/main.rs index d4326a696..87f9e32e7 100644 --- a/packages/cli/src/main.rs +++ b/packages/cli/src/main.rs @@ -7,35 +7,6 @@ use dioxus_cli::*; use Commands::*; -fn get_bin(bin: Option) -> Result { - let metadata = cargo_metadata::MetadataCommand::new() - .exec() - .map_err(Error::CargoMetadata)?; - let package = if let Some(bin) = bin { - metadata - .workspace_packages() - .into_iter() - .find(|p| p.name == bin) - .ok_or(Error::CargoError(format!("no such package: {}", bin)))? - } else { - metadata - .root_package() - .ok_or(Error::CargoError("no root package?".to_string()))? - }; - - let crate_dir = package - .manifest_path - .parent() - .ok_or(Error::CargoError("couldn't take parent dir".to_string()))?; - - Ok(crate_dir.into()) -} - -/// Simplifies error messages that use the same pattern. -fn error_wrapper(message: &str) -> String { - format!("🚫 {message}:") -} - #[tokio::main] async fn main() -> anyhow::Result<()> { let args = Cli::parse(); @@ -47,7 +18,7 @@ async fn main() -> anyhow::Result<()> { .translate() .context(error_wrapper("Translation of HTML into RSX failed")), - Create(opts) => opts + New(opts) => opts .create() .context(error_wrapper("Creating new project failed")), @@ -74,12 +45,6 @@ async fn main() -> anyhow::Result<()> { .await .context(error_wrapper("Error checking RSX")), - Version(opt) => { - let version = opt.version(); - println!("{}", version); - - Ok(()) - } action => { let bin = get_bin(args.bin)?; let _dioxus_config = DioxusConfig::load(Some(bin.clone())) @@ -119,3 +84,32 @@ async fn main() -> anyhow::Result<()> { } } } + +fn get_bin(bin: Option) -> Result { + let metadata = cargo_metadata::MetadataCommand::new() + .exec() + .map_err(Error::CargoMetadata)?; + let package = if let Some(bin) = bin { + metadata + .workspace_packages() + .into_iter() + .find(|p| p.name == bin) + .ok_or(Error::CargoError(format!("no such package: {}", bin)))? + } else { + metadata + .root_package() + .ok_or(Error::CargoError("no root package?".to_string()))? + }; + + let crate_dir = package + .manifest_path + .parent() + .ok_or(Error::CargoError("couldn't take parent dir".to_string()))?; + + Ok(crate_dir.into()) +} + +/// Simplifies error messages that use the same pattern. +fn error_wrapper(message: &str) -> String { + format!("🚫 {message}:") +} diff --git a/packages/cli/src/server/desktop/mod.rs b/packages/cli/src/server/desktop/mod.rs index 919f91999..10997582a 100644 --- a/packages/cli/src/server/desktop/mod.rs +++ b/packages/cli/src/server/desktop/mod.rs @@ -1,20 +1,18 @@ -use crate::server::Platform; use crate::{ cfg::ConfigOptsServe, server::{ output::{print_console_info, PrettierOptions}, - setup_file_watcher, + setup_file_watcher, Platform, }, BuildResult, Result, }; -use dioxus_cli_config::CrateConfig; - +use dioxus_cli_config::{CrateConfig, ExecutableType}; use dioxus_hot_reload::HotReloadMsg; use dioxus_html::HtmlCtx; use dioxus_rsx::hot_reload::*; -use interprocess_docfix::local_socket::LocalSocketListener; -use std::fs::create_dir_all; +use interprocess::local_socket::LocalSocketListener; use std::{ + fs::create_dir_all, process::{Child, Command}, sync::{Arc, Mutex, RwLock}, }; @@ -33,13 +31,7 @@ pub(crate) async fn startup_with_platform( config: CrateConfig, serve_cfg: &ConfigOptsServe, ) -> Result<()> { - // ctrl-c shutdown checker - let _crate_config = config.clone(); - let _ = ctrlc::set_handler(move || { - #[cfg(feature = "plugin")] - let _ = PluginManager::on_serve_shutdown(&_crate_config); - std::process::exit(0); - }); + set_ctrl_c(&config); let hot_reload_state = match config.hot_reload { true => { @@ -67,6 +59,16 @@ pub(crate) async fn startup_with_platform( Ok(()) } +fn set_ctrl_c(config: &CrateConfig) { + // ctrl-c shutdown checker + let _crate_config = config.clone(); + let _ = ctrlc::set_handler(move || { + #[cfg(feature = "plugin")] + let _ = PluginManager::on_serve_shutdown(&_crate_config); + std::process::exit(0); + }); +} + /// Start the server without hot reload async fn serve( config: CrateConfig, @@ -169,12 +171,13 @@ async fn start_desktop_hot_reload(hot_reload_state: HotReloadState) -> Result<() let mut hot_reload_rx = hot_reload_state.messages.subscribe(); - while let Ok(template) = hot_reload_rx.recv().await { + while let Ok(msg) = hot_reload_rx.recv().await { let channels = &mut *channels.lock().unwrap(); let mut i = 0; + while i < channels.len() { let channel = &mut channels[i]; - if send_msg(HotReloadMsg::UpdateTemplate(template), channel) { + if send_msg(msg.clone(), channel) { i += 1; } else { channels.remove(i); diff --git a/packages/cli/src/server/mod.rs b/packages/cli/src/server/mod.rs index caca56e1a..f1d948478 100644 --- a/packages/cli/src/server/mod.rs +++ b/packages/cli/src/server/mod.rs @@ -3,10 +3,14 @@ use dioxus_cli_config::CrateConfig; use cargo_metadata::diagnostic::Diagnostic; use dioxus_core::Template; +use dioxus_hot_reload::HotReloadMsg; use dioxus_html::HtmlCtx; use dioxus_rsx::hot_reload::*; use notify::{RecommendedWatcher, Watcher}; -use std::sync::{Arc, Mutex}; +use std::{ + path::PathBuf, + sync::{Arc, Mutex}, +}; use tokio::sync::broadcast::{self}; mod output; @@ -15,7 +19,15 @@ pub mod desktop; pub mod fullstack; pub mod web; -/// Sets up a file watcher +#[derive(Clone)] +pub struct HotReloadState { + pub messages: broadcast::Sender, + pub file_map: Arc>>, +} + +/// Sets up a file watcher. +/// +/// Will attempt to hotreload HTML, RSX (.rs), and CSS async fn setup_file_watcher Result + Send + 'static>( build_with: F, config: &CrateConfig, @@ -25,124 +37,184 @@ async fn setup_file_watcher Result + Send + 'static>( let mut last_update_time = chrono::Local::now().timestamp(); // file watcher: check file change - let allow_watch_path = config.dioxus_config.web.watcher.watch_path.clone(); + let mut allow_watch_path = config.dioxus_config.web.watcher.watch_path.clone(); - let watcher_config = config.clone(); - let mut watcher = notify::recommended_watcher(move |info: notify::Result| { - let config = watcher_config.clone(); - if let Ok(e) = info { - match e.kind { - notify::EventKind::Create(_) - | notify::EventKind::Remove(_) - | notify::EventKind::Modify(_) => { - if chrono::Local::now().timestamp() > last_update_time { - let mut needs_full_rebuild; - if let Some(hot_reload) = &hot_reload { - // find changes to the rsx in the file - let mut rsx_file_map = hot_reload.file_map.lock().unwrap(); - let mut messages: Vec