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.lock b/Cargo.lock index d305e8632..c3b8e9ec3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1149,7 +1149,7 @@ dependencies = [ "clap 4.4.18", "console", "dialoguer", - "env_logger", + "env_logger 0.10.2", "fs-err", "git2", "gix-config", @@ -1200,20 +1200,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cargo_metadata" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "cargo_metadata" version = "0.17.0" @@ -1295,15 +1281,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "cfg-expr" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bbc13bf6290a6b202cc3efb36f7ec2b739a80634215630c8053a313edf6abef" -dependencies = [ - "smallvec", -] - [[package]] name = "cfg-expr" version = "0.15.7" @@ -2121,7 +2098,7 @@ dependencies = [ "dioxus-signals", "dioxus-ssr", "dioxus-web", - "env_logger", + "env_logger 0.10.2", "futures-util", "rand 0.8.5", "serde", @@ -2152,7 +2129,7 @@ dependencies = [ "pretty_assertions", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.52", ] [[package]] @@ -2179,6 +2156,7 @@ dependencies = [ "dioxus-html", "dioxus-rsx", "dirs", + "env_logger 0.11.3", "fern", "flate2", "fs_extra", @@ -2190,7 +2168,7 @@ dependencies = [ "hyper-util", "ignore", "indicatif", - "interprocess-docfix", + "interprocess", "lazy_static", "log", "manganis-cli-support", @@ -2431,7 +2409,7 @@ dependencies = [ "dioxus-rsx", "execute", "ignore", - "interprocess-docfix", + "interprocess", "notify", "once_cell", "serde", @@ -2885,6 +2863,16 @@ dependencies = [ "syn 2.0.52", ] +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", +] + [[package]] name = "env_logger" version = "0.10.2" @@ -2898,6 +2886,19 @@ dependencies = [ "termcolor", ] +[[package]] +name = "env_logger" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -4920,10 +4921,10 @@ dependencies = [ ] [[package]] -name = "interprocess-docfix" -version = "1.2.2" +name = "interprocess" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b84ee245c606aeb0841649a9288e3eae8c61b853a8cd5c0e14450e96d53d28f" +checksum = "81f2533f3be42fffe3b5e63b71aeca416c1c3bc33e4e27be018521e76b1f38fb" dependencies = [ "blocking", "cfg-if", @@ -5182,12 +5183,12 @@ dependencies = [ [[package]] name = "krates" -version = "0.12.6" +version = "0.16.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942c43a6cba1c201dfe81a943c89fa5c9140b34993e0c027f542c80b92e319a7" +checksum = "320d34cfe880f2c6243b4cfff8aab3e34eab6325d0a26729f23356418fbdc809" dependencies = [ - "cargo_metadata 0.15.4", - "cfg-expr 0.12.0", + "cargo_metadata 0.18.1", + "cfg-expr", "petgraph", "semver", ] @@ -5362,9 +5363,9 @@ dependencies = [ [[package]] name = "lightningcss" -version = "1.0.0-alpha.54" +version = "1.0.0-alpha.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07d306844e5af1753490c420c0d6ae3d814b00725092d106332762827ca8f0fe" +checksum = "3bd5bed3814fb631bfc1e24c2be6f7e86a9837c660909acab79a38374dcb8798" dependencies = [ "ahash 0.8.11", "bitflags 2.4.2", @@ -6363,9 +6364,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "owo-colors" -version = "3.5.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f" dependencies = [ "supports-color", ] @@ -6928,7 +6929,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" dependencies = [ - "env_logger", + "env_logger 0.10.2", "log", ] @@ -8646,11 +8647,11 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "supports-color" -version = "1.3.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ba6faf2ca7ee42fdd458f4347ae0a9bd6bcc445ad7cb57ad82b383f18870d6f" +checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" dependencies = [ - "atty", + "is-terminal", "is_ci", ] @@ -8721,7 +8722,7 @@ version = "6.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8e9199467bcbc77c6a13cc6e32a6af21721ab8c96aa0261856c4fda5a4433f0" dependencies = [ - "cfg-expr 0.15.7", + "cfg-expr", "heck 0.4.1", "pkg-config", "toml 0.8.11", diff --git a/Cargo.toml b/Cargo.toml index 9df562b8e..fe2e7bfd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,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" @@ -56,27 +56,27 @@ 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-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" } rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.5.0-alpha.0" } dioxus-signals = { path = "packages/signals", version = "0.5.0-alpha.0" } 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" @@ -97,10 +97,13 @@ manganis-cli-support = { version = "0.2.1", features = [ ] } manganis = { version = "0.2.1" } +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" @@ -108,10 +111,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 @@ -130,9 +147,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"] } @@ -146,7 +163,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..f6dba4767 100644 --- a/packages/cli-config/src/config.rs +++ b/packages/cli-config/src/config.rs @@ -7,12 +7,17 @@ use std::path::PathBuf; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug)] #[cfg_attr(feature = "cli", derive(clap::ValueEnum))] pub enum Platform { + /// Targeting the web platform using WASM #[cfg_attr(feature = "cli", clap(name = "web"))] #[serde(rename = "web")] Web, + + /// Targeting the desktop platform using Tao/Wry-based webview #[cfg_attr(feature = "cli", clap(name = "desktop"))] #[serde(rename = "desktop")] Desktop, + + /// Targeting the server platform using Axum and Dioxus-Fullstack #[cfg_attr(feature = "cli", clap(name = "fullstack"))] #[serde(rename = "fullstack")] Fullstack, @@ -220,10 +225,13 @@ impl Default for DioxusConfig { pub struct ApplicationConfig { #[serde(default = "default_name")] pub name: String, + #[serde(default = "default_platform")] pub default_platform: Platform, + #[serde(default = "out_dir_default")] pub out_dir: PathBuf, + #[serde(default = "asset_dir_default")] pub asset_dir: PathBuf, @@ -301,8 +309,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, } @@ -531,6 +541,34 @@ impl CrateConfig { self.cargo_args = cargo_args; self } + + pub fn add_features(&mut self, feature: Vec) -> &mut Self { + if let Some(features) = &mut self.features { + features.extend(feature); + } else { + self.features = Some(feature); + } + self + } + + #[cfg(feature = "cli")] + pub fn extend_with_platform(&mut self, platform: Platform) -> &mut Self { + let manifest = &self.manifest; + let features = match platform { + Platform::Web if manifest.features.contains_key("web") => { + vec!["web".to_string()] + } + Platform::Desktop if manifest.features.contains_key("desktop") => { + vec!["desktop".to_string()] + } + _ => { + // fullstack has its own feature insertion - we use a different featureset for the client and server + vec![] + } + }; + self.add_features(features); + self + } } fn true_bool() -> bool { diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index ba4c1f8cf..e10d2c270 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -10,7 +10,7 @@ keywords = ["react", "gui", "cli", "dioxus", "wasm"] [dependencies] # cli core -clap = { version = "4.2", features = ["derive"] } +clap = { version = "4.2", features = ["derive", "cargo"] } thiserror = { workspace = true } wasm-bindgen-cli-support = "0.2" colored = "2.0.0" @@ -21,10 +21,10 @@ 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 } +futures-util = { workspace = true, features = ["async-await-macro"] } notify = { version = "5.0.0-pre.16", features = ["serde"] } html_parser = { workspace = true } cargo_metadata = "0.18.1" @@ -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,8 +90,10 @@ 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" +env_logger = "0.11.3" [features] default = [] 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/assets/autoreload.js b/packages/cli/src/assets/autoreload.js index cc8fef166..3d7d40012 100644 --- a/packages/cli/src/assets/autoreload.js +++ b/packages/cli/src/assets/autoreload.js @@ -4,7 +4,8 @@ (function () { var protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; var url = protocol + '//' + window.location.host + '/_dioxus/ws'; - var poll_interval = 8080; + var poll_interval = 8080; + var reload_upon_connect = () => { window.setTimeout( () => { @@ -15,11 +16,15 @@ poll_interval); }; - var ws = new WebSocket(url); - ws.onmessage = (ev) => { - if (ev.data == "reload") { - window.location.reload(); - } + var ws = new WebSocket(url); + + ws.onmessage = (ev) => { + console.log("Received message: ", ev, ev.data); + + if (ev.data == "reload") { + window.location.reload(); + } }; + ws.onclose = reload_upon_connect; })() diff --git a/packages/cli/src/builder.rs b/packages/cli/src/builder.rs index fa32ba0e9..9a2c0ebb5 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}; @@ -16,6 +15,7 @@ use std::{ io::Read, panic, path::PathBuf, + process::Command, time::Duration, }; use wasm_bindgen_cli_support::Bindgen; @@ -65,9 +65,8 @@ impl ExecWithRustFlagsSetter for subprocess::Exec { /// Build client (WASM). /// Note: `rust_flags` argument is only used for the fullstack platform. -pub fn build( +pub fn build_web( config: &CrateConfig, - _: bool, skip_assets: bool, rust_flags: Option, ) -> Result { @@ -100,15 +99,17 @@ pub fn build( // [1] Build the .wasm module log::info!("🚅 Running build command..."); - 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.."); - let _ = std::process::Command::new("rustup") - .args(["target", "add", "wasm32-unknown-unknown"]) - .output()?; + // If the user has rustup, we can check if the wasm32-unknown-unknown target is installed + // Otherwise we can just assume it is installed - which i snot great... + // Eventually we can poke at the errors and let the user know they need to install the target + if let Ok(wasm_check_command) = 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.."); + let _ = Command::new("rustup") + .args(["target", "add", "wasm32-unknown-unknown"]) + .output()?; + } } let cmd = subprocess::Exec::cmd("cargo") @@ -163,9 +164,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 +185,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 +225,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 +277,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 +302,7 @@ pub fn build( } } + log::info!("Processing assets"); let assets = if !skip_assets { let assets = asset_manifest(executable.executable(), config); process_assets(config, &assets)?; @@ -326,6 +335,12 @@ pub fn build_desktop( let _manganis_support = ManganisSupportGuard::default(); let _guard = AssetConfigDropGuard::new(); + // set the asset dir via cli args + env::set_var( + "DIOXUS_ASSET_DIR", + config.asset_dir().canonicalize().unwrap(), + ); + let mut cmd = subprocess::Exec::cmd("cargo") .set_rust_flags(rust_flags) .env("CARGO_TARGET_DIR", &config.target_dir) diff --git a/packages/cli/src/cli/build.rs b/packages/cli/src/cli/build.rs index 80962f005..365a4f572 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::*; @@ -51,6 +50,7 @@ impl Build { } crate_config.set_cargo_args(self.build.cargo_args.clone()); + crate_config.extend_with_platform(platform); // #[cfg(feature = "plugin")] // let _ = crate::plugin::PluginManager::on_build_start(&crate_config, &platform); @@ -58,7 +58,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_web(&crate_config, self.build.skip_assets, rust_flags)? } Platform::Desktop => { // Since desktop platform doesn't use `rust_flags`, this @@ -81,9 +81,8 @@ impl Build { } None => web_config.features = Some(vec![web_feature]), }; - crate::builder::build( + crate::builder::build_web( &web_config, - false, self.build.skip_assets, Some(client_rust_flags), )?; diff --git a/packages/cli/src/cli/bundle.rs b/packages/cli/src/cli/bundle.rs index 44c8548b3..85c21cd21 100644 --- a/packages/cli/src/cli/bundle.rs +++ b/packages/cli/src/cli/bundle.rs @@ -82,6 +82,9 @@ impl Bundle { } crate_config.set_cargo_args(self.build.cargo_args); + if let Some(platform) = self.build.platform { + crate_config.extend_with_platform(platform); + } // build the desktop app // Since the `bundle()` function is only run for the desktop platform, diff --git a/packages/cli/src/cli/cfg.rs b/packages/cli/src/cli/cfg.rs index c764d77d6..daa8ad713 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, @@ -178,7 +178,7 @@ pub struct ConfigOptsBundle { /// Build platform: support Web & Desktop [default: "default_platform"] #[clap(long)] - pub platform: Option, + pub platform: Option, /// Space separated list of features to activate #[clap(long)] 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..1ba985c13 100644 --- a/packages/cli/src/cli/serve.rs +++ b/packages/cli/src/cli/serve.rs @@ -60,25 +60,16 @@ impl Serve { } let platform = platform.unwrap_or(crate_config.dioxus_config.application.default_platform); + crate_config.extend_with_platform(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/lib.rs b/packages/cli/src/lib.rs index 191c65008..5c904d7ba 100644 --- a/packages/cli/src/lib.rs +++ b/packages/cli/src/lib.rs @@ -2,8 +2,6 @@ #![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")] #![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")] -pub const DIOXUS_CLI_VERSION: &str = "0.4.1"; - mod assets; pub mod builder; pub mod server; diff --git a/packages/cli/src/main.rs b/packages/cli/src/main.rs index d4326a696..4943e6e3b 100644 --- a/packages/cli/src/main.rs +++ b/packages/cli/src/main.rs @@ -7,47 +7,21 @@ 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(); - set_up_logging(); + #[cfg(debug_assertions)] + env_logger::init(); + + // set_up_logging(); match args.action { Translate(opts) => opts .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 +48,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 +87,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..d5b5c7b11 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_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, @@ -136,7 +138,7 @@ async fn start_desktop_hot_reload(hot_reload_state: HotReloadState) -> Result<() .unwrap() .map .values() - .filter_map(|(_, template_slot)| *template_slot) + .flat_map(|v| v.templates.values().copied()) .collect() }; for template in templates { @@ -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..332fbf909 100644 --- a/packages/cli/src/server/mod.rs +++ b/packages/cli/src/server/mod.rs @@ -3,10 +3,15 @@ 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 fs_extra::dir::CopyOptions; 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 +20,31 @@ pub mod desktop; pub mod fullstack; pub mod web; -/// Sets up a file watcher +#[derive(Clone)] +pub struct HotReloadState { + /// Pending hotreload updates to be sent to all connected clients + pub messages: broadcast::Sender, + + /// The file map that tracks the state of the projecta + pub file_map: SharedFileMap, +} +type SharedFileMap = Arc>>; + +impl HotReloadState { + pub fn all_templates(&self) -> Vec