mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-10 06:34:20 +00:00
Simplify cli-config, hotreload -> devtools (drop to 0 deps, fast compile times) (#2975)
* simplify cli-config crate * clean up configs * add devtools crate, update cargo imports * fix serve addr, fix websocket proxy issue * add comment about opt profiles * rename hot-reload to devtools
This commit is contained in:
parent
8203ee571f
commit
3fb1f739d1
58 changed files with 1131 additions and 1654 deletions
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
|
@ -4,10 +4,11 @@
|
||||||
"editor.formatOnSave": false
|
"editor.formatOnSave": false
|
||||||
},
|
},
|
||||||
// "rust-analyzer.check.workspace": true,
|
// "rust-analyzer.check.workspace": true,
|
||||||
"rust-analyzer.check.workspace": false,
|
// "rust-analyzer.check.workspace": false,
|
||||||
"rust-analyzer.check.features": "all",
|
// "rust-analyzer.check.features": "all",
|
||||||
"rust-analyzer.cargo.features": "all",
|
"rust-analyzer.cargo.features": "all",
|
||||||
"rust-analyzer.check.allTargets": true,
|
"rust-analyzer.check.features": "all",
|
||||||
|
// "rust-analyzer.check.allTargets": true,
|
||||||
// we don't want the formatter to kick in while we're working on dioxus itself
|
// we don't want the formatter to kick in while we're working on dioxus itself
|
||||||
"dioxus.formatOnSave": "disabled",
|
"dioxus.formatOnSave": "disabled",
|
||||||
}
|
}
|
||||||
|
|
273
Cargo.lock
generated
273
Cargo.lock
generated
|
@ -1225,42 +1225,6 @@ dependencies = [
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cached"
|
|
||||||
version = "0.44.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b195e4fbc4b6862bbd065b991a34750399c119797efff72492f28a5864de8700"
|
|
||||||
dependencies = [
|
|
||||||
"async-trait",
|
|
||||||
"cached_proc_macro",
|
|
||||||
"cached_proc_macro_types",
|
|
||||||
"futures",
|
|
||||||
"hashbrown 0.13.2",
|
|
||||||
"instant",
|
|
||||||
"once_cell",
|
|
||||||
"thiserror",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cached_proc_macro"
|
|
||||||
version = "0.17.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b48814962d2fd604c50d2b9433c2a41a0ab567779ee2c02f7fba6eca1221f082"
|
|
||||||
dependencies = [
|
|
||||||
"cached_proc_macro_types",
|
|
||||||
"darling 0.14.4",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cached_proc_macro_types"
|
|
||||||
version = "0.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cairo-rs"
|
name = "cairo-rs"
|
||||||
version = "0.18.5"
|
version = "0.18.5"
|
||||||
|
@ -2247,38 +2211,14 @@ dependencies = [
|
||||||
"syn 2.0.77",
|
"syn 2.0.77",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling"
|
|
||||||
version = "0.14.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core 0.14.4",
|
|
||||||
"darling_macro 0.14.4",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.20.10"
|
version = "0.20.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core 0.20.10",
|
"darling_core",
|
||||||
"darling_macro 0.20.10",
|
"darling_macro",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_core"
|
|
||||||
version = "0.14.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
|
|
||||||
dependencies = [
|
|
||||||
"fnv",
|
|
||||||
"ident_case",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"strsim 0.10.0",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2295,24 +2235,13 @@ dependencies = [
|
||||||
"syn 2.0.77",
|
"syn 2.0.77",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_macro"
|
|
||||||
version = "0.14.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core 0.14.4",
|
|
||||||
"quote",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling_macro"
|
name = "darling_macro"
|
||||||
version = "0.20.10"
|
version = "0.20.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core 0.20.10",
|
"darling_core",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.77",
|
||||||
]
|
]
|
||||||
|
@ -2437,9 +2366,9 @@ dependencies = [
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
"dioxus-core-macro",
|
"dioxus-core-macro",
|
||||||
"dioxus-desktop",
|
"dioxus-desktop",
|
||||||
|
"dioxus-devtools",
|
||||||
"dioxus-fullstack",
|
"dioxus-fullstack",
|
||||||
"dioxus-hooks",
|
"dioxus-hooks",
|
||||||
"dioxus-hot-reload",
|
|
||||||
"dioxus-html",
|
"dioxus-html",
|
||||||
"dioxus-liveview",
|
"dioxus-liveview",
|
||||||
"dioxus-mobile",
|
"dioxus-mobile",
|
||||||
|
@ -2511,7 +2440,7 @@ dependencies = [
|
||||||
"dioxus-cli-config",
|
"dioxus-cli-config",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
"dioxus-core-types",
|
"dioxus-core-types",
|
||||||
"dioxus-hot-reload",
|
"dioxus-devtools",
|
||||||
"dioxus-html",
|
"dioxus-html",
|
||||||
"dioxus-rsx",
|
"dioxus-rsx",
|
||||||
"dioxus-rsx-hotreload",
|
"dioxus-rsx-hotreload",
|
||||||
|
@ -2540,7 +2469,7 @@ dependencies = [
|
||||||
"ratatui",
|
"ratatui",
|
||||||
"rayon",
|
"rayon",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest 0.12.7",
|
"reqwest",
|
||||||
"rustls 0.23.13",
|
"rustls 0.23.13",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -2548,6 +2477,7 @@ dependencies = [
|
||||||
"syn 2.0.77",
|
"syn 2.0.77",
|
||||||
"tar",
|
"tar",
|
||||||
"tauri-bundler",
|
"tauri-bundler",
|
||||||
|
"tauri-utils",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -2568,19 +2498,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-cli-config"
|
name = "dioxus-cli-config"
|
||||||
version = "0.6.0-alpha.2"
|
version = "0.6.0-alpha.2"
|
||||||
dependencies = [
|
|
||||||
"built",
|
|
||||||
"cargo_toml",
|
|
||||||
"clap",
|
|
||||||
"dirs",
|
|
||||||
"once_cell",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"tauri-bundler",
|
|
||||||
"tauri-utils",
|
|
||||||
"toml 0.8.19",
|
|
||||||
"tracing",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-config-macro"
|
name = "dioxus-config-macro"
|
||||||
|
@ -2605,7 +2522,7 @@ dependencies = [
|
||||||
"manganis",
|
"manganis",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"reqwest 0.12.7",
|
"reqwest",
|
||||||
"rustc-hash 1.1.0",
|
"rustc-hash 1.1.0",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -2649,8 +2566,8 @@ dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-cli-config",
|
"dioxus-cli-config",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
|
"dioxus-devtools",
|
||||||
"dioxus-hooks",
|
"dioxus-hooks",
|
||||||
"dioxus-hot-reload",
|
|
||||||
"dioxus-html",
|
"dioxus-html",
|
||||||
"dioxus-interpreter-js",
|
"dioxus-interpreter-js",
|
||||||
"dioxus-signals",
|
"dioxus-signals",
|
||||||
|
@ -2667,7 +2584,7 @@ dependencies = [
|
||||||
"objc",
|
"objc",
|
||||||
"objc_id",
|
"objc_id",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"reqwest 0.12.7",
|
"reqwest",
|
||||||
"rfd",
|
"rfd",
|
||||||
"rustc-hash 1.1.0",
|
"rustc-hash 1.1.0",
|
||||||
"separator",
|
"separator",
|
||||||
|
@ -2685,6 +2602,29 @@ dependencies = [
|
||||||
"wry",
|
"wry",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dioxus-devtools"
|
||||||
|
version = "0.6.0-alpha.2"
|
||||||
|
dependencies = [
|
||||||
|
"dioxus-core",
|
||||||
|
"dioxus-devtools-types",
|
||||||
|
"dioxus-signals",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"tungstenite 0.23.0",
|
||||||
|
"warnings",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dioxus-devtools-types"
|
||||||
|
version = "0.6.0-alpha.2"
|
||||||
|
dependencies = [
|
||||||
|
"dioxus-core",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-examples"
|
name = "dioxus-examples"
|
||||||
version = "0.6.0-alpha.2"
|
version = "0.6.0-alpha.2"
|
||||||
|
@ -2700,7 +2640,7 @@ dependencies = [
|
||||||
"http-range",
|
"http-range",
|
||||||
"manganis",
|
"manganis",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"reqwest 0.12.7",
|
"reqwest",
|
||||||
"separator",
|
"separator",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -2730,11 +2670,10 @@ dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"ciborium",
|
"ciborium",
|
||||||
"clap",
|
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-cli-config",
|
"dioxus-cli-config",
|
||||||
"dioxus-desktop",
|
"dioxus-desktop",
|
||||||
"dioxus-hot-reload",
|
"dioxus-devtools",
|
||||||
"dioxus-interpreter-js",
|
"dioxus-interpreter-js",
|
||||||
"dioxus-isrg",
|
"dioxus-isrg",
|
||||||
"dioxus-lib",
|
"dioxus-lib",
|
||||||
|
@ -2776,7 +2715,7 @@ dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"generational-box",
|
"generational-box",
|
||||||
"reqwest 0.12.7",
|
"reqwest",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"slab",
|
"slab",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -2785,31 +2724,6 @@ dependencies = [
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "dioxus-hot-reload"
|
|
||||||
version = "0.6.0-alpha.2"
|
|
||||||
dependencies = [
|
|
||||||
"chrono",
|
|
||||||
"dioxus-cli-config",
|
|
||||||
"dioxus-core",
|
|
||||||
"dioxus-html",
|
|
||||||
"dioxus-rsx",
|
|
||||||
"dioxus-rsx-hotreload",
|
|
||||||
"dioxus-signals",
|
|
||||||
"execute",
|
|
||||||
"futures-util",
|
|
||||||
"ignore",
|
|
||||||
"notify",
|
|
||||||
"once_cell",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"tokio",
|
|
||||||
"tokio-stream",
|
|
||||||
"tokio-tungstenite 0.23.1",
|
|
||||||
"tracing",
|
|
||||||
"warnings",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dioxus-html"
|
name = "dioxus-html"
|
||||||
version = "0.6.0-alpha.2"
|
version = "0.6.0-alpha.2"
|
||||||
|
@ -2905,7 +2819,7 @@ dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-cli-config",
|
"dioxus-cli-config",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
"dioxus-hot-reload",
|
"dioxus-devtools",
|
||||||
"dioxus-html",
|
"dioxus-html",
|
||||||
"dioxus-interpreter-js",
|
"dioxus-interpreter-js",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
|
@ -3087,7 +3001,7 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"reqwest 0.12.7",
|
"reqwest",
|
||||||
"rustc-hash 1.1.0",
|
"rustc-hash 1.1.0",
|
||||||
"serde",
|
"serde",
|
||||||
"simple_logger",
|
"simple_logger",
|
||||||
|
@ -3116,8 +3030,8 @@ dependencies = [
|
||||||
"criterion",
|
"criterion",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-cli-config",
|
"dioxus-cli-config",
|
||||||
|
"dioxus-devtools",
|
||||||
"dioxus-fullstack",
|
"dioxus-fullstack",
|
||||||
"dioxus-hot-reload",
|
|
||||||
"dioxus-isrg",
|
"dioxus-isrg",
|
||||||
"dioxus-lib",
|
"dioxus-lib",
|
||||||
"dioxus-router",
|
"dioxus-router",
|
||||||
|
@ -3147,7 +3061,7 @@ dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"dioxus-core",
|
"dioxus-core",
|
||||||
"dioxus-core-types",
|
"dioxus-core-types",
|
||||||
"dioxus-hot-reload",
|
"dioxus-devtools",
|
||||||
"dioxus-html",
|
"dioxus-html",
|
||||||
"dioxus-interpreter-js",
|
"dioxus-interpreter-js",
|
||||||
"dioxus-signals",
|
"dioxus-signals",
|
||||||
|
@ -3301,10 +3215,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||||
name = "ecommerce-site"
|
name = "ecommerce-site"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cached",
|
|
||||||
"chrono",
|
"chrono",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"reqwest 0.11.27",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3374,7 +3287,7 @@ version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242"
|
checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling 0.20.10",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.77",
|
||||||
|
@ -3787,7 +3700,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"reqwest 0.12.7",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
|
@ -3799,7 +3712,7 @@ name = "fullstack-hello-world-example"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dioxus",
|
"dioxus",
|
||||||
"reqwest 0.12.7",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"simple_logger",
|
"simple_logger",
|
||||||
"tracing",
|
"tracing",
|
||||||
|
@ -5242,19 +5155,6 @@ dependencies = [
|
||||||
"tokio-io-timeout",
|
"tokio-io-timeout",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hyper-tls"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
|
|
||||||
dependencies = [
|
|
||||||
"bytes",
|
|
||||||
"hyper 0.14.30",
|
|
||||||
"native-tls",
|
|
||||||
"tokio",
|
|
||||||
"tokio-native-tls",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-tls"
|
name = "hyper-tls"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
@ -6236,7 +6136,7 @@ dependencies = [
|
||||||
"railwind",
|
"railwind",
|
||||||
"ravif",
|
"ravif",
|
||||||
"rayon",
|
"rayon",
|
||||||
"reqwest 0.12.7",
|
"reqwest",
|
||||||
"rustc-hash 1.1.0",
|
"rustc-hash 1.1.0",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -8245,46 +8145,6 @@ dependencies = [
|
||||||
"bytecheck",
|
"bytecheck",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "reqwest"
|
|
||||||
version = "0.11.27"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
|
||||||
dependencies = [
|
|
||||||
"base64 0.21.7",
|
|
||||||
"bytes",
|
|
||||||
"encoding_rs",
|
|
||||||
"futures-core",
|
|
||||||
"futures-util",
|
|
||||||
"h2 0.3.26",
|
|
||||||
"http 0.2.12",
|
|
||||||
"http-body 0.4.6",
|
|
||||||
"hyper 0.14.30",
|
|
||||||
"hyper-tls 0.5.0",
|
|
||||||
"ipnet",
|
|
||||||
"js-sys",
|
|
||||||
"log",
|
|
||||||
"mime",
|
|
||||||
"native-tls",
|
|
||||||
"once_cell",
|
|
||||||
"percent-encoding",
|
|
||||||
"pin-project-lite",
|
|
||||||
"rustls-pemfile 1.0.4",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"serde_urlencoded",
|
|
||||||
"sync_wrapper 0.1.2",
|
|
||||||
"system-configuration 0.5.1",
|
|
||||||
"tokio",
|
|
||||||
"tokio-native-tls",
|
|
||||||
"tower-service",
|
|
||||||
"url",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"wasm-bindgen-futures",
|
|
||||||
"web-sys",
|
|
||||||
"winreg 0.50.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.12.7"
|
version = "0.12.7"
|
||||||
|
@ -8303,7 +8163,7 @@ dependencies = [
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper 1.4.1",
|
"hyper 1.4.1",
|
||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
"hyper-tls 0.6.0",
|
"hyper-tls",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"ipnet",
|
"ipnet",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
@ -8322,7 +8182,7 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sync_wrapper 1.0.1",
|
"sync_wrapper 1.0.1",
|
||||||
"system-configuration 0.6.1",
|
"system-configuration",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-native-tls",
|
"tokio-native-tls",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
|
@ -8941,7 +8801,7 @@ version = "3.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350"
|
checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling 0.20.10",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.77",
|
"syn 2.0.77",
|
||||||
|
@ -8965,7 +8825,7 @@ dependencies = [
|
||||||
"inventory",
|
"inventory",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"reqwest 0.12.7",
|
"reqwest",
|
||||||
"send_wrapper",
|
"send_wrapper",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -11214,17 +11074,6 @@ dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "system-configuration"
|
|
||||||
version = "0.5.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
"core-foundation 0.9.4",
|
|
||||||
"system-configuration-sys 0.5.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-configuration"
|
name = "system-configuration"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
@ -11233,17 +11082,7 @@ checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"core-foundation 0.9.4",
|
"core-foundation 0.9.4",
|
||||||
"system-configuration-sys 0.6.0",
|
"system-configuration-sys",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "system-configuration-sys"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9"
|
|
||||||
dependencies = [
|
|
||||||
"core-foundation-sys",
|
|
||||||
"libc",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -11378,7 +11217,7 @@ dependencies = [
|
||||||
"uuid",
|
"uuid",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
"winreg 0.51.0",
|
"winreg",
|
||||||
"zip",
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -13247,16 +13086,6 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winreg"
|
|
||||||
version = "0.50.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"windows-sys 0.48.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winreg"
|
name = "winreg"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
|
|
19
Cargo.toml
19
Cargo.toml
|
@ -28,7 +28,8 @@ members = [
|
||||||
"packages/rsx-rosetta",
|
"packages/rsx-rosetta",
|
||||||
"packages/generational-box",
|
"packages/generational-box",
|
||||||
"packages/signals",
|
"packages/signals",
|
||||||
"packages/hot-reload",
|
"packages/devtools",
|
||||||
|
"packages/devtools-types",
|
||||||
"packages/fullstack",
|
"packages/fullstack",
|
||||||
"packages/server-macro",
|
"packages/server-macro",
|
||||||
"packages/static-generation",
|
"packages/static-generation",
|
||||||
|
@ -91,9 +92,10 @@ dioxus-rsx = { path = "packages/rsx", version = "0.6.0-alpha.0" }
|
||||||
dioxus-rsx-hotreload = { path = "packages/rsx-hotreload", version = "0.6.0-alpha.0" }
|
dioxus-rsx-hotreload = { path = "packages/rsx-hotreload", version = "0.6.0-alpha.0" }
|
||||||
dioxus-rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.6.0-alpha.0" }
|
dioxus-rsx-rosetta = { path = "packages/rsx-rosetta", version = "0.6.0-alpha.0" }
|
||||||
dioxus-signals = { path = "packages/signals", version = "0.6.0-alpha.0" }
|
dioxus-signals = { path = "packages/signals", version = "0.6.0-alpha.0" }
|
||||||
dioxus-cli-config = { path = "packages/cli-config", version = "0.6.0-alpha.0", default-features = false}
|
dioxus-cli-config = { path = "packages/cli-config", version = "0.6.0-alpha.0" }
|
||||||
generational-box = { path = "packages/generational-box", version = "0.6.0-alpha.0" }
|
generational-box = { path = "packages/generational-box", version = "0.6.0-alpha.0" }
|
||||||
dioxus-hot-reload = { path = "packages/hot-reload", version = "0.6.0-alpha.0" }
|
dioxus-devtools = { path = "packages/devtools", version = "0.6.0-alpha.0" }
|
||||||
|
dioxus-devtools-types = { path = "packages/devtools-types", version = "0.6.0-alpha.0" }
|
||||||
dioxus-fullstack = { path = "packages/fullstack", version = "0.6.0-alpha.1" }
|
dioxus-fullstack = { path = "packages/fullstack", version = "0.6.0-alpha.1" }
|
||||||
dioxus-static-site-generation = { path = "packages/static-generation", version = "0.6.0-alpha.0" }
|
dioxus-static-site-generation = { path = "packages/static-generation", version = "0.6.0-alpha.0" }
|
||||||
dioxus_server_macro = { path = "packages/server-macro", version = "0.6.0-alpha.0", default-features = false }
|
dioxus_server_macro = { path = "packages/server-macro", version = "0.6.0-alpha.0", default-features = false }
|
||||||
|
@ -171,6 +173,7 @@ web-sys = { version = "0.3.56", default-features = false }
|
||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
cargo-config2 = "0.1.26"
|
cargo-config2 = "0.1.26"
|
||||||
criterion = { version = "0.5" }
|
criterion = { version = "0.5" }
|
||||||
|
walrus = "*"
|
||||||
|
|
||||||
# desktop
|
# desktop
|
||||||
wry = { version = "0.43.0", default-features = false }
|
wry = { version = "0.43.0", default-features = false }
|
||||||
|
@ -190,13 +193,9 @@ objc_id = "0.1.1"
|
||||||
[profile.dev.package.dioxus-core-macro]
|
[profile.dev.package.dioxus-core-macro]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
# Enable a small amount of optimization in debug mode
|
# wasm bindgen is slooooooow, but it's because we're actually processing the wasm
|
||||||
[profile.cli-dev]
|
# so, lets just bump up walrus to make it faster, no need for any special profiles
|
||||||
inherits = "dev"
|
[profile.dev.package.walrus]
|
||||||
opt-level = 1
|
|
||||||
|
|
||||||
# Enable high optimizations for dependencies (incl. Bevy), but not for our code:
|
|
||||||
[profile.cli-dev.package."*"]
|
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
# Disable debug assertions to check the released path of core and other packages, but build without optimizations to keep build times quick
|
# Disable debug assertions to check the released path of core and other packages, but build without optimizations to keep build times quick
|
||||||
|
|
|
@ -6,11 +6,15 @@ edition = "2018"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cached = "0.44.0"
|
|
||||||
dioxus = { workspace = true, features = ["fullstack", "router"] }
|
dioxus = { workspace = true, features = ["fullstack", "router"] }
|
||||||
reqwest = { version = "0.11.16", features = ["json"] }
|
reqwest = { workspace = true, features = ["json"] }
|
||||||
serde = "1.0.160"
|
serde = { workspace = true }
|
||||||
chrono = { version = "0.4.24", features = ["serde"] }
|
|
||||||
|
[target.'cfg(target_family = "wasm")'.dependencies]
|
||||||
|
chrono = { workspace = true, features = ["serde", "wasmbind"] }
|
||||||
|
|
||||||
|
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||||
|
chrono = { workspace = true, features = ["serde"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
web = ["dioxus/web"]
|
web = ["dioxus/web"]
|
||||||
|
|
|
@ -55,7 +55,6 @@ impl Display for Sort {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache up to 100 requests, invalidating them after 60 seconds
|
// Cache up to 100 requests, invalidating them after 60 seconds
|
||||||
#[cached::proc_macro::cached(size = 100, time = 60, result = true)]
|
|
||||||
pub(crate) async fn fetch_user_carts(user_id: usize) -> Result<Vec<Cart>, reqwest::Error> {
|
pub(crate) async fn fetch_user_carts(user_id: usize) -> Result<Vec<Cart>, reqwest::Error> {
|
||||||
reqwest::get(format!(
|
reqwest::get(format!(
|
||||||
"https://fakestoreapi.com/carts/user/{user_id}?startdate=2019-12-10&enddate=2023-01-01"
|
"https://fakestoreapi.com/carts/user/{user_id}?startdate=2019-12-10&enddate=2023-01-01"
|
||||||
|
@ -66,7 +65,6 @@ pub(crate) async fn fetch_user_carts(user_id: usize) -> Result<Vec<Cart>, reqwes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache up to 100 requests, invalidating them after 60 seconds
|
// Cache up to 100 requests, invalidating them after 60 seconds
|
||||||
#[cached::proc_macro::cached(size = 100, time = 60, result = true)]
|
|
||||||
pub(crate) async fn fetch_user(user_id: usize) -> dioxus::Result<Product> {
|
pub(crate) async fn fetch_user(user_id: usize) -> dioxus::Result<Product> {
|
||||||
Ok(
|
Ok(
|
||||||
reqwest::get(format!("https://fakestoreapi.com/users/{user_id}"))
|
reqwest::get(format!("https://fakestoreapi.com/users/{user_id}"))
|
||||||
|
@ -77,7 +75,6 @@ pub(crate) async fn fetch_user(user_id: usize) -> dioxus::Result<Product> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache up to 100 requests, invalidating them after 60 seconds
|
// Cache up to 100 requests, invalidating them after 60 seconds
|
||||||
#[cached::proc_macro::cached(size = 100, time = 60, result = true)]
|
|
||||||
pub(crate) async fn fetch_product(product_id: usize) -> dioxus::Result<Product> {
|
pub(crate) async fn fetch_product(product_id: usize) -> dioxus::Result<Product> {
|
||||||
Ok(
|
Ok(
|
||||||
reqwest::get(format!("https://fakestoreapi.com/products/{product_id}"))
|
reqwest::get(format!("https://fakestoreapi.com/products/{product_id}"))
|
||||||
|
@ -88,7 +85,6 @@ pub(crate) async fn fetch_product(product_id: usize) -> dioxus::Result<Product>
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache up to 100 requests, invalidating them after 60 seconds
|
// Cache up to 100 requests, invalidating them after 60 seconds
|
||||||
#[cached::proc_macro::cached(size = 100, time = 60, result = true)]
|
|
||||||
pub(crate) async fn fetch_products(count: usize, sort: Sort) -> dioxus::Result<Vec<Product>> {
|
pub(crate) async fn fetch_products(count: usize, sort: Sort) -> dioxus::Result<Vec<Product>> {
|
||||||
Ok(reqwest::get(format!(
|
Ok(reqwest::get(format!(
|
||||||
"https://fakestoreapi.com/products/?sort={sort}&limit={count}"
|
"https://fakestoreapi.com/products/?sort={sort}&limit={count}"
|
||||||
|
|
|
@ -1,36 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "dioxus-cli-config"
|
name = "dioxus-cli-config"
|
||||||
version = { workspace = true }
|
|
||||||
authors = ["Jonathan Kelley"]
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Configuration for the Dioxus CLI"
|
version.workspace = true
|
||||||
repository = "https://github.com/DioxusLabs/dioxus/"
|
|
||||||
license = "MIT OR Apache-2.0"
|
|
||||||
keywords = ["react", "gui", "cli", "dioxus", "wasm"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.2", features = ["derive"], optional = true }
|
|
||||||
serde = { version = "1.0.136", features = ["derive"] }
|
|
||||||
serde_json = "1.0.79"
|
|
||||||
toml = { workspace = true, optional = true }
|
|
||||||
cargo_toml = { workspace = true, optional = true }
|
|
||||||
once_cell = "1.18.0"
|
|
||||||
tracing = { workspace = true }
|
|
||||||
|
|
||||||
# bundling
|
|
||||||
tauri-bundler = { workspace = true, optional = true }
|
|
||||||
tauri-utils = { workspace = true, optional = true }
|
|
||||||
|
|
||||||
dirs = { workspace = true, optional = true }
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
built = { version = "=0.7.4", features = ["git2"] }
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["read-config"]
|
|
||||||
cli = ["dep:tauri-bundler", "dep:tauri-utils", "read-from-args", "dep:toml", "dep:cargo_toml", "dep:dirs"]
|
|
||||||
read-config = []
|
|
||||||
read-from-args = ["dep:clap"]
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<div>
|
# dioxus-cli-config
|
||||||
<h1>📦✨ Dioxus CLI Configuration</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
The **dioxus-cli-config** contains the configuration for the **dioxus-cli**.
|
A crate that provides key/value names and types for configuring Dioxus applications at runtime.
|
||||||
|
|
||||||
|
This crate exists for us to very cleanly define the exact fields we want to pass down to Dioxus applications at runtime but without exposing the entire config object.
|
||||||
|
|
||||||
|
This leads to faster compile times, smaller binaries, and a clearer distinction between the config and the application.
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
fn main() {
|
|
||||||
built::write_built_file().expect("Failed to acquire build-time information");
|
|
||||||
}
|
|
|
@ -1,260 +0,0 @@
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
||||||
pub struct BundleConfig {
|
|
||||||
pub identifier: Option<String>,
|
|
||||||
pub publisher: Option<String>,
|
|
||||||
pub icon: Option<Vec<String>>,
|
|
||||||
pub resources: Option<Vec<String>>,
|
|
||||||
pub copyright: Option<String>,
|
|
||||||
pub category: Option<String>,
|
|
||||||
pub short_description: Option<String>,
|
|
||||||
pub long_description: Option<String>,
|
|
||||||
pub external_bin: Option<Vec<String>>,
|
|
||||||
pub deb: Option<DebianSettings>,
|
|
||||||
pub macos: Option<MacOsSettings>,
|
|
||||||
pub windows: Option<WindowsSettings>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
|
||||||
impl From<BundleConfig> for tauri_bundler::BundleSettings {
|
|
||||||
fn from(val: BundleConfig) -> Self {
|
|
||||||
tauri_bundler::BundleSettings {
|
|
||||||
identifier: val.identifier,
|
|
||||||
publisher: val.publisher,
|
|
||||||
icon: val.icon,
|
|
||||||
resources: val.resources,
|
|
||||||
copyright: val.copyright,
|
|
||||||
category: val.category.and_then(|c| c.parse().ok()),
|
|
||||||
short_description: val.short_description,
|
|
||||||
long_description: val.long_description,
|
|
||||||
external_bin: val.external_bin,
|
|
||||||
deb: val.deb.map(Into::into).unwrap_or_default(),
|
|
||||||
macos: val.macos.map(Into::into).unwrap_or_default(),
|
|
||||||
windows: val.windows.map(Into::into).unwrap_or_default(),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
||||||
pub struct DebianSettings {
|
|
||||||
pub depends: Option<Vec<String>>,
|
|
||||||
pub files: HashMap<PathBuf, PathBuf>,
|
|
||||||
pub nsis: Option<NsisSettings>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
|
||||||
impl From<DebianSettings> for tauri_bundler::DebianSettings {
|
|
||||||
fn from(val: DebianSettings) -> Self {
|
|
||||||
tauri_bundler::DebianSettings {
|
|
||||||
depends: val.depends,
|
|
||||||
files: val.files,
|
|
||||||
desktop_template: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
||||||
pub struct WixSettings {
|
|
||||||
pub language: Vec<(String, Option<PathBuf>)>,
|
|
||||||
pub template: Option<PathBuf>,
|
|
||||||
pub fragment_paths: Vec<PathBuf>,
|
|
||||||
pub component_group_refs: Vec<String>,
|
|
||||||
pub component_refs: Vec<String>,
|
|
||||||
pub feature_group_refs: Vec<String>,
|
|
||||||
pub feature_refs: Vec<String>,
|
|
||||||
pub merge_refs: Vec<String>,
|
|
||||||
pub skip_webview_install: bool,
|
|
||||||
pub license: Option<PathBuf>,
|
|
||||||
pub enable_elevated_update_task: bool,
|
|
||||||
pub banner_path: Option<PathBuf>,
|
|
||||||
pub dialog_image_path: Option<PathBuf>,
|
|
||||||
pub fips_compliant: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
|
||||||
impl From<WixSettings> for tauri_bundler::WixSettings {
|
|
||||||
fn from(val: WixSettings) -> Self {
|
|
||||||
tauri_bundler::WixSettings {
|
|
||||||
language: tauri_bundler::bundle::WixLanguage({
|
|
||||||
let mut languages: Vec<_> = val
|
|
||||||
.language
|
|
||||||
.iter()
|
|
||||||
.map(|l| {
|
|
||||||
(
|
|
||||||
l.0.clone(),
|
|
||||||
tauri_bundler::bundle::WixLanguageConfig {
|
|
||||||
locale_path: l.1.clone(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
if languages.is_empty() {
|
|
||||||
languages.push(("en-US".into(), Default::default()));
|
|
||||||
}
|
|
||||||
languages
|
|
||||||
}),
|
|
||||||
template: val.template,
|
|
||||||
fragment_paths: val.fragment_paths,
|
|
||||||
component_group_refs: val.component_group_refs,
|
|
||||||
component_refs: val.component_refs,
|
|
||||||
feature_group_refs: val.feature_group_refs,
|
|
||||||
feature_refs: val.feature_refs,
|
|
||||||
merge_refs: val.merge_refs,
|
|
||||||
skip_webview_install: val.skip_webview_install,
|
|
||||||
license: val.license,
|
|
||||||
enable_elevated_update_task: val.enable_elevated_update_task,
|
|
||||||
banner_path: val.banner_path,
|
|
||||||
dialog_image_path: val.dialog_image_path,
|
|
||||||
fips_compliant: val.fips_compliant,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
||||||
pub struct MacOsSettings {
|
|
||||||
pub frameworks: Option<Vec<String>>,
|
|
||||||
pub minimum_system_version: Option<String>,
|
|
||||||
pub license: Option<String>,
|
|
||||||
pub exception_domain: Option<String>,
|
|
||||||
pub signing_identity: Option<String>,
|
|
||||||
pub provider_short_name: Option<String>,
|
|
||||||
pub entitlements: Option<String>,
|
|
||||||
pub info_plist_path: Option<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
|
||||||
impl From<MacOsSettings> for tauri_bundler::MacOsSettings {
|
|
||||||
fn from(val: MacOsSettings) -> Self {
|
|
||||||
tauri_bundler::MacOsSettings {
|
|
||||||
frameworks: val.frameworks,
|
|
||||||
minimum_system_version: val.minimum_system_version,
|
|
||||||
license: val.license,
|
|
||||||
exception_domain: val.exception_domain,
|
|
||||||
signing_identity: val.signing_identity,
|
|
||||||
provider_short_name: val.provider_short_name,
|
|
||||||
entitlements: val.entitlements,
|
|
||||||
info_plist_path: val.info_plist_path,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct WindowsSettings {
|
|
||||||
pub digest_algorithm: Option<String>,
|
|
||||||
pub certificate_thumbprint: Option<String>,
|
|
||||||
pub timestamp_url: Option<String>,
|
|
||||||
pub tsp: bool,
|
|
||||||
pub wix: Option<WixSettings>,
|
|
||||||
pub icon_path: Option<PathBuf>,
|
|
||||||
pub webview_install_mode: WebviewInstallMode,
|
|
||||||
pub webview_fixed_runtime_path: Option<PathBuf>,
|
|
||||||
pub allow_downgrades: bool,
|
|
||||||
pub nsis: Option<NsisSettings>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
|
||||||
impl From<WindowsSettings> for tauri_bundler::WindowsSettings {
|
|
||||||
fn from(val: WindowsSettings) -> Self {
|
|
||||||
tauri_bundler::WindowsSettings {
|
|
||||||
digest_algorithm: val.digest_algorithm,
|
|
||||||
certificate_thumbprint: val.certificate_thumbprint,
|
|
||||||
timestamp_url: val.timestamp_url,
|
|
||||||
tsp: val.tsp,
|
|
||||||
wix: val.wix.map(Into::into),
|
|
||||||
icon_path: val.icon_path.unwrap_or("icons/icon.ico".into()),
|
|
||||||
webview_install_mode: val.webview_install_mode.into(),
|
|
||||||
webview_fixed_runtime_path: val.webview_fixed_runtime_path,
|
|
||||||
allow_downgrades: val.allow_downgrades,
|
|
||||||
nsis: val.nsis.map(Into::into),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct NsisSettings {
|
|
||||||
pub template: Option<PathBuf>,
|
|
||||||
pub license: Option<PathBuf>,
|
|
||||||
pub header_image: Option<PathBuf>,
|
|
||||||
pub sidebar_image: Option<PathBuf>,
|
|
||||||
pub installer_icon: Option<PathBuf>,
|
|
||||||
pub install_mode: NSISInstallerMode,
|
|
||||||
pub languages: Option<Vec<String>>,
|
|
||||||
pub custom_language_files: Option<HashMap<String, PathBuf>>,
|
|
||||||
pub display_language_selector: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
|
||||||
impl From<NsisSettings> for tauri_bundler::NsisSettings {
|
|
||||||
fn from(val: NsisSettings) -> Self {
|
|
||||||
tauri_bundler::NsisSettings {
|
|
||||||
license: val.license,
|
|
||||||
header_image: val.header_image,
|
|
||||||
sidebar_image: val.sidebar_image,
|
|
||||||
installer_icon: val.installer_icon,
|
|
||||||
install_mode: val.install_mode.into(),
|
|
||||||
languages: val.languages,
|
|
||||||
display_language_selector: val.display_language_selector,
|
|
||||||
custom_language_files: None,
|
|
||||||
template: None,
|
|
||||||
compression: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub enum NSISInstallerMode {
|
|
||||||
CurrentUser,
|
|
||||||
PerMachine,
|
|
||||||
Both,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
|
||||||
impl From<NSISInstallerMode> for tauri_utils::config::NSISInstallerMode {
|
|
||||||
fn from(val: NSISInstallerMode) -> Self {
|
|
||||||
match val {
|
|
||||||
NSISInstallerMode::CurrentUser => tauri_utils::config::NSISInstallerMode::CurrentUser,
|
|
||||||
NSISInstallerMode::PerMachine => tauri_utils::config::NSISInstallerMode::PerMachine,
|
|
||||||
NSISInstallerMode::Both => tauri_utils::config::NSISInstallerMode::Both,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub enum WebviewInstallMode {
|
|
||||||
Skip,
|
|
||||||
DownloadBootstrapper { silent: bool },
|
|
||||||
EmbedBootstrapper { silent: bool },
|
|
||||||
OfflineInstaller { silent: bool },
|
|
||||||
FixedRuntime { path: PathBuf },
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
|
||||||
impl WebviewInstallMode {
|
|
||||||
fn into(self) -> tauri_utils::config::WebviewInstallMode {
|
|
||||||
match self {
|
|
||||||
Self::Skip => tauri_utils::config::WebviewInstallMode::Skip,
|
|
||||||
Self::DownloadBootstrapper { silent } => {
|
|
||||||
tauri_utils::config::WebviewInstallMode::DownloadBootstrapper { silent }
|
|
||||||
}
|
|
||||||
Self::EmbedBootstrapper { silent } => {
|
|
||||||
tauri_utils::config::WebviewInstallMode::EmbedBootstrapper { silent }
|
|
||||||
}
|
|
||||||
Self::OfflineInstaller { silent } => {
|
|
||||||
tauri_utils::config::WebviewInstallMode::OfflineInstaller { silent }
|
|
||||||
}
|
|
||||||
Self::FixedRuntime { path } => {
|
|
||||||
tauri_utils::config::WebviewInstallMode::FixedRuntime { path }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for WebviewInstallMode {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::OfflineInstaller { silent: false }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,372 +0,0 @@
|
||||||
use crate::BundleConfig;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[derive(
|
|
||||||
Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug, Default,
|
|
||||||
)]
|
|
||||||
#[cfg_attr(feature = "cli", derive(clap::ValueEnum))]
|
|
||||||
#[non_exhaustive]
|
|
||||||
pub enum Platform {
|
|
||||||
/// Targeting the web platform using WASM
|
|
||||||
#[cfg_attr(feature = "cli", clap(name = "web"))]
|
|
||||||
#[serde(rename = "web")]
|
|
||||||
#[default]
|
|
||||||
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,
|
|
||||||
|
|
||||||
/// Targeting the static generation platform using SSR and Dioxus-Fullstack
|
|
||||||
#[cfg_attr(feature = "cli", clap(name = "static-generation"))]
|
|
||||||
#[serde(rename = "static-generation")]
|
|
||||||
StaticGeneration,
|
|
||||||
|
|
||||||
/// Targeting the static generation platform using SSR and Dioxus-Fullstack
|
|
||||||
#[cfg_attr(feature = "cli", clap(name = "liveview"))]
|
|
||||||
#[serde(rename = "liveview")]
|
|
||||||
Liveview,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An error that occurs when a platform is not recognized
|
|
||||||
pub struct UnknownPlatformError;
|
|
||||||
|
|
||||||
impl std::fmt::Display for UnknownPlatformError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
write!(f, "Unknown platform")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Platform {
|
|
||||||
type Err = UnknownPlatformError;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
match s {
|
|
||||||
"web" => Ok(Self::Web),
|
|
||||||
"desktop" => Ok(Self::Desktop),
|
|
||||||
"fullstack" => Ok(Self::Fullstack),
|
|
||||||
"static-generation" => Ok(Self::StaticGeneration),
|
|
||||||
"liveview" => Ok(Self::Liveview),
|
|
||||||
_ => Err(UnknownPlatformError),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Platform {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
let feature = self.feature_name();
|
|
||||||
f.write_str(feature)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Platform {
|
|
||||||
/// All platforms the dioxus CLI supports
|
|
||||||
pub const ALL: &'static [Self] = &[
|
|
||||||
Platform::Web,
|
|
||||||
Platform::Desktop,
|
|
||||||
Platform::Fullstack,
|
|
||||||
Platform::StaticGeneration,
|
|
||||||
];
|
|
||||||
|
|
||||||
/// Get the feature name for the platform in the dioxus crate
|
|
||||||
pub fn feature_name(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
Platform::Web => "web",
|
|
||||||
Platform::Desktop => "desktop",
|
|
||||||
Platform::Fullstack => "fullstack",
|
|
||||||
Platform::StaticGeneration => "static-generation",
|
|
||||||
Platform::Liveview => "liveview",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct DioxusConfig {
|
|
||||||
pub application: ApplicationConfig,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
pub web: WebConfig,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
pub desktop: DesktopConfig,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
pub bundle: BundleConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for DioxusConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
let name = default_name();
|
|
||||||
Self {
|
|
||||||
application: ApplicationConfig {
|
|
||||||
name: name.clone(),
|
|
||||||
default_platform: default_platform(),
|
|
||||||
out_dir: out_dir_default(),
|
|
||||||
asset_dir: asset_dir_default(),
|
|
||||||
|
|
||||||
sub_package: None,
|
|
||||||
},
|
|
||||||
web: WebConfig {
|
|
||||||
app: WebAppConfig {
|
|
||||||
title: default_title(),
|
|
||||||
base_path: None,
|
|
||||||
},
|
|
||||||
proxy: vec![],
|
|
||||||
watcher: Default::default(),
|
|
||||||
resource: WebResourceConfig {
|
|
||||||
dev: WebDevResourceConfig {
|
|
||||||
style: vec![],
|
|
||||||
script: vec![],
|
|
||||||
},
|
|
||||||
style: Some(vec![]),
|
|
||||||
script: Some(vec![]),
|
|
||||||
},
|
|
||||||
https: WebHttpsConfig {
|
|
||||||
enabled: None,
|
|
||||||
mkcert: None,
|
|
||||||
key_path: None,
|
|
||||||
cert_path: None,
|
|
||||||
},
|
|
||||||
pre_compress: true,
|
|
||||||
wasm_opt: Default::default(),
|
|
||||||
},
|
|
||||||
desktop: DesktopConfig::default(),
|
|
||||||
bundle: BundleConfig {
|
|
||||||
identifier: Some(format!("io.github.{name}")),
|
|
||||||
publisher: Some(name),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
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,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
pub sub_package: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_name() -> String {
|
|
||||||
"my-cool-project".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_platform() -> Platform {
|
|
||||||
Platform::Web
|
|
||||||
}
|
|
||||||
|
|
||||||
fn asset_dir_default() -> PathBuf {
|
|
||||||
PathBuf::from("public")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn out_dir_default() -> PathBuf {
|
|
||||||
PathBuf::from("dist")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct WebConfig {
|
|
||||||
#[serde(default)]
|
|
||||||
pub app: WebAppConfig,
|
|
||||||
#[serde(default)]
|
|
||||||
pub proxy: Vec<WebProxyConfig>,
|
|
||||||
#[serde(default)]
|
|
||||||
pub watcher: WebWatcherConfig,
|
|
||||||
#[serde(default)]
|
|
||||||
pub resource: WebResourceConfig,
|
|
||||||
#[serde(default)]
|
|
||||||
pub https: WebHttpsConfig,
|
|
||||||
/// Whether to enable pre-compression of assets and wasm during a web build in release mode
|
|
||||||
#[serde(default = "true_bool")]
|
|
||||||
pub pre_compress: bool,
|
|
||||||
/// The wasm-opt configuration
|
|
||||||
#[serde(default)]
|
|
||||||
pub wasm_opt: WasmOptConfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for WebConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
pre_compress: true_bool(),
|
|
||||||
app: Default::default(),
|
|
||||||
https: Default::default(),
|
|
||||||
wasm_opt: Default::default(),
|
|
||||||
proxy: Default::default(),
|
|
||||||
watcher: Default::default(),
|
|
||||||
resource: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents configuration items for the desktop platform.
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct DesktopConfig {
|
|
||||||
/// Describes whether a debug-mode desktop app should be always-on-top.
|
|
||||||
#[serde(default)]
|
|
||||||
pub always_on_top: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for DesktopConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
always_on_top: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The wasm-opt configuration
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
||||||
pub struct WasmOptConfig {
|
|
||||||
/// The wasm-opt level to use for release builds [default: s]
|
|
||||||
/// Options:
|
|
||||||
/// - z: optimize aggressively for size
|
|
||||||
/// - s: optimize for size
|
|
||||||
/// - 1: optimize for speed
|
|
||||||
/// - 2: optimize for more for speed
|
|
||||||
/// - 3: optimize for even more for speed
|
|
||||||
/// - 4: optimize aggressively for speed
|
|
||||||
#[serde(default)]
|
|
||||||
pub level: WasmOptLevel,
|
|
||||||
|
|
||||||
/// Keep debug symbols in the wasm file
|
|
||||||
#[serde(default = "false_bool")]
|
|
||||||
pub debug: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The wasm-opt level to use for release web builds [default: 4]
|
|
||||||
#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize)]
|
|
||||||
pub enum WasmOptLevel {
|
|
||||||
/// Optimize aggressively for size
|
|
||||||
#[serde(rename = "z")]
|
|
||||||
Z,
|
|
||||||
/// Optimize for size
|
|
||||||
#[serde(rename = "s")]
|
|
||||||
S,
|
|
||||||
/// Don't optimize
|
|
||||||
#[serde(rename = "0")]
|
|
||||||
Zero,
|
|
||||||
/// Optimize for speed
|
|
||||||
#[serde(rename = "1")]
|
|
||||||
One,
|
|
||||||
/// Optimize for more for speed
|
|
||||||
#[serde(rename = "2")]
|
|
||||||
Two,
|
|
||||||
/// Optimize for even more for speed
|
|
||||||
#[serde(rename = "3")]
|
|
||||||
Three,
|
|
||||||
/// Optimize aggressively for speed
|
|
||||||
#[serde(rename = "4")]
|
|
||||||
#[default]
|
|
||||||
Four,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct WebAppConfig {
|
|
||||||
#[serde(default = "default_title")]
|
|
||||||
pub title: String,
|
|
||||||
pub base_path: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WebAppConfig {
|
|
||||||
/// Get the normalized base path for the application with `/` trimmed from both ends. If the base path is not set, this will return `.`.
|
|
||||||
pub fn base_path(&self) -> &str {
|
|
||||||
match &self.base_path {
|
|
||||||
Some(path) => path.trim_matches('/'),
|
|
||||||
None => ".",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for WebAppConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
title: default_title(),
|
|
||||||
base_path: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_title() -> String {
|
|
||||||
"dioxus | ⛺".into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct WebProxyConfig {
|
|
||||||
pub backend: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct WebWatcherConfig {
|
|
||||||
#[serde(default = "watch_path_default")]
|
|
||||||
pub watch_path: Vec<PathBuf>,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
pub reload_html: bool,
|
|
||||||
|
|
||||||
#[serde(default = "true_bool")]
|
|
||||||
pub index_on_404: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for WebWatcherConfig {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
watch_path: watch_path_default(),
|
|
||||||
reload_html: false,
|
|
||||||
index_on_404: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn watch_path_default() -> Vec<PathBuf> {
|
|
||||||
vec![PathBuf::from("src"), PathBuf::from("examples")]
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct WebResourceConfig {
|
|
||||||
pub dev: WebDevResourceConfig,
|
|
||||||
pub style: Option<Vec<PathBuf>>,
|
|
||||||
pub script: Option<Vec<PathBuf>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct WebDevResourceConfig {
|
|
||||||
#[serde(default)]
|
|
||||||
pub style: Vec<PathBuf>,
|
|
||||||
#[serde(default)]
|
|
||||||
pub script: Vec<PathBuf>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
|
||||||
pub struct WebHttpsConfig {
|
|
||||||
pub enabled: Option<bool>,
|
|
||||||
pub mkcert: Option<bool>,
|
|
||||||
pub key_path: Option<String>,
|
|
||||||
pub cert_path: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn true_bool() -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn false_bool() -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
|
@ -1,99 +1,73 @@
|
||||||
#![doc = include_str!("../README.md")]
|
use std::{
|
||||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/79236386")]
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
#![doc(html_favicon_url = "https://avatars.githubusercontent.com/u/79236386")]
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
mod config;
|
pub const CLI_ENABLED_ENV: &str = "DIOXUS_CLI_ENABLED";
|
||||||
pub use config::*;
|
pub const SERVER_IP_ENV: &str = "IP";
|
||||||
|
pub const SERVER_PORT_ENV: &str = "PORT";
|
||||||
|
pub const DEVSERVER_RAW_ADDR_ENV: &str = "DIOXUS_DEVSERVER_ADDR";
|
||||||
|
pub const ALWAYS_ON_TOP_ENV: &str = "DIOXUS_ALWAYS_ON_TOP";
|
||||||
|
pub const ASSET_ROOT_ENV: &str = "DIOXUS_ASSET_ROOT";
|
||||||
|
pub const APP_TITLE_ENV: &str = "DIOXUS_APP_TITLE";
|
||||||
|
pub const OUT_DIR: &str = "DIOXUS_OUT_DIR";
|
||||||
|
|
||||||
mod bundle;
|
/// todo: this is not implemented but we're going to reserve this
|
||||||
pub use bundle::*;
|
///
|
||||||
|
/// technically this is only passed on "launch" so if you close the app, this will be lost
|
||||||
|
pub const IOS_DEVSERVER_ADDR_ENV: &str = "SIMCTL_CHILD_DIOXUS_DEVSERVER_ADDR";
|
||||||
|
|
||||||
mod serve;
|
/// Get the address of the devserver for use over a raw socket
|
||||||
pub use serve::*;
|
///
|
||||||
|
/// This is not a websocket! There's no protocol!
|
||||||
mod build_info;
|
pub fn devserver_raw_addr() -> Option<SocketAddr> {
|
||||||
|
std::env::var(DEVSERVER_RAW_ADDR_ENV)
|
||||||
#[doc(hidden)]
|
.map(|s| s.parse().ok())
|
||||||
pub mod __private {
|
.ok()
|
||||||
use crate::DioxusConfig;
|
.flatten()
|
||||||
|
|
||||||
pub(crate) const DIOXUS_CLI_VERSION: &str = "DIOXUS_CLI_VERSION";
|
|
||||||
pub(crate) const CONFIG_ENV: &str = "DIOXUS_CONFIG";
|
|
||||||
pub(crate) const CONFIG_BASE_PATH_ENV: &str = "DIOXUS_CONFIG_BASE_PATH";
|
|
||||||
|
|
||||||
pub fn save_config(config: &DioxusConfig, cli_version: &str) -> CrateConfigDropGuard {
|
|
||||||
std::env::set_var(CONFIG_ENV, serde_json::to_string(config).unwrap());
|
|
||||||
std::env::set_var(
|
|
||||||
CONFIG_BASE_PATH_ENV,
|
|
||||||
config.web.app.base_path.clone().unwrap_or_default(),
|
|
||||||
);
|
|
||||||
std::env::set_var(DIOXUS_CLI_VERSION, cli_version);
|
|
||||||
CrateConfigDropGuard
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A guard that removes the config from the environment when dropped.
|
pub fn devserver_ws_endpoint() -> Option<String> {
|
||||||
pub struct CrateConfigDropGuard;
|
let addr = devserver_raw_addr()?;
|
||||||
|
Some(format!("ws://{addr}/_dioxus"))
|
||||||
impl Drop for CrateConfigDropGuard {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
std::env::remove_var(CONFIG_ENV);
|
|
||||||
std::env::remove_var(CONFIG_BASE_PATH_ENV);
|
|
||||||
std::env::remove_var(DIOXUS_CLI_VERSION);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "read-config")]
|
pub fn server_ip() -> Option<IpAddr> {
|
||||||
/// The environment variable that stores the CLIs serve configuration.
|
std::env::var(SERVER_IP_ENV)
|
||||||
/// We use this to communicate between the CLI and the server for fullstack applications.
|
.ok()
|
||||||
pub const SERVE_ENV: &str = "DIOXUS_SERVE_CONFIG";
|
.and_then(|s| s.parse().ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An error that occurs when the dioxus CLI was not used to build the application.
|
pub fn server_port() -> Option<u16> {
|
||||||
#[derive(Debug)]
|
std::env::var(SERVER_PORT_ENV)
|
||||||
pub struct DioxusCLINotUsed;
|
.ok()
|
||||||
|
.and_then(|s| s.parse().ok())
|
||||||
impl std::fmt::Display for DioxusCLINotUsed {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.write_str("dioxus CLI was not used to build the application")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::error::Error for DioxusCLINotUsed {}
|
pub fn fullstack_address_or_localhost() -> SocketAddr {
|
||||||
|
let ip = server_ip().unwrap_or_else(|| IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
|
||||||
#[cfg(feature = "read-config")]
|
let port = server_port().unwrap_or(8080);
|
||||||
/// The current crate's configuration.
|
SocketAddr::new(ip, port)
|
||||||
pub static CURRENT_CONFIG: once_cell::sync::Lazy<
|
|
||||||
Result<crate::config::DioxusConfig, DioxusCLINotUsed>,
|
|
||||||
> = once_cell::sync::Lazy::new(|| {
|
|
||||||
CURRENT_CONFIG_JSON
|
|
||||||
.ok_or_else(|| {
|
|
||||||
tracing::warn!("A library is trying to access the crate's configuration, but the dioxus CLI was not used to build the application.");
|
|
||||||
DioxusCLINotUsed
|
|
||||||
}).and_then(
|
|
||||||
|config|
|
|
||||||
match serde_json::from_str(config) {
|
|
||||||
Ok(config) => Ok(config),
|
|
||||||
Err(err) => {
|
|
||||||
let mut cli_version = crate::build_info::PKG_VERSION.to_string();
|
|
||||||
|
|
||||||
if let Some(hash) = crate::build_info::GIT_COMMIT_HASH_SHORT {
|
|
||||||
let hash = &hash.trim_start_matches('g')[..4];
|
|
||||||
cli_version.push_str(&format!("-{hash}"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let dioxus_version = std::option_env!("DIOXUS_CLI_VERSION").unwrap_or("unknown");
|
pub fn app_title() -> Option<String> {
|
||||||
|
std::env::var(APP_TITLE_ENV).ok()
|
||||||
tracing::warn!("Failed to parse the CLI config file. This is likely caused by a mismatch between the version of the CLI and the dioxus version.\nCLI version: {cli_version}\nDioxus version: {dioxus_version}\nSerialization error: {err}");
|
|
||||||
Err(DioxusCLINotUsed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn always_on_top() -> Option<bool> {
|
||||||
|
std::env::var(ALWAYS_ON_TOP_ENV)
|
||||||
|
.ok()
|
||||||
|
.and_then(|s| s.parse().ok())
|
||||||
}
|
}
|
||||||
)
|
|
||||||
});
|
|
||||||
|
|
||||||
#[cfg(feature = "read-config")]
|
pub fn is_cli_enabled() -> bool {
|
||||||
/// The current crate's configuration.
|
std::env::var(CLI_ENABLED_ENV).is_ok()
|
||||||
pub const CURRENT_CONFIG_JSON: Option<&str> = std::option_env!("DIOXUS_CONFIG");
|
}
|
||||||
|
|
||||||
#[cfg(feature = "read-config")]
|
pub fn base_path() -> Option<PathBuf> {
|
||||||
/// The current crate's configuration.
|
std::env::var("DIOXUS_ASSET_ROOT").ok().map(PathBuf::from)
|
||||||
pub const BASE_PATH: Option<&str> = std::option_env!("DIOXUS_CONFIG_BASE_PATH");
|
}
|
||||||
|
|
||||||
|
pub fn out_dir() -> Option<PathBuf> {
|
||||||
|
std::env::var(OUT_DIR).ok().map(PathBuf::from)
|
||||||
|
}
|
||||||
|
|
|
@ -1,98 +0,0 @@
|
||||||
#![allow(unused)] // lots of configs...
|
|
||||||
|
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};
|
|
||||||
|
|
||||||
#[cfg(feature = "read-from-args")]
|
|
||||||
use clap::Parser;
|
|
||||||
|
|
||||||
/// The arguments for the address the server will run on
|
|
||||||
|
|
||||||
#[cfg(feature = "read-from-args")]
|
|
||||||
#[derive(Clone, Debug, Parser)]
|
|
||||||
pub struct AddressArguments {
|
|
||||||
/// The port the server will run on
|
|
||||||
#[clap(long)]
|
|
||||||
#[clap(default_value_t = default_port())]
|
|
||||||
pub port: u16,
|
|
||||||
|
|
||||||
/// The address the server will run on
|
|
||||||
#[clap(long, default_value_t = default_address())]
|
|
||||||
pub addr: std::net::IpAddr,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "read-from-args")]
|
|
||||||
impl Default for AddressArguments {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
port: default_port(),
|
|
||||||
addr: default_address(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "read-from-args")]
|
|
||||||
impl AddressArguments {
|
|
||||||
/// Get the address the server should run on
|
|
||||||
pub fn address(&self) -> SocketAddr {
|
|
||||||
SocketAddr::new(self.addr, self.port)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
|
||||||
pub struct RuntimeCLIArguments {
|
|
||||||
/// The address hot reloading is running on
|
|
||||||
cli_address: SocketAddr,
|
|
||||||
|
|
||||||
/// The address the server should run on
|
|
||||||
server_socket: Option<SocketAddr>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RuntimeCLIArguments {
|
|
||||||
/// Create a new RuntimeCLIArguments
|
|
||||||
pub fn new(cli_address: SocketAddr, server_socket: Option<SocketAddr>) -> Self {
|
|
||||||
Self {
|
|
||||||
cli_address,
|
|
||||||
server_socket,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Attempt to read the current serve settings from the CLI. This will only be set for the fullstack platform on recent versions of the CLI.
|
|
||||||
pub fn from_cli() -> Option<Self> {
|
|
||||||
std::env::var(crate::__private::SERVE_ENV)
|
|
||||||
.ok()
|
|
||||||
.and_then(|json| serde_json::from_str(&json).ok())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the address the server should run on
|
|
||||||
pub fn server_socket(&self) -> Option<SocketAddr> {
|
|
||||||
self.server_socket
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the address the CLI is running on
|
|
||||||
pub fn cli_address(&self) -> SocketAddr {
|
|
||||||
self.cli_address
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the address the proxied fullstack server should run on
|
|
||||||
#[cfg(feature = "read-from-args")]
|
|
||||||
pub fn fullstack_address(&self) -> AddressArguments {
|
|
||||||
let socket = self.server_socket.unwrap_or_else(|| {
|
|
||||||
SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, default_port()))
|
|
||||||
});
|
|
||||||
|
|
||||||
AddressArguments {
|
|
||||||
port: socket.port(),
|
|
||||||
addr: socket.ip(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "read-from-args")]
|
|
||||||
fn default_port() -> u16 {
|
|
||||||
8080
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "read-from-args")]
|
|
||||||
fn default_address() -> IpAddr {
|
|
||||||
IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1))
|
|
||||||
}
|
|
|
@ -16,7 +16,7 @@ thiserror = { workspace = true }
|
||||||
wasm-bindgen-cli-support = "0.2"
|
wasm-bindgen-cli-support = "0.2"
|
||||||
wasm-bindgen-shared = "0.2"
|
wasm-bindgen-shared = "0.2"
|
||||||
colored = "2.0.0"
|
colored = "2.0.0"
|
||||||
dioxus-cli-config = { workspace = true, features = ["cli"], default-features = false }
|
dioxus-cli-config = { workspace = true }
|
||||||
|
|
||||||
# features
|
# features
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
|
@ -78,6 +78,7 @@ toml_edit = "0.22.20"
|
||||||
|
|
||||||
# bundling
|
# bundling
|
||||||
tauri-bundler = { workspace = true }
|
tauri-bundler = { workspace = true }
|
||||||
|
tauri-utils = { workspace = true }
|
||||||
|
|
||||||
# formatting
|
# formatting
|
||||||
# syn = { workspace = true }
|
# syn = { workspace = true }
|
||||||
|
@ -95,7 +96,7 @@ dioxus-rsx-hotreload = { workspace = true }
|
||||||
dioxus-html = { workspace = true, features = ["hot-reload-context"] }
|
dioxus-html = { workspace = true, features = ["hot-reload-context"] }
|
||||||
dioxus-core = { workspace = true, features = ["serialize"] }
|
dioxus-core = { workspace = true, features = ["serialize"] }
|
||||||
dioxus-core-types = { workspace = true }
|
dioxus-core-types = { workspace = true }
|
||||||
dioxus-hot-reload = { workspace = true, features = ["serve"] }
|
dioxus-devtools = { workspace = true }
|
||||||
ignore = "0.4.22"
|
ignore = "0.4.22"
|
||||||
env_logger = "0.11.3"
|
env_logger = "0.11.3"
|
||||||
|
|
||||||
|
@ -119,9 +120,7 @@ built = { version = "=0.7.4", features = ["git2"] }
|
||||||
default = []
|
default = []
|
||||||
plugin = []
|
plugin = []
|
||||||
tokio-console = ["dep:console-subscriber"]
|
tokio-console = ["dep:console-subscriber"]
|
||||||
|
# optimizations = ["dep:wasm-opt"]
|
||||||
# when releasing dioxus, we want to enable wasm-opt
|
|
||||||
wasm-opt = ["dep:wasm-opt"]
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
|
@ -10,11 +10,11 @@ use crate::builder::progress::CargoBuildResult;
|
||||||
use crate::builder::progress::Stage;
|
use crate::builder::progress::Stage;
|
||||||
use crate::builder::progress::UpdateBuildProgress;
|
use crate::builder::progress::UpdateBuildProgress;
|
||||||
use crate::builder::progress::UpdateStage;
|
use crate::builder::progress::UpdateStage;
|
||||||
|
use crate::config::Platform;
|
||||||
use crate::link::LinkCommand;
|
use crate::link::LinkCommand;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use crate::TraceSrc;
|
use crate::TraceSrc;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use dioxus_cli_config::Platform;
|
|
||||||
use futures_channel::mpsc::UnboundedSender;
|
use futures_channel::mpsc::UnboundedSender;
|
||||||
use manganis_cli_support::AssetManifest;
|
use manganis_cli_support::AssetManifest;
|
||||||
use manganis_cli_support::ManganisSupportGuard;
|
use manganis_cli_support::ManganisSupportGuard;
|
||||||
|
@ -115,10 +115,6 @@ impl BuildRequest {
|
||||||
let hash = &hash.trim_start_matches('g')[..4];
|
let hash = &hash.trim_start_matches('g')[..4];
|
||||||
dioxus_version.push_str(&format!("-{hash}"));
|
dioxus_version.push_str(&format!("-{hash}"));
|
||||||
}
|
}
|
||||||
let _guard = dioxus_cli_config::__private::save_config(
|
|
||||||
&self.dioxus_crate.dioxus_config,
|
|
||||||
&dioxus_version,
|
|
||||||
);
|
|
||||||
let _manganis_support = ManganisSupportGuard::default();
|
let _manganis_support = ManganisSupportGuard::default();
|
||||||
let _asset_guard =
|
let _asset_guard =
|
||||||
AssetConfigDropGuard::new(self.dioxus_crate.dioxus_config.web.app.base_path.as_deref());
|
AssetConfigDropGuard::new(self.dioxus_crate.dioxus_config.web.app.base_path.as_deref());
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::cli::serve::ServeArguments;
|
use crate::cli::serve::ServeArguments;
|
||||||
|
use crate::config::Platform;
|
||||||
use crate::dioxus_crate::DioxusCrate;
|
use crate::dioxus_crate::DioxusCrate;
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use crate::{build::Build, TraceSrc};
|
use crate::{build::Build, TraceSrc};
|
||||||
use dioxus_cli_config::{Platform, RuntimeCLIArguments};
|
|
||||||
use futures_util::stream::select_all;
|
use futures_util::stream::select_all;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
@ -96,7 +96,6 @@ impl BuildRequest {
|
||||||
Platform::StaticGeneration | Platform::Fullstack => {
|
Platform::StaticGeneration | Platform::Fullstack => {
|
||||||
Self::new_fullstack(dioxus_crate.clone(), build_arguments, serve)?
|
Self::new_fullstack(dioxus_crate.clone(), build_arguments, serve)?
|
||||||
}
|
}
|
||||||
_ => unimplemented!("Unknown platform: {platform:?}"),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +158,16 @@ pub(crate) struct BuildResult {
|
||||||
|
|
||||||
impl BuildResult {
|
impl BuildResult {
|
||||||
/// Open the executable if this is a native build
|
/// Open the executable if this is a native build
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn open(
|
pub fn open(
|
||||||
&self,
|
&self,
|
||||||
serve: &ServeArguments,
|
serve: &ServeArguments,
|
||||||
fullstack_address: Option<SocketAddr>,
|
fullstack_address: Option<SocketAddr>,
|
||||||
workspace: &std::path::Path,
|
workspace: &std::path::Path,
|
||||||
|
asset_root: &std::path::Path,
|
||||||
|
devserver_addr: SocketAddr,
|
||||||
|
app_title: String,
|
||||||
|
out_dir: PathBuf,
|
||||||
) -> std::io::Result<Option<Child>> {
|
) -> std::io::Result<Option<Child>> {
|
||||||
match self.target_platform {
|
match self.target_platform {
|
||||||
TargetPlatform::Web => {
|
TargetPlatform::Web => {
|
||||||
|
@ -174,13 +178,7 @@ impl BuildResult {
|
||||||
tracing::info!(dx_src = ?TraceSrc::Dev, "Launching desktop app at {} 🎉", self.executable.display());
|
tracing::info!(dx_src = ?TraceSrc::Dev, "Launching desktop app at {} 🎉", self.executable.display());
|
||||||
}
|
}
|
||||||
TargetPlatform::Server => {
|
TargetPlatform::Server => {
|
||||||
if let Some(fullstack_address) = fullstack_address {
|
// shut this up for now - the web app will take priority in logging
|
||||||
tracing::info!(
|
|
||||||
dx_src = ?TraceSrc::Dev,
|
|
||||||
"Launching fullstack server on http://{:?} 🎉",
|
|
||||||
fullstack_address
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
TargetPlatform::Liveview => {
|
TargetPlatform::Liveview => {
|
||||||
if let Some(fullstack_address) = fullstack_address {
|
if let Some(fullstack_address) = fullstack_address {
|
||||||
|
@ -195,19 +193,36 @@ impl BuildResult {
|
||||||
|
|
||||||
tracing::info!(dx_src = ?TraceSrc::Dev, "Press [o] to open the app manually.");
|
tracing::info!(dx_src = ?TraceSrc::Dev, "Press [o] to open the app manually.");
|
||||||
|
|
||||||
let arguments = RuntimeCLIArguments::new(serve.address.address(), fullstack_address);
|
|
||||||
let executable = self.executable.canonicalize()?;
|
let executable = self.executable.canonicalize()?;
|
||||||
let mut cmd = Command::new(executable);
|
let mut cmd = Command::new(executable);
|
||||||
cmd
|
|
||||||
// When building the fullstack server, we need to forward the serve arguments (like port) to the fullstack server through env vars
|
// Set the env vars that the clients will expect
|
||||||
.env(
|
// These need to be stable within a release version (ie 0.6.0)
|
||||||
dioxus_cli_config::__private::SERVE_ENV,
|
cmd.env(dioxus_cli_config::CLI_ENABLED_ENV, "true");
|
||||||
serde_json::to_string(&arguments).unwrap(),
|
if let Some(addr) = fullstack_address {
|
||||||
)
|
cmd.env(dioxus_cli_config::SERVER_IP_ENV, addr.ip().to_string());
|
||||||
.stderr(Stdio::piped())
|
cmd.env(dioxus_cli_config::SERVER_PORT_ENV, addr.port().to_string());
|
||||||
|
}
|
||||||
|
cmd.env(
|
||||||
|
dioxus_cli_config::ALWAYS_ON_TOP_ENV,
|
||||||
|
serve.always_on_top.unwrap_or(true).to_string(),
|
||||||
|
);
|
||||||
|
cmd.env(
|
||||||
|
dioxus_cli_config::ASSET_ROOT_ENV,
|
||||||
|
asset_root.display().to_string(),
|
||||||
|
);
|
||||||
|
cmd.env(
|
||||||
|
dioxus_cli_config::DEVSERVER_RAW_ADDR_ENV,
|
||||||
|
devserver_addr.to_string(),
|
||||||
|
);
|
||||||
|
cmd.env(dioxus_cli_config::APP_TITLE_ENV, app_title);
|
||||||
|
cmd.env(dioxus_cli_config::OUT_DIR, out_dir.display().to_string());
|
||||||
|
|
||||||
|
cmd.stderr(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.kill_on_drop(true)
|
.kill_on_drop(true)
|
||||||
.current_dir(workspace);
|
.current_dir(workspace);
|
||||||
|
|
||||||
Ok(Some(cmd.spawn()?))
|
Ok(Some(cmd.spawn()?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,11 +132,11 @@ impl BuildRequest {
|
||||||
|
|
||||||
// Only run wasm-opt if the feature is enabled
|
// Only run wasm-opt if the feature is enabled
|
||||||
// Wasm-opt has an expensive build script that makes it annoying to keep enabled for iterative dev
|
// Wasm-opt has an expensive build script that makes it annoying to keep enabled for iterative dev
|
||||||
#[cfg(feature = "wasm-opt")]
|
#[cfg(feature = "optimizations")]
|
||||||
{
|
{
|
||||||
// Run wasm-opt if this is a release build
|
// Run wasm-opt if this is a release build
|
||||||
if self.build_arguments.release {
|
if self.build_arguments.release {
|
||||||
use dioxus_cli_config::WasmOptLevel;
|
use crate::config::WasmOptLevel;
|
||||||
|
|
||||||
tracing::info!(dx_src = ?TraceSrc::Build, "Running optimization with wasm-opt...");
|
tracing::info!(dx_src = ?TraceSrc::Build, "Running optimization with wasm-opt...");
|
||||||
let mut options = match self.dioxus_crate.dioxus_config.web.wasm_opt.level {
|
let mut options = match self.dioxus_crate.dioxus_config.web.wasm_opt.level {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use crate::config::Platform;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use dioxus_cli_config::Platform;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::{BuildRequest, TargetPlatform},
|
builder::{BuildRequest, TargetPlatform},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
use crate::config::AddressArguments;
|
||||||
use crate::{settings, tracer::CLILogControl, DioxusCrate};
|
use crate::{settings, tracer::CLILogControl, DioxusCrate};
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use build::Build;
|
use build::Build;
|
||||||
use dioxus_cli_config::AddressArguments;
|
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
668
packages/cli/src/config.rs
Normal file
668
packages/cli/src/config.rs
Normal file
|
@ -0,0 +1,668 @@
|
||||||
|
use clap::Parser;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::net::{IpAddr, SocketAddr};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
#[derive(
|
||||||
|
Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Debug, Default,
|
||||||
|
)]
|
||||||
|
#[derive(clap::ValueEnum)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum Platform {
|
||||||
|
/// Targeting the web platform using WASM
|
||||||
|
#[clap(name = "web")]
|
||||||
|
#[serde(rename = "web")]
|
||||||
|
#[default]
|
||||||
|
Web,
|
||||||
|
|
||||||
|
/// Targeting the desktop platform using Tao/Wry-based webview
|
||||||
|
#[clap(name = "desktop")]
|
||||||
|
#[serde(rename = "desktop")]
|
||||||
|
Desktop,
|
||||||
|
|
||||||
|
/// Targeting the server platform using Axum and Dioxus-Fullstack
|
||||||
|
#[clap(name = "fullstack")]
|
||||||
|
#[serde(rename = "fullstack")]
|
||||||
|
Fullstack,
|
||||||
|
|
||||||
|
/// Targeting the static generation platform using SSR and Dioxus-Fullstack
|
||||||
|
#[ clap(name = "static-generation")]
|
||||||
|
#[serde(rename = "static-generation")]
|
||||||
|
StaticGeneration,
|
||||||
|
|
||||||
|
/// Targeting the static generation platform using SSR and Dioxus-Fullstack
|
||||||
|
#[clap(name = "liveview")]
|
||||||
|
#[serde(rename = "liveview")]
|
||||||
|
Liveview,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An error that occurs when a platform is not recognized
|
||||||
|
pub struct UnknownPlatformError;
|
||||||
|
|
||||||
|
impl std::error::Error for UnknownPlatformError {}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for UnknownPlatformError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Unknown platform")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for UnknownPlatformError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "Unknown platform")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Platform {
|
||||||
|
type Err = UnknownPlatformError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"web" => Ok(Self::Web),
|
||||||
|
"desktop" => Ok(Self::Desktop),
|
||||||
|
"fullstack" => Ok(Self::Fullstack),
|
||||||
|
"static-generation" => Ok(Self::StaticGeneration),
|
||||||
|
"liveview" => Ok(Self::Liveview),
|
||||||
|
_ => Err(UnknownPlatformError),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Platform {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let feature = self.feature_name();
|
||||||
|
f.write_str(feature)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Platform {
|
||||||
|
/// All platforms the dioxus CLI supports
|
||||||
|
pub const ALL: &'static [Self] = &[
|
||||||
|
Platform::Web,
|
||||||
|
Platform::Desktop,
|
||||||
|
Platform::Fullstack,
|
||||||
|
Platform::StaticGeneration,
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Get the feature name for the platform in the dioxus crate
|
||||||
|
pub fn feature_name(&self) -> &str {
|
||||||
|
match self {
|
||||||
|
Platform::Web => "web",
|
||||||
|
Platform::Desktop => "desktop",
|
||||||
|
Platform::Fullstack => "fullstack",
|
||||||
|
Platform::StaticGeneration => "static-generation",
|
||||||
|
Platform::Liveview => "liveview",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct DioxusConfig {
|
||||||
|
pub application: ApplicationConfig,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub web: WebConfig,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub desktop: DesktopConfig,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub bundle: BundleConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DioxusConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
let name = default_name();
|
||||||
|
Self {
|
||||||
|
application: ApplicationConfig {
|
||||||
|
name: name.clone(),
|
||||||
|
default_platform: default_platform(),
|
||||||
|
out_dir: out_dir_default(),
|
||||||
|
asset_dir: asset_dir_default(),
|
||||||
|
|
||||||
|
sub_package: None,
|
||||||
|
},
|
||||||
|
web: WebConfig {
|
||||||
|
app: WebAppConfig {
|
||||||
|
title: default_title(),
|
||||||
|
base_path: None,
|
||||||
|
},
|
||||||
|
proxy: vec![],
|
||||||
|
watcher: Default::default(),
|
||||||
|
resource: WebResourceConfig {
|
||||||
|
dev: WebDevResourceConfig {
|
||||||
|
style: vec![],
|
||||||
|
script: vec![],
|
||||||
|
},
|
||||||
|
style: Some(vec![]),
|
||||||
|
script: Some(vec![]),
|
||||||
|
},
|
||||||
|
https: WebHttpsConfig {
|
||||||
|
enabled: None,
|
||||||
|
mkcert: None,
|
||||||
|
key_path: None,
|
||||||
|
cert_path: None,
|
||||||
|
},
|
||||||
|
pre_compress: true,
|
||||||
|
wasm_opt: Default::default(),
|
||||||
|
},
|
||||||
|
desktop: DesktopConfig::default(),
|
||||||
|
bundle: BundleConfig {
|
||||||
|
identifier: Some(format!("io.github.{name}")),
|
||||||
|
publisher: Some(name),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
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,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub sub_package: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_name() -> String {
|
||||||
|
"my-cool-project".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_platform() -> Platform {
|
||||||
|
Platform::Web
|
||||||
|
}
|
||||||
|
|
||||||
|
fn asset_dir_default() -> PathBuf {
|
||||||
|
PathBuf::from("public")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn out_dir_default() -> PathBuf {
|
||||||
|
PathBuf::from("dist")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct WebConfig {
|
||||||
|
#[serde(default)]
|
||||||
|
pub app: WebAppConfig,
|
||||||
|
#[serde(default)]
|
||||||
|
pub proxy: Vec<WebProxyConfig>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub watcher: WebWatcherConfig,
|
||||||
|
#[serde(default)]
|
||||||
|
pub resource: WebResourceConfig,
|
||||||
|
#[serde(default)]
|
||||||
|
pub https: WebHttpsConfig,
|
||||||
|
/// Whether to enable pre-compression of assets and wasm during a web build in release mode
|
||||||
|
#[serde(default = "true_bool")]
|
||||||
|
pub pre_compress: bool,
|
||||||
|
/// The wasm-opt configuration
|
||||||
|
#[serde(default)]
|
||||||
|
pub wasm_opt: WasmOptConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for WebConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
pre_compress: true_bool(),
|
||||||
|
app: Default::default(),
|
||||||
|
https: Default::default(),
|
||||||
|
wasm_opt: Default::default(),
|
||||||
|
proxy: Default::default(),
|
||||||
|
watcher: Default::default(),
|
||||||
|
resource: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Represents configuration items for the desktop platform.
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct DesktopConfig {
|
||||||
|
/// Describes whether a debug-mode desktop app should be always-on-top.
|
||||||
|
#[serde(default)]
|
||||||
|
pub always_on_top: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for DesktopConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
always_on_top: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The wasm-opt configuration
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct WasmOptConfig {
|
||||||
|
/// The wasm-opt level to use for release builds [default: s]
|
||||||
|
/// Options:
|
||||||
|
/// - z: optimize aggressively for size
|
||||||
|
/// - s: optimize for size
|
||||||
|
/// - 1: optimize for speed
|
||||||
|
/// - 2: optimize for more for speed
|
||||||
|
/// - 3: optimize for even more for speed
|
||||||
|
/// - 4: optimize aggressively for speed
|
||||||
|
#[serde(default)]
|
||||||
|
pub level: WasmOptLevel,
|
||||||
|
|
||||||
|
/// Keep debug symbols in the wasm file
|
||||||
|
#[serde(default = "false_bool")]
|
||||||
|
pub debug: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The wasm-opt level to use for release web builds [default: 4]
|
||||||
|
#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum WasmOptLevel {
|
||||||
|
/// Optimize aggressively for size
|
||||||
|
#[serde(rename = "z")]
|
||||||
|
Z,
|
||||||
|
/// Optimize for size
|
||||||
|
#[serde(rename = "s")]
|
||||||
|
S,
|
||||||
|
/// Don't optimize
|
||||||
|
#[serde(rename = "0")]
|
||||||
|
Zero,
|
||||||
|
/// Optimize for speed
|
||||||
|
#[serde(rename = "1")]
|
||||||
|
One,
|
||||||
|
/// Optimize for more for speed
|
||||||
|
#[serde(rename = "2")]
|
||||||
|
Two,
|
||||||
|
/// Optimize for even more for speed
|
||||||
|
#[serde(rename = "3")]
|
||||||
|
Three,
|
||||||
|
/// Optimize aggressively for speed
|
||||||
|
#[serde(rename = "4")]
|
||||||
|
#[default]
|
||||||
|
Four,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct WebAppConfig {
|
||||||
|
#[serde(default = "default_title")]
|
||||||
|
pub title: String,
|
||||||
|
pub base_path: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WebAppConfig {
|
||||||
|
/// Get the normalized base path for the application with `/` trimmed from both ends. If the base path is not set, this will return `.`.
|
||||||
|
pub fn base_path(&self) -> &str {
|
||||||
|
match &self.base_path {
|
||||||
|
Some(path) => path.trim_matches('/'),
|
||||||
|
None => ".",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for WebAppConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
title: default_title(),
|
||||||
|
base_path: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_title() -> String {
|
||||||
|
"dioxus | ⛺".into()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct WebProxyConfig {
|
||||||
|
pub backend: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct WebWatcherConfig {
|
||||||
|
#[serde(default = "watch_path_default")]
|
||||||
|
pub watch_path: Vec<PathBuf>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub reload_html: bool,
|
||||||
|
|
||||||
|
#[serde(default = "true_bool")]
|
||||||
|
pub index_on_404: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for WebWatcherConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
watch_path: watch_path_default(),
|
||||||
|
reload_html: false,
|
||||||
|
index_on_404: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn watch_path_default() -> Vec<PathBuf> {
|
||||||
|
vec![PathBuf::from("src"), PathBuf::from("examples")]
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct WebResourceConfig {
|
||||||
|
pub dev: WebDevResourceConfig,
|
||||||
|
pub style: Option<Vec<PathBuf>>,
|
||||||
|
pub script: Option<Vec<PathBuf>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct WebDevResourceConfig {
|
||||||
|
#[serde(default)]
|
||||||
|
pub style: Vec<PathBuf>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub script: Vec<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct WebHttpsConfig {
|
||||||
|
pub enabled: Option<bool>,
|
||||||
|
pub mkcert: Option<bool>,
|
||||||
|
pub key_path: Option<String>,
|
||||||
|
pub cert_path: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn true_bool() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn false_bool() -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct BundleConfig {
|
||||||
|
pub identifier: Option<String>,
|
||||||
|
pub publisher: Option<String>,
|
||||||
|
pub icon: Option<Vec<String>>,
|
||||||
|
pub resources: Option<Vec<String>>,
|
||||||
|
pub copyright: Option<String>,
|
||||||
|
pub category: Option<String>,
|
||||||
|
pub short_description: Option<String>,
|
||||||
|
pub long_description: Option<String>,
|
||||||
|
pub external_bin: Option<Vec<String>>,
|
||||||
|
pub deb: Option<DebianSettings>,
|
||||||
|
pub macos: Option<MacOsSettings>,
|
||||||
|
pub windows: Option<WindowsSettings>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BundleConfig> for tauri_bundler::BundleSettings {
|
||||||
|
fn from(val: BundleConfig) -> Self {
|
||||||
|
tauri_bundler::BundleSettings {
|
||||||
|
identifier: val.identifier,
|
||||||
|
publisher: val.publisher,
|
||||||
|
icon: val.icon,
|
||||||
|
resources: val.resources,
|
||||||
|
copyright: val.copyright,
|
||||||
|
category: val.category.and_then(|c| c.parse().ok()),
|
||||||
|
short_description: val.short_description,
|
||||||
|
long_description: val.long_description,
|
||||||
|
external_bin: val.external_bin,
|
||||||
|
deb: val.deb.map(Into::into).unwrap_or_default(),
|
||||||
|
macos: val.macos.map(Into::into).unwrap_or_default(),
|
||||||
|
windows: val.windows.map(Into::into).unwrap_or_default(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct DebianSettings {
|
||||||
|
pub depends: Option<Vec<String>>,
|
||||||
|
pub files: HashMap<PathBuf, PathBuf>,
|
||||||
|
pub nsis: Option<NsisSettings>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DebianSettings> for tauri_bundler::DebianSettings {
|
||||||
|
fn from(val: DebianSettings) -> Self {
|
||||||
|
tauri_bundler::DebianSettings {
|
||||||
|
depends: val.depends,
|
||||||
|
files: val.files,
|
||||||
|
desktop_template: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct WixSettings {
|
||||||
|
pub language: Vec<(String, Option<PathBuf>)>,
|
||||||
|
pub template: Option<PathBuf>,
|
||||||
|
pub fragment_paths: Vec<PathBuf>,
|
||||||
|
pub component_group_refs: Vec<String>,
|
||||||
|
pub component_refs: Vec<String>,
|
||||||
|
pub feature_group_refs: Vec<String>,
|
||||||
|
pub feature_refs: Vec<String>,
|
||||||
|
pub merge_refs: Vec<String>,
|
||||||
|
pub skip_webview_install: bool,
|
||||||
|
pub license: Option<PathBuf>,
|
||||||
|
pub enable_elevated_update_task: bool,
|
||||||
|
pub banner_path: Option<PathBuf>,
|
||||||
|
pub dialog_image_path: Option<PathBuf>,
|
||||||
|
pub fips_compliant: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<WixSettings> for tauri_bundler::WixSettings {
|
||||||
|
fn from(val: WixSettings) -> Self {
|
||||||
|
tauri_bundler::WixSettings {
|
||||||
|
language: tauri_bundler::bundle::WixLanguage({
|
||||||
|
let mut languages: Vec<_> = val
|
||||||
|
.language
|
||||||
|
.iter()
|
||||||
|
.map(|l| {
|
||||||
|
(
|
||||||
|
l.0.clone(),
|
||||||
|
tauri_bundler::bundle::WixLanguageConfig {
|
||||||
|
locale_path: l.1.clone(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
if languages.is_empty() {
|
||||||
|
languages.push(("en-US".into(), Default::default()));
|
||||||
|
}
|
||||||
|
languages
|
||||||
|
}),
|
||||||
|
template: val.template,
|
||||||
|
fragment_paths: val.fragment_paths,
|
||||||
|
component_group_refs: val.component_group_refs,
|
||||||
|
component_refs: val.component_refs,
|
||||||
|
feature_group_refs: val.feature_group_refs,
|
||||||
|
feature_refs: val.feature_refs,
|
||||||
|
merge_refs: val.merge_refs,
|
||||||
|
skip_webview_install: val.skip_webview_install,
|
||||||
|
license: val.license,
|
||||||
|
enable_elevated_update_task: val.enable_elevated_update_task,
|
||||||
|
banner_path: val.banner_path,
|
||||||
|
dialog_image_path: val.dialog_image_path,
|
||||||
|
fips_compliant: val.fips_compliant,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
||||||
|
pub struct MacOsSettings {
|
||||||
|
pub frameworks: Option<Vec<String>>,
|
||||||
|
pub minimum_system_version: Option<String>,
|
||||||
|
pub license: Option<String>,
|
||||||
|
pub exception_domain: Option<String>,
|
||||||
|
pub signing_identity: Option<String>,
|
||||||
|
pub provider_short_name: Option<String>,
|
||||||
|
pub entitlements: Option<String>,
|
||||||
|
pub info_plist_path: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<MacOsSettings> for tauri_bundler::MacOsSettings {
|
||||||
|
fn from(val: MacOsSettings) -> Self {
|
||||||
|
tauri_bundler::MacOsSettings {
|
||||||
|
frameworks: val.frameworks,
|
||||||
|
minimum_system_version: val.minimum_system_version,
|
||||||
|
license: val.license,
|
||||||
|
exception_domain: val.exception_domain,
|
||||||
|
signing_identity: val.signing_identity,
|
||||||
|
provider_short_name: val.provider_short_name,
|
||||||
|
entitlements: val.entitlements,
|
||||||
|
info_plist_path: val.info_plist_path,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct WindowsSettings {
|
||||||
|
pub digest_algorithm: Option<String>,
|
||||||
|
pub certificate_thumbprint: Option<String>,
|
||||||
|
pub timestamp_url: Option<String>,
|
||||||
|
pub tsp: bool,
|
||||||
|
pub wix: Option<WixSettings>,
|
||||||
|
pub icon_path: Option<PathBuf>,
|
||||||
|
pub webview_install_mode: WebviewInstallMode,
|
||||||
|
pub webview_fixed_runtime_path: Option<PathBuf>,
|
||||||
|
pub allow_downgrades: bool,
|
||||||
|
pub nsis: Option<NsisSettings>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<WindowsSettings> for tauri_bundler::WindowsSettings {
|
||||||
|
fn from(val: WindowsSettings) -> Self {
|
||||||
|
tauri_bundler::WindowsSettings {
|
||||||
|
digest_algorithm: val.digest_algorithm,
|
||||||
|
certificate_thumbprint: val.certificate_thumbprint,
|
||||||
|
timestamp_url: val.timestamp_url,
|
||||||
|
tsp: val.tsp,
|
||||||
|
wix: val.wix.map(Into::into),
|
||||||
|
icon_path: val.icon_path.unwrap_or("icons/icon.ico".into()),
|
||||||
|
webview_install_mode: val.webview_install_mode.into(),
|
||||||
|
webview_fixed_runtime_path: val.webview_fixed_runtime_path,
|
||||||
|
allow_downgrades: val.allow_downgrades,
|
||||||
|
nsis: val.nsis.map(Into::into),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct NsisSettings {
|
||||||
|
pub template: Option<PathBuf>,
|
||||||
|
pub license: Option<PathBuf>,
|
||||||
|
pub header_image: Option<PathBuf>,
|
||||||
|
pub sidebar_image: Option<PathBuf>,
|
||||||
|
pub installer_icon: Option<PathBuf>,
|
||||||
|
pub install_mode: NSISInstallerMode,
|
||||||
|
pub languages: Option<Vec<String>>,
|
||||||
|
pub custom_language_files: Option<HashMap<String, PathBuf>>,
|
||||||
|
pub display_language_selector: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NsisSettings> for tauri_bundler::NsisSettings {
|
||||||
|
fn from(val: NsisSettings) -> Self {
|
||||||
|
tauri_bundler::NsisSettings {
|
||||||
|
license: val.license,
|
||||||
|
header_image: val.header_image,
|
||||||
|
sidebar_image: val.sidebar_image,
|
||||||
|
installer_icon: val.installer_icon,
|
||||||
|
install_mode: val.install_mode.into(),
|
||||||
|
languages: val.languages,
|
||||||
|
display_language_selector: val.display_language_selector,
|
||||||
|
custom_language_files: None,
|
||||||
|
template: None,
|
||||||
|
compression: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum NSISInstallerMode {
|
||||||
|
CurrentUser,
|
||||||
|
PerMachine,
|
||||||
|
Both,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<NSISInstallerMode> for tauri_utils::config::NSISInstallerMode {
|
||||||
|
fn from(val: NSISInstallerMode) -> Self {
|
||||||
|
match val {
|
||||||
|
NSISInstallerMode::CurrentUser => tauri_utils::config::NSISInstallerMode::CurrentUser,
|
||||||
|
NSISInstallerMode::PerMachine => tauri_utils::config::NSISInstallerMode::PerMachine,
|
||||||
|
NSISInstallerMode::Both => tauri_utils::config::NSISInstallerMode::Both,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum WebviewInstallMode {
|
||||||
|
Skip,
|
||||||
|
DownloadBootstrapper { silent: bool },
|
||||||
|
EmbedBootstrapper { silent: bool },
|
||||||
|
OfflineInstaller { silent: bool },
|
||||||
|
FixedRuntime { path: PathBuf },
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WebviewInstallMode {
|
||||||
|
fn into(self) -> tauri_utils::config::WebviewInstallMode {
|
||||||
|
match self {
|
||||||
|
Self::Skip => tauri_utils::config::WebviewInstallMode::Skip,
|
||||||
|
Self::DownloadBootstrapper { silent } => {
|
||||||
|
tauri_utils::config::WebviewInstallMode::DownloadBootstrapper { silent }
|
||||||
|
}
|
||||||
|
Self::EmbedBootstrapper { silent } => {
|
||||||
|
tauri_utils::config::WebviewInstallMode::EmbedBootstrapper { silent }
|
||||||
|
}
|
||||||
|
Self::OfflineInstaller { silent } => {
|
||||||
|
tauri_utils::config::WebviewInstallMode::OfflineInstaller { silent }
|
||||||
|
}
|
||||||
|
Self::FixedRuntime { path } => {
|
||||||
|
tauri_utils::config::WebviewInstallMode::FixedRuntime { path }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for WebviewInstallMode {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::OfflineInstaller { silent: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The arguments for the address the server will run on
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Parser)]
|
||||||
|
pub struct AddressArguments {
|
||||||
|
/// The port the server will run on
|
||||||
|
#[clap(long)]
|
||||||
|
#[clap(default_value_t = default_port())]
|
||||||
|
pub port: u16,
|
||||||
|
|
||||||
|
/// The address the server will run on
|
||||||
|
#[clap(long, default_value_t = default_address())]
|
||||||
|
pub addr: std::net::IpAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for AddressArguments {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
port: default_port(),
|
||||||
|
addr: default_address(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AddressArguments {
|
||||||
|
/// Get the address the server should run on
|
||||||
|
pub fn address(&self) -> SocketAddr {
|
||||||
|
SocketAddr::new(self.addr, self.port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_port() -> u16 {
|
||||||
|
8080
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_address() -> IpAddr {
|
||||||
|
IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1))
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::build::TargetArgs;
|
use crate::build::TargetArgs;
|
||||||
use dioxus_cli_config::{DioxusConfig, Platform};
|
use crate::config::{DioxusConfig, Platform};
|
||||||
use krates::cm::Target;
|
use krates::{cm::Target, KrateDetails};
|
||||||
use krates::{cm::TargetKind, Cmd, Krates, NodeId};
|
use krates::{cm::TargetKind, Cmd, Krates, NodeId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -84,16 +84,26 @@ fn find_main_package(package: Option<String>, krates: &Krates) -> Result<NodeId,
|
||||||
let kid = match package {
|
let kid = match package {
|
||||||
Some(package) => {
|
Some(package) => {
|
||||||
let mut workspace_members = krates.workspace_members();
|
let mut workspace_members = krates.workspace_members();
|
||||||
workspace_members
|
let found = workspace_members.find_map(|node| {
|
||||||
.find_map(|node| {
|
|
||||||
if let krates::Node::Krate { id, krate, .. } = node {
|
if let krates::Node::Krate { id, krate, .. } = node {
|
||||||
if krate.name == package {
|
if krate.name == package {
|
||||||
return Some(id);
|
return Some(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
})
|
});
|
||||||
.ok_or_else(|| CrateConfigError::PackageNotFound(package.clone()))?
|
|
||||||
|
if found.is_none() {
|
||||||
|
eprintln!("Could not find package {package} in the workspace. Did you forget to add it to the workspace?");
|
||||||
|
eprintln!("Packages in the workspace:");
|
||||||
|
for package in krates.workspace_members() {
|
||||||
|
if let krates::Node::Krate { krate, .. } = package {
|
||||||
|
eprintln!("{}", krate.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
found.ok_or_else(|| CrateConfigError::PackageNotFound(package.clone()))?
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// Otherwise find the package that is the closest parent of the current directory
|
// Otherwise find the package that is the closest parent of the current directory
|
||||||
|
@ -144,6 +154,7 @@ impl DioxusCrate {
|
||||||
cmd.features(target.features.clone());
|
cmd.features(target.features.clone());
|
||||||
let builder = krates::Builder::new();
|
let builder = krates::Builder::new();
|
||||||
let krates = builder.build(cmd, |_| {})?;
|
let krates = builder.build(cmd, |_| {})?;
|
||||||
|
|
||||||
let package = find_main_package(target.package.clone(), &krates)?;
|
let package = find_main_package(target.package.clone(), &krates)?;
|
||||||
|
|
||||||
let dioxus_config = load_dioxus_config(&krates, package)?.unwrap_or_default();
|
let dioxus_config = load_dioxus_config(&krates, package)?.unwrap_or_default();
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
pub mod assets;
|
pub mod assets;
|
||||||
pub mod builder;
|
pub mod builder;
|
||||||
pub mod cli;
|
pub mod cli;
|
||||||
|
pub mod config;
|
||||||
pub mod dioxus_crate;
|
pub mod dioxus_crate;
|
||||||
pub mod dx_build_info;
|
pub mod dx_build_info;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
|
@ -155,9 +155,24 @@ pub async fn serve_all(
|
||||||
builder.children.clear();
|
builder.children.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let asset_dir = dioxus_crate
|
||||||
|
.dioxus_config
|
||||||
|
.application
|
||||||
|
.asset_dir
|
||||||
|
.canonicalize()
|
||||||
|
.unwrap_or(std::path::PathBuf::from("./assets"));
|
||||||
|
|
||||||
// If we have a build result, open it
|
// If we have a build result, open it
|
||||||
for build_result in results.iter() {
|
for build_result in results.iter() {
|
||||||
let child = build_result.open(&serve.server_arguments, server.fullstack_address(), &dioxus_crate.workspace_dir());
|
let child = build_result.open(
|
||||||
|
&serve.server_arguments,
|
||||||
|
server.fullstack_address(),
|
||||||
|
&dioxus_crate.workspace_dir(),
|
||||||
|
&asset_dir,
|
||||||
|
server.ip,
|
||||||
|
dioxus_crate.dioxus_config.application.name.clone(),
|
||||||
|
dioxus_crate.out_dir()
|
||||||
|
);
|
||||||
match child {
|
match child {
|
||||||
Ok(Some(child_proc)) => builder.children.push((build_result.target_platform, child_proc)),
|
Ok(Some(child_proc)) => builder.children.push((build_result.target_platform, child_proc)),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::config::{AddressArguments, Platform};
|
||||||
use crate::{
|
use crate::{
|
||||||
builder::{BuildResult, UpdateStage},
|
builder::{BuildResult, UpdateStage},
|
||||||
builder::{Stage, TargetPlatform, UpdateBuildProgress},
|
builder::{Stage, TargetPlatform, UpdateBuildProgress},
|
||||||
|
@ -18,8 +19,7 @@ use crossterm::{
|
||||||
tty::IsTty,
|
tty::IsTty,
|
||||||
ExecutableCommand,
|
ExecutableCommand,
|
||||||
};
|
};
|
||||||
use dioxus_cli_config::{AddressArguments, Platform};
|
use dioxus_devtools::ClientMsg;
|
||||||
use dioxus_hot_reload::ClientMsg;
|
|
||||||
use futures_util::{future::select_all, Future, FutureExt, StreamExt};
|
use futures_util::{future::select_all, Future, FutureExt, StreamExt};
|
||||||
use ratatui::{prelude::*, TerminalOptions, Viewport};
|
use ratatui::{prelude::*, TerminalOptions, Viewport};
|
||||||
use std::{
|
use std::{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{BuildProgress, TraceMsg, TraceSrc};
|
use super::{BuildProgress, TraceMsg, TraceSrc};
|
||||||
|
use crate::config::Platform;
|
||||||
use ansi_to_tui::IntoText as _;
|
use ansi_to_tui::IntoText as _;
|
||||||
use dioxus_cli_config::Platform;
|
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
layout::{Alignment, Constraint, Direction, Layout, Rect},
|
||||||
style::{Color, Style, Stylize},
|
style::{Color, Style, Stylize},
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
use crate::config::WebProxyConfig;
|
||||||
use crate::TraceSrc;
|
use crate::TraceSrc;
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
use dioxus_cli_config::WebProxyConfig;
|
|
||||||
|
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use axum::body::Body as MyBody;
|
|
||||||
use axum::body::Body;
|
use axum::body::Body;
|
||||||
|
use axum::{body::Body as MyBody, response::IntoResponse};
|
||||||
use axum::{
|
use axum::{
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
routing::{any, MethodRouter},
|
routing::{any, MethodRouter},
|
||||||
|
@ -97,7 +97,7 @@ pub(crate) fn proxy_to(
|
||||||
nocache: bool,
|
nocache: bool,
|
||||||
handle_error: fn(Error) -> Response<Body>,
|
handle_error: fn(Error) -> Response<Body>,
|
||||||
) -> MethodRouter {
|
) -> MethodRouter {
|
||||||
let client = ProxyClient::new(url);
|
let client = ProxyClient::new(url.clone());
|
||||||
|
|
||||||
any(move |mut req: Request<MyBody>| async move {
|
any(move |mut req: Request<MyBody>| async move {
|
||||||
// Prevent request loops
|
// Prevent request loops
|
||||||
|
@ -115,11 +115,54 @@ pub(crate) fn proxy_to(
|
||||||
"true".parse().expect("header value is valid"),
|
"true".parse().expect("header value is valid"),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// We have to throw a redirect for ws connections since the upgrade handler will not be called
|
||||||
|
// Our _dioxus handler will override this in the default case
|
||||||
|
if req.uri().scheme().map(|f| f.as_str()) == Some("ws")
|
||||||
|
|| req.uri().scheme().map(|f| f.as_str()) == Some("wss")
|
||||||
|
{
|
||||||
|
let new_host = url.host().unwrap_or("localhost");
|
||||||
|
let proxied_uri = format!(
|
||||||
|
"{scheme}://{host}:{port}{path_and_query}",
|
||||||
|
scheme = req.uri().scheme_str().unwrap_or("ws"),
|
||||||
|
port = url.port().unwrap(),
|
||||||
|
host = new_host,
|
||||||
|
path_and_query = req
|
||||||
|
.uri()
|
||||||
|
.path_and_query()
|
||||||
|
.map(|f| f.to_string())
|
||||||
|
.unwrap_or_default()
|
||||||
|
);
|
||||||
|
tracing::info!(dx_src = ?TraceSrc::Dev, "Proxied websocket request {req:?} to {proxied_uri}");
|
||||||
|
|
||||||
|
return Ok(axum::response::Redirect::permanent(&proxied_uri).into_response());
|
||||||
|
}
|
||||||
|
|
||||||
if nocache {
|
if nocache {
|
||||||
crate::serve::insert_no_cache_headers(req.headers_mut());
|
crate::serve::insert_no_cache_headers(req.headers_mut());
|
||||||
}
|
}
|
||||||
|
|
||||||
client.send(req).await.map_err(handle_error)
|
let uri = req.uri().clone();
|
||||||
|
let res = client.send(req).await.map_err(handle_error);
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Ok(res) => {
|
||||||
|
// log assets at a different log level
|
||||||
|
if uri.path().starts_with("/assets")
|
||||||
|
|| uri.path().starts_with("/_dioxus")
|
||||||
|
|| uri.path().starts_with("/public")
|
||||||
|
{
|
||||||
|
tracing::trace!(dx_src = ?TraceSrc::Dev, "[{}] {}", res.status().as_u16(), uri);
|
||||||
|
} else {
|
||||||
|
tracing::info!(dx_src = ?TraceSrc::Dev, "[{}] {}", res.status().as_u16(), uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(res.into_response())
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
tracing::error!(dx_src = ?TraceSrc::Dev, "[{}] {}", err.status().as_u16(), uri);
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::config::{Platform, WebHttpsConfig};
|
||||||
use crate::serve::{next_or_pending, Serve};
|
use crate::serve::{next_or_pending, Serve};
|
||||||
use crate::{dioxus_crate::DioxusCrate, TraceSrc};
|
use crate::{dioxus_crate::DioxusCrate, TraceSrc};
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
|
@ -18,8 +19,7 @@ use axum::{
|
||||||
Extension, Router,
|
Extension, Router,
|
||||||
};
|
};
|
||||||
use axum_server::tls_rustls::RustlsConfig;
|
use axum_server::tls_rustls::RustlsConfig;
|
||||||
use dioxus_cli_config::{Platform, WebHttpsConfig};
|
use dioxus_devtools::{DevserverMsg, HotReloadMsg};
|
||||||
use dioxus_hot_reload::{DevserverMsg, HotReloadMsg};
|
|
||||||
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||||
use futures_util::stream;
|
use futures_util::stream;
|
||||||
use futures_util::{stream::FuturesUnordered, StreamExt};
|
use futures_util::{stream::FuturesUnordered, StreamExt};
|
||||||
|
@ -419,6 +419,7 @@ fn setup_router(
|
||||||
"/",
|
"/",
|
||||||
get(
|
get(
|
||||||
|ws: WebSocketUpgrade, ext: Extension<UnboundedSender<WebSocket>>| async move {
|
|ws: WebSocketUpgrade, ext: Extension<UnboundedSender<WebSocket>>| async move {
|
||||||
|
tracing::info!("Incoming hotreload websocket request: {ws:?}");
|
||||||
ws.on_upgrade(move |socket| async move { _ = ext.0.unbounded_send(socket) })
|
ws.on_upgrade(move |socket| async move { _ = ext.0.unbounded_send(socket) })
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -5,7 +5,7 @@ use super::hot_reloading_file_map::HotreloadError;
|
||||||
use crate::serve::hot_reloading_file_map::FileMap;
|
use crate::serve::hot_reloading_file_map::FileMap;
|
||||||
use crate::TraceSrc;
|
use crate::TraceSrc;
|
||||||
use crate::{cli::serve::Serve, dioxus_crate::DioxusCrate};
|
use crate::{cli::serve::Serve, dioxus_crate::DioxusCrate};
|
||||||
use dioxus_hot_reload::HotReloadMsg;
|
use dioxus_devtools::HotReloadMsg;
|
||||||
use dioxus_html::HtmlCtx;
|
use dioxus_html::HtmlCtx;
|
||||||
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
|
|
|
@ -19,10 +19,10 @@ dioxus-html = { workspace = true, features = [
|
||||||
] }
|
] }
|
||||||
dioxus-signals = { workspace = true, optional = true }
|
dioxus-signals = { workspace = true, optional = true }
|
||||||
dioxus-interpreter-js = { workspace = true, features = ["binary-protocol", "serialize"] }
|
dioxus-interpreter-js = { workspace = true, features = ["binary-protocol", "serialize"] }
|
||||||
dioxus-cli-config = { workspace = true, features = ["read-config"] }
|
dioxus-cli-config = { workspace = true }
|
||||||
generational-box = { workspace = true }
|
generational-box = { workspace = true }
|
||||||
# hotreload only works on desktop platforms.... mobile is still wip
|
# hotreload only works on desktop platforms.... mobile is still wip
|
||||||
dioxus-hot-reload = { workspace = true, optional = true, features = ["serve", "client"]}
|
dioxus-devtools = { workspace = true, optional = true }
|
||||||
|
|
||||||
serde = "1.0.136"
|
serde = "1.0.136"
|
||||||
serde_json = "1.0.79"
|
serde_json = "1.0.79"
|
||||||
|
@ -89,16 +89,15 @@ core-foundation = "0.9.3"
|
||||||
objc = "0.2.7"
|
objc = "0.2.7"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["tokio_runtime", "wry/objc-exception", "hot-reload", "devtools"]
|
default = ["tokio_runtime", "wry/objc-exception", "devtools"]
|
||||||
tokio_runtime = ["dep:tokio"]
|
tokio_runtime = ["dep:tokio"]
|
||||||
fullscreen = ["wry/fullscreen"]
|
fullscreen = ["wry/fullscreen"]
|
||||||
transparent = ["wry/transparent"]
|
transparent = ["wry/transparent"]
|
||||||
devtools = ["wry/devtools"]
|
devtools = ["wry/devtools", "dep:dioxus-devtools", "dioxus-signals"]
|
||||||
hot-reload = ["dep:dioxus-hot-reload", "dioxus-signals"]
|
|
||||||
gnu = []
|
gnu = []
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["tokio_runtime", "hot-reload"]
|
features = ["tokio_runtime", "devtools"]
|
||||||
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
|
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
|
||||||
default-features = false
|
default-features = false
|
||||||
targets = [
|
targets = [
|
||||||
|
|
|
@ -86,12 +86,7 @@ impl App {
|
||||||
app.set_menubar_receiver();
|
app.set_menubar_receiver();
|
||||||
|
|
||||||
// Allow hotreloading to work - but only in debug mode
|
// Allow hotreloading to work - but only in debug mode
|
||||||
#[cfg(all(
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
feature = "hot-reload",
|
|
||||||
debug_assertions,
|
|
||||||
not(target_os = "android"),
|
|
||||||
not(target_os = "ios")
|
|
||||||
))]
|
|
||||||
app.connect_hotreload();
|
app.connect_hotreload();
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
|
@ -140,25 +135,14 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
feature = "hot-reload",
|
|
||||||
debug_assertions,
|
|
||||||
not(target_os = "android"),
|
|
||||||
not(target_os = "ios")
|
|
||||||
))]
|
|
||||||
pub fn connect_hotreload(&self) {
|
pub fn connect_hotreload(&self) {
|
||||||
|
if let Some(endpoint) = dioxus_cli_config::devserver_ws_endpoint() {
|
||||||
let proxy = self.shared.proxy.clone();
|
let proxy = self.shared.proxy.clone();
|
||||||
|
dioxus_devtools::connect(endpoint, move |msg| {
|
||||||
tokio::task::spawn(async move {
|
|
||||||
let Some(Ok(mut receiver)) = dioxus_hot_reload::NativeReceiver::create_from_cli().await
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
while let Some(Ok(msg)) = receiver.next().await {
|
|
||||||
_ = proxy.send_event(UserWindowEvent::HotReloadEvent(msg));
|
_ = proxy.send_event(UserWindowEvent::HotReloadEvent(msg));
|
||||||
|
})
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_new_window(&mut self) {
|
pub fn handle_new_window(&mut self) {
|
||||||
|
@ -276,19 +260,14 @@ impl App {
|
||||||
view.desktop_context.query.send(result);
|
view.desktop_context.query.send(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
feature = "hot-reload",
|
pub fn handle_hot_reload_msg(&mut self, msg: dioxus_devtools::DevserverMsg) {
|
||||||
debug_assertions,
|
use dioxus_devtools::DevserverMsg;
|
||||||
not(target_os = "android"),
|
|
||||||
not(target_os = "ios")
|
|
||||||
))]
|
|
||||||
pub fn handle_hot_reload_msg(&mut self, msg: dioxus_hot_reload::DevserverMsg) {
|
|
||||||
use dioxus_hot_reload::DevserverMsg;
|
|
||||||
|
|
||||||
match msg {
|
match msg {
|
||||||
DevserverMsg::HotReload(hr_msg) => {
|
DevserverMsg::HotReload(hr_msg) => {
|
||||||
for webview in self.webviews.values_mut() {
|
for webview in self.webviews.values_mut() {
|
||||||
dioxus_hot_reload::apply_changes(&mut webview.dom, &hr_msg);
|
dioxus_devtools::apply_changes(&webview.dom, &hr_msg);
|
||||||
webview.poll_vdom();
|
webview.poll_vdom();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,18 +65,12 @@ impl Config {
|
||||||
/// Initializes a new `WindowBuilder` with default values.
|
/// Initializes a new `WindowBuilder` with default values.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let dioxus_config = dioxus_cli_config::CURRENT_CONFIG.as_ref();
|
let mut window: WindowBuilder = WindowBuilder::new()
|
||||||
|
.with_title(dioxus_cli_config::app_title().unwrap_or_else(|| "Dioxus App".to_string()));
|
||||||
let mut window: WindowBuilder = WindowBuilder::new().with_title(
|
|
||||||
dioxus_config
|
|
||||||
.map(|c| c.application.name.clone())
|
|
||||||
.unwrap_or("Dioxus App".to_string()),
|
|
||||||
);
|
|
||||||
|
|
||||||
// During development we want the window to be on top so we can see it while we work
|
// During development we want the window to be on top so we can see it while we work
|
||||||
let always_on_top = dioxus_config
|
let always_on_top = dioxus_cli_config::always_on_top().unwrap_or(true);
|
||||||
.map(|c| c.desktop.always_on_top)
|
|
||||||
.unwrap_or(true);
|
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
window = window.with_always_on_top(always_on_top);
|
window = window.with_always_on_top(always_on_top);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,12 @@ pub enum UserWindowEvent {
|
||||||
|
|
||||||
/// Handle a hotreload event, basically telling us to update our templates
|
/// Handle a hotreload event, basically telling us to update our templates
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
feature = "hot-reload",
|
feature = "devtools",
|
||||||
debug_assertions,
|
debug_assertions,
|
||||||
not(target_os = "android"),
|
not(target_os = "android"),
|
||||||
not(target_os = "ios")
|
not(target_os = "ios")
|
||||||
))]
|
))]
|
||||||
HotReloadEvent(dioxus_hot_reload::DevserverMsg),
|
HotReloadEvent(dioxus_devtools::DevserverMsg),
|
||||||
|
|
||||||
/// Create a new window
|
/// Create a new window
|
||||||
NewWindow,
|
NewWindow,
|
||||||
|
|
|
@ -41,12 +41,7 @@ pub fn launch_virtual_dom_blocking(virtual_dom: VirtualDom, desktop_config: Conf
|
||||||
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
#[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
|
||||||
UserWindowEvent::MudaMenuEvent(evnt) => app.handle_menu_event(evnt),
|
UserWindowEvent::MudaMenuEvent(evnt) => app.handle_menu_event(evnt),
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
feature = "hot-reload",
|
|
||||||
debug_assertions,
|
|
||||||
not(target_os = "android"),
|
|
||||||
not(target_os = "ios")
|
|
||||||
))]
|
|
||||||
UserWindowEvent::HotReloadEvent(msg) => app.handle_hot_reload_msg(msg),
|
UserWindowEvent::HotReloadEvent(msg) => app.handle_hot_reload_msg(msg),
|
||||||
|
|
||||||
UserWindowEvent::Ipc { id, msg } => match msg.method() {
|
UserWindowEvent::Ipc { id, msg } => match msg.method() {
|
||||||
|
|
|
@ -280,10 +280,10 @@ fn running_in_dev_mode() -> bool {
|
||||||
#[allow(unreachable_code)]
|
#[allow(unreachable_code)]
|
||||||
fn get_asset_root() -> Option<PathBuf> {
|
fn get_asset_root() -> Option<PathBuf> {
|
||||||
if running_in_dev_mode() {
|
if running_in_dev_mode() {
|
||||||
return dioxus_cli_config::CURRENT_CONFIG
|
// todo: we don't want to canonicalize assets like this, but it will take longer to migrate, so we'll do it later
|
||||||
.as_ref()
|
// we should just be parsing paths the way they are instead of relative to the "asset" dir
|
||||||
.map(|c| c.application.out_dir.clone())
|
// manganis will eventually just dump the raw path to us, but until then, we need to canonicalize here
|
||||||
.ok();
|
return dioxus_cli_config::base_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
|
|
@ -381,7 +381,7 @@ impl WebviewInstance {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
pub fn kick_stylsheets(&self) {
|
pub fn kick_stylsheets(&self) {
|
||||||
// run eval in the webview to kick the stylesheets by appending a query string
|
// run eval in the webview to kick the stylesheets by appending a query string
|
||||||
// we should do something less clunky than this
|
// we should do something less clunky than this
|
||||||
|
|
8
packages/devtools-types/Cargo.toml
Normal file
8
packages/devtools-types/Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "dioxus-devtools-types"
|
||||||
|
edition = "2021"
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
dioxus-core = { workspace = true }
|
|
@ -2,18 +2,6 @@ use dioxus_core::internal::HotReloadTemplateWithLocation;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[cfg(feature = "client")]
|
|
||||||
mod client;
|
|
||||||
|
|
||||||
#[cfg(feature = "client")]
|
|
||||||
pub use client::*;
|
|
||||||
|
|
||||||
#[cfg(feature = "serve")]
|
|
||||||
mod ws_receiver;
|
|
||||||
|
|
||||||
#[cfg(feature = "serve")]
|
|
||||||
pub use ws_receiver::*;
|
|
||||||
|
|
||||||
/// A message the hot reloading server sends to the client
|
/// A message the hot reloading server sends to the client
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
|
||||||
pub enum DevserverMsg {
|
pub enum DevserverMsg {
|
||||||
|
@ -49,21 +37,5 @@ pub enum ClientMsg {
|
||||||
pub struct HotReloadMsg {
|
pub struct HotReloadMsg {
|
||||||
pub templates: Vec<HotReloadTemplateWithLocation>,
|
pub templates: Vec<HotReloadTemplateWithLocation>,
|
||||||
pub assets: Vec<PathBuf>,
|
pub assets: Vec<PathBuf>,
|
||||||
|
|
||||||
/// A file changed that's not an asset or a rust file - best of luck!
|
|
||||||
pub unknown_files: Vec<PathBuf>,
|
pub unknown_files: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn serialize_client_msg() {
|
|
||||||
let msg = ClientMsg::Log {
|
|
||||||
level: "info".to_string(),
|
|
||||||
messages: vec!["hello world".to_string()],
|
|
||||||
};
|
|
||||||
|
|
||||||
let json = serde_json::to_string(&msg).unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
json,
|
|
||||||
r#"{"Log":{"level":"info","messages":["hello world"]}}"#
|
|
||||||
);
|
|
||||||
}
|
|
31
packages/devtools/Cargo.toml
Normal file
31
packages/devtools/Cargo.toml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
[package]
|
||||||
|
name = "dioxus-devtools"
|
||||||
|
authors = ["Jonathan Kelley", "Evan Almloff"]
|
||||||
|
version = { workspace = true }
|
||||||
|
edition = "2021"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
repository = "https://github.com/DioxusLabs/dioxus/"
|
||||||
|
homepage = "https://dioxuslabs.com/learn/0.4/migration/hot_reload"
|
||||||
|
description = "Hot reloading utilities for Dioxus"
|
||||||
|
keywords = ["dom", "ui", "gui", "react", "hot-reloading"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dioxus-signals = { workspace = true }
|
||||||
|
dioxus-core = { workspace = true, features = ["serialize"] }
|
||||||
|
dioxus-devtools-types = { workspace = true }
|
||||||
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
serde_json = { workspace = true }
|
||||||
|
|
||||||
|
# hot reloading serve
|
||||||
|
tracing = { workspace = true }
|
||||||
|
warnings.workspace = true
|
||||||
|
|
||||||
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
tungstenite = { version = "0.23.0" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
tokio = { workspace = true, features = ["full"] }
|
||||||
|
serde_json = "1.0.91"
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
|
59
packages/devtools/src/lib.rs
Normal file
59
packages/devtools/src/lib.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use dioxus_core::{ScopeId, VirtualDom};
|
||||||
|
pub use dioxus_devtools_types::*;
|
||||||
|
use dioxus_signals::Writable;
|
||||||
|
use warnings::Warning;
|
||||||
|
|
||||||
|
/// Applies template and literal changes to the VirtualDom
|
||||||
|
///
|
||||||
|
/// Assets need to be handled by the renderer.
|
||||||
|
pub fn apply_changes(dom: &VirtualDom, msg: &HotReloadMsg) {
|
||||||
|
dom.runtime().on_scope(ScopeId::ROOT, || {
|
||||||
|
let ctx = dioxus_signals::get_global_context();
|
||||||
|
|
||||||
|
for template in &msg.templates {
|
||||||
|
let id = &template.location;
|
||||||
|
let value = template.template.clone();
|
||||||
|
if let Some(mut signal) = ctx.get_signal_with_key(id) {
|
||||||
|
dioxus_signals::warnings::signal_read_and_write_in_reactive_scope::allow(|| {
|
||||||
|
dioxus_signals::warnings::signal_write_in_component_body::allow(|| {
|
||||||
|
signal.set(Some(value));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Connect to the devserver and handle its messages with a callback.
|
||||||
|
///
|
||||||
|
/// This doesn't use any form of security or protocol, so it's not safe to expose to the internet.
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
pub fn connect(endpoint: String, mut callback: impl FnMut(DevserverMsg) + Send + 'static) {
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
let (mut websocket, _req) = match tungstenite::connect(endpoint.clone()) {
|
||||||
|
Ok((websocket, req)) => (websocket, req),
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!(
|
||||||
|
"Failed to connect to devserver at {} because {}",
|
||||||
|
endpoint, err
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
while let Ok(msg) = websocket.read() {
|
||||||
|
match msg {
|
||||||
|
tungstenite::Message::Text(text) => {
|
||||||
|
if let Ok(msg) = serde_json::from_str(&text) {
|
||||||
|
callback(msg);
|
||||||
|
} else {
|
||||||
|
eprintln!("Failed to parse message from devserver: {:?}", text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg => {
|
||||||
|
println!("Received a non-text message: {:?}", msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -31,16 +31,16 @@ serde = { version = "1.0.136", optional = true }
|
||||||
axum = { workspace = true, optional = true }
|
axum = { workspace = true, optional = true }
|
||||||
|
|
||||||
[target.'cfg(not(any(target_arch = "wasm32", target_os = "ios", target_os = "android")))'.dependencies]
|
[target.'cfg(not(any(target_arch = "wasm32", target_os = "ios", target_os = "android")))'.dependencies]
|
||||||
dioxus-hot-reload = { workspace = true, optional = true }
|
dioxus-devtools = { workspace = true, optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["macro", "html", "hot-reload", "signals", "hooks", "launch", "mounted", "file_engine", "document", "asset"]
|
default = ["macro", "html", "devtools", "signals", "hooks", "launch", "mounted", "file_engine", "document", "asset"]
|
||||||
minimal = ["macro", "html", "signals", "hooks", "launch"]
|
minimal = ["macro", "html", "signals", "hooks", "launch"]
|
||||||
signals = ["dep:dioxus-signals"]
|
signals = ["dep:dioxus-signals"]
|
||||||
macro = ["dep:dioxus-core-macro"]
|
macro = ["dep:dioxus-core-macro"]
|
||||||
html = ["dep:dioxus-html"]
|
html = ["dep:dioxus-html"]
|
||||||
hooks = ["dep:dioxus-hooks"]
|
hooks = ["dep:dioxus-hooks"]
|
||||||
hot-reload = ["dep:dioxus-hot-reload", "dioxus-web?/hot_reload", "dioxus-fullstack?/hot-reload"]
|
devtools = ["dep:dioxus-devtools", "dioxus-web?/devtools", "dioxus-fullstack?/devtools"]
|
||||||
mounted = ["dioxus-web?/mounted", "dioxus-html?/mounted"]
|
mounted = ["dioxus-web?/mounted", "dioxus-html?/mounted"]
|
||||||
file_engine = ["dioxus-web?/file_engine"]
|
file_engine = ["dioxus-web?/file_engine"]
|
||||||
asset = ["dep:manganis", "dioxus-core/manganis"]
|
asset = ["dep:manganis", "dioxus-core/manganis"]
|
||||||
|
|
|
@ -93,10 +93,10 @@ pub mod prelude {
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
not(any(target_arch = "wasm32", target_os = "ios", target_os = "android")),
|
not(any(target_arch = "wasm32", target_os = "ios", target_os = "android")),
|
||||||
feature = "hot-reload"
|
feature = "devtools"
|
||||||
))]
|
))]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "hot-reload")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "devtools")))]
|
||||||
pub use dioxus_hot_reload;
|
pub use dioxus_devtools;
|
||||||
|
|
||||||
pub use dioxus_core;
|
pub use dioxus_core;
|
||||||
|
|
||||||
|
|
|
@ -61,25 +61,24 @@ tower-layer = { version = "0.3.2", optional = true }
|
||||||
parking_lot = { version = "0.12.1", features = ["send_guard"], optional = true }
|
parking_lot = { version = "0.12.1", features = ["send_guard"], optional = true }
|
||||||
web-sys = { version = "0.3.61", optional = true, features = ["Window", "Document", "Element", "HtmlDocument", "Storage", "console"] }
|
web-sys = { version = "0.3.61", optional = true, features = ["Window", "Document", "Element", "HtmlDocument", "Storage", "console"] }
|
||||||
|
|
||||||
dioxus-cli-config = { workspace = true, features = ["read-config"], optional = true }
|
dioxus-cli-config = { workspace = true, optional = true }
|
||||||
clap = { version = "4.5.7", optional = true, features = ["derive"] }
|
|
||||||
|
|
||||||
|
dioxus-devtools = { workspace = true, optional = true }
|
||||||
aws-lc-rs = { version = "1.8.1", optional = true }
|
aws-lc-rs = { version = "1.8.1", optional = true }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
tokio = { workspace = true, features = ["rt", "sync"], optional = true }
|
tokio = { workspace = true, features = ["rt", "sync"], optional = true }
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
dioxus-hot-reload = { workspace = true, features = ["serve"] }
|
|
||||||
tokio = { workspace = true, features = ["rt", "sync", "rt-multi-thread"], optional = true }
|
tokio = { workspace = true, features = ["rt", "sync", "rt-multi-thread"], optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
dioxus = { workspace = true, features = ["fullstack"] }
|
dioxus = { workspace = true, features = ["fullstack"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["hot-reload", "panic_hook", "document", "file_engine", "mounted"]
|
default = ["devtools", "panic_hook", "document", "file_engine", "mounted"]
|
||||||
panic_hook = ["dioxus-web?/panic_hook"]
|
panic_hook = ["dioxus-web?/panic_hook"]
|
||||||
hot-reload = ["dioxus-web?/hot_reload", "dioxus-hot-reload/serve"]
|
devtools = ["dioxus-web?/devtools", "dep:dioxus-devtools"]
|
||||||
mounted = ["dioxus-web?/mounted"]
|
mounted = ["dioxus-web?/mounted"]
|
||||||
file_engine = ["dioxus-web?/file_engine"]
|
file_engine = ["dioxus-web?/file_engine"]
|
||||||
document = ["dioxus-web?/document"]
|
document = ["dioxus-web?/document"]
|
||||||
|
@ -108,8 +107,6 @@ server = [
|
||||||
"dep:async-trait",
|
"dep:async-trait",
|
||||||
"dep:parking_lot",
|
"dep:parking_lot",
|
||||||
"dioxus-interpreter-js",
|
"dioxus-interpreter-js",
|
||||||
"dep:clap",
|
|
||||||
"dioxus-cli-config/read-from-args",
|
|
||||||
]
|
]
|
||||||
aws-lc-rs = ["dep:aws-lc-rs"]
|
aws-lc-rs = ["dep:aws-lc-rs"]
|
||||||
|
|
||||||
|
|
|
@ -126,16 +126,9 @@ async fn launch_server(
|
||||||
build_virtual_dom: impl Fn() -> VirtualDom + Send + Sync + 'static,
|
build_virtual_dom: impl Fn() -> VirtualDom + Send + Sync + 'static,
|
||||||
context_providers: ContextProviders,
|
context_providers: ContextProviders,
|
||||||
) {
|
) {
|
||||||
use clap::Parser;
|
|
||||||
|
|
||||||
// Get the address the server should run on. If the CLI is running, the CLI proxies fullstack into the main address
|
// Get the address the server should run on. If the CLI is running, the CLI proxies fullstack into the main address
|
||||||
// and we use the generated address the CLI gives us
|
// and we use the generated address the CLI gives us
|
||||||
let cli_args = dioxus_cli_config::RuntimeCLIArguments::from_cli();
|
let address = dioxus_cli_config::fullstack_address_or_localhost();
|
||||||
let address = cli_args
|
|
||||||
.as_ref()
|
|
||||||
.map(|args| args.fullstack_address())
|
|
||||||
.unwrap_or_else(dioxus_cli_config::AddressArguments::parse)
|
|
||||||
.address();
|
|
||||||
|
|
||||||
#[cfg(feature = "axum")]
|
#[cfg(feature = "axum")]
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "dioxus-hot-reload"
|
|
||||||
authors = ["Jonathan Kelley", "Evan Almloff"]
|
|
||||||
version = { workspace = true }
|
|
||||||
edition = "2021"
|
|
||||||
license = "MIT OR Apache-2.0"
|
|
||||||
repository = "https://github.com/DioxusLabs/dioxus/"
|
|
||||||
homepage = "https://dioxuslabs.com/learn/0.4/migration/hot_reload"
|
|
||||||
description = "Hot reloading utilities for Dioxus"
|
|
||||||
keywords = ["dom", "ui", "gui", "react", "hot-reloading"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
dioxus-rsx = { workspace = true }
|
|
||||||
dioxus-rsx-hotreload = { workspace = true }
|
|
||||||
dioxus-core = { workspace = true, features = ["serialize"] }
|
|
||||||
dioxus-html = { workspace = true, optional = true }
|
|
||||||
dioxus-signals = { workspace = true, optional = true }
|
|
||||||
dioxus-cli-config = { workspace = true, optional = true, features = ["read-config"] }
|
|
||||||
|
|
||||||
notify = { workspace = true, optional = true }
|
|
||||||
chrono = { version = "0.4.24", default-features = false, features = ["clock"], optional = true }
|
|
||||||
serde_json = "1.0.91"
|
|
||||||
serde = { version = "1", features = ["derive"] }
|
|
||||||
execute = { version = "0.2.11", optional = true }
|
|
||||||
once_cell = { version = "1.17.0", optional = true }
|
|
||||||
ignore = { version = "0.4.19", optional = true }
|
|
||||||
|
|
||||||
# hot reloading serve
|
|
||||||
tokio-stream = { version = "0.1.12", features = ["sync"], optional = true }
|
|
||||||
futures-util = { workspace = true, features = ["async-await-macro"], optional = true }
|
|
||||||
tokio = { workspace = true, features = ["sync", "rt-multi-thread"], optional = true }
|
|
||||||
tracing = { workspace = true }
|
|
||||||
warnings.workspace = true
|
|
||||||
|
|
||||||
# use rustls on android
|
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
|
||||||
tokio-tungstenite = { workspace = true, optional = true, features = ["rustls"] }
|
|
||||||
|
|
||||||
# use native tls on other platforms
|
|
||||||
[target.'cfg(not(target_os = "android"))'.dependencies]
|
|
||||||
tokio-tungstenite = { workspace = true, optional = true, features = ["native-tls"] }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
tokio = { workspace = true, features = ["full"] }
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = ["dioxus-html"]
|
|
||||||
client = ["dep:dioxus-signals"]
|
|
||||||
serve = ["dep:tokio-stream", "dep:futures-util", "dep:tokio", "dep:tokio-tungstenite", "dep:dioxus-cli-config"]
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
|
||||||
cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
|
|
|
@ -1,171 +0,0 @@
|
||||||
# `dioxus-hot-reload`: Hot Reloading Utilities for Dioxus
|
|
||||||
|
|
||||||
[![Crates.io][crates-badge]][crates-url]
|
|
||||||
[![MIT licensed][mit-badge]][mit-url]
|
|
||||||
[![Build Status][actions-badge]][actions-url]
|
|
||||||
[![Discord chat][discord-badge]][discord-url]
|
|
||||||
|
|
||||||
[crates-badge]: https://img.shields.io/crates/v/dioxus-hot-reload.svg
|
|
||||||
[crates-url]: https://crates.io/crates/dioxus-hot-reload
|
|
||||||
[mit-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
|
||||||
[mit-url]: https://github.com/dioxuslabs/dioxus/blob/main/LICENSE-MIT
|
|
||||||
[actions-badge]: https://github.com/dioxuslabs/dioxus/actions/workflows/main.yml/badge.svg
|
|
||||||
[actions-url]: https://github.com/dioxuslabs/dioxus/actions?query=workflow%3ACI+branch%3Amaster
|
|
||||||
[discord-badge]: https://img.shields.io/discord/899851952891002890.svg?logo=discord&style=flat-square
|
|
||||||
[discord-url]: https://discord.gg/XgGxMSkvUM
|
|
||||||
|
|
||||||
[Website](https://dioxuslabs.com) |
|
|
||||||
[Guides](https://dioxuslabs.com/learn/0.5/) |
|
|
||||||
[API Docs](https://docs.rs/dioxus-hot-reload/latest/dioxus_hot_reload) |
|
|
||||||
[Chat](https://discord.gg/XgGxMSkvUM)
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
Dioxus supports hot reloading for static parts of rsx macros. This enables changing the styling of your application without recompiling the rust code. This is useful for rapid iteration on the styling of your application.
|
|
||||||
|
|
||||||
Hot reloading could update the following change without recompiling:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
rsx! {
|
|
||||||
div {
|
|
||||||
"Count: {count}",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
=>
|
|
||||||
|
|
||||||
```rust
|
|
||||||
rsx! {
|
|
||||||
div {
|
|
||||||
color: "red",
|
|
||||||
font_size: "2em",
|
|
||||||
"Count: {count}",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
But it could not update the following change:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
rsx! {
|
|
||||||
div {
|
|
||||||
"Count: {count}",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
=>
|
|
||||||
|
|
||||||
```rust
|
|
||||||
rsx! {
|
|
||||||
div {
|
|
||||||
"Count: {count*2}",
|
|
||||||
onclick: |_| println!("clicked"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
> This crate implements hot reloading for native compilation targets not WASM. For hot reloading with the web renderer, see the [dioxus-cli](https://github.com/DioxusLabs/dioxus/tree/master/packages/cli) project.
|
|
||||||
|
|
||||||
Add this to the top of your main function on any renderer that supports hot reloading to start the hot reloading server:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
fn main(){
|
|
||||||
hot_reload_init!();
|
|
||||||
// launch your application
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
By default the dev server watches on the root of the crate the macro is called in and ignores changes in the `/target` directory and any directories set in the `.gitignore` file in the root directory. To watch on custom paths pass call the `with_paths` function on the config builder:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
fn main(){
|
|
||||||
hot_reload_init!(Config::new().with_paths(&["src", "examples", "assets"]));
|
|
||||||
// launch your application
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
By default the hot reloading server will output some logs in the console, to disable these logs call the `with_logging` function on the config builder:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
fn main(){
|
|
||||||
hot_reload_init!(Config::new().with_logging(false));
|
|
||||||
// launch your application
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
To rebuild the application when the logic changes, you can use the `with_rebuild_command` function on the config builder. This command will be called when hot reloading fails to quickly update the rsx:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
fn main(){
|
|
||||||
hot_reload_init!(Config::new().with_rebuild_command("cargo run"));
|
|
||||||
// launch your application
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If you are using a namespace other than html, you can implement the [HotReloadingContext](https://docs.rs/dioxus-rsx/latest/dioxus_rsx/index.html#reexport.HotReloadingContext) trait to provide a mapping between the rust names of your elements/attributes and the resulting strings.
|
|
||||||
|
|
||||||
You can then provide the Context to the builder to make hot reloading work with your custom namespace:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
fn main(){
|
|
||||||
// Note: Use default instead of new if you are using a custom namespace
|
|
||||||
hot_reload_init!(Config::<MyContext>::default());
|
|
||||||
// launch your application
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Implementing Hot Reloading for a Custom Renderer
|
|
||||||
|
|
||||||
To add hot reloading support to your custom renderer you can use the connect function. This will connect to the dev server you just need to provide a way to transfer `Template`s to the `VirtualDom`. Once you implement this your users can use the hot_reload_init function just like any other render.
|
|
||||||
|
|
||||||
```rust
|
|
||||||
async fn launch(app: Component) {
|
|
||||||
let mut vdom = VirtualDom::new(app);
|
|
||||||
// ...
|
|
||||||
|
|
||||||
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel();
|
|
||||||
dioxus_hot_reload::connect(move |msg| {
|
|
||||||
let _ = tx.send(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
loop {
|
|
||||||
tokio::select! {
|
|
||||||
Some(msg) = rx.recv() => {
|
|
||||||
match msg{
|
|
||||||
HotReloadMsg::Shutdown => {
|
|
||||||
// ... shutdown the application
|
|
||||||
}
|
|
||||||
HotReloadMsg::UpdateTemplate(template) => {
|
|
||||||
// update the template in the virtual dom
|
|
||||||
vdom.replace_template(template);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ = vdom.wait_for_work() => {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mutations = vdom.render_immediate();
|
|
||||||
// apply the mutations to the dom
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
- Report issues on our [issue tracker](https://github.com/dioxuslabs/dioxus/issues).
|
|
||||||
- Join the discord and ask questions!
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
This project is licensed under the [MIT license].
|
|
||||||
|
|
||||||
[mit license]: https://github.com/dioxuslabs/dioxus/blob/main/LICENSE-MIT
|
|
||||||
|
|
||||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
|
||||||
for inclusion in Dioxus by you shall be licensed as MIT without any additional
|
|
||||||
terms or conditions.
|
|
|
@ -1,25 +0,0 @@
|
||||||
use crate::HotReloadMsg;
|
|
||||||
use dioxus_core::{ScopeId, VirtualDom};
|
|
||||||
use dioxus_signals::Writable;
|
|
||||||
use warnings::Warning;
|
|
||||||
|
|
||||||
/// Applies template and literal changes to the VirtualDom
|
|
||||||
///
|
|
||||||
/// Assets need to be handled by the renderer.
|
|
||||||
pub fn apply_changes(dom: &mut VirtualDom, msg: &HotReloadMsg) {
|
|
||||||
dom.runtime().on_scope(ScopeId::ROOT, || {
|
|
||||||
let ctx = dioxus_signals::get_global_context();
|
|
||||||
|
|
||||||
for template in &msg.templates {
|
|
||||||
let id = &template.location;
|
|
||||||
let value = template.template.clone();
|
|
||||||
if let Some(mut signal) = ctx.get_signal_with_key(id) {
|
|
||||||
dioxus_signals::warnings::signal_read_and_write_in_reactive_scope::allow(|| {
|
|
||||||
dioxus_signals::warnings::signal_write_in_component_body::allow(|| {
|
|
||||||
signal.set(Some(value));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
use crate::DevserverMsg;
|
|
||||||
use futures_util::{SinkExt, StreamExt};
|
|
||||||
use tokio::net::TcpStream;
|
|
||||||
use tokio_tungstenite::{
|
|
||||||
tungstenite::{Message, Result as TtResult},
|
|
||||||
MaybeTlsStream, WebSocketStream,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn connect(mut callback: impl FnMut(DevserverMsg) + Send + 'static) {
|
|
||||||
tokio::spawn(async move {
|
|
||||||
let Some(Ok(mut recv)) = NativeReceiver::create_from_cli().await else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
while let Some(msg) = recv.next().await {
|
|
||||||
match msg {
|
|
||||||
Ok(msg) => callback(msg),
|
|
||||||
Err(_e) => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A receiver for messages from the devserver
|
|
||||||
///
|
|
||||||
/// Calling `next` will watch the channel for the next valid message from the devserver
|
|
||||||
pub struct NativeReceiver {
|
|
||||||
socket: WebSocketStream<MaybeTlsStream<TcpStream>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NativeReceiver {
|
|
||||||
/// Connect to the devserver
|
|
||||||
async fn create(url: String) -> TtResult<Self> {
|
|
||||||
let (socket, _ws) = tokio_tungstenite::connect_async(&url).await?;
|
|
||||||
Ok(Self { socket })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Connect to the devserver with an address from the CLI. Returns None if the current application was not run with the CLI
|
|
||||||
pub async fn create_from_cli() -> Option<TtResult<Self>> {
|
|
||||||
let cli_args = dioxus_cli_config::RuntimeCLIArguments::from_cli()?;
|
|
||||||
let addr = cli_args.cli_address();
|
|
||||||
Some(Self::create(format!("ws://{addr}/_dioxus")).await)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wait for the next message from the devserver
|
|
||||||
///
|
|
||||||
/// Returns None when the connection is closed or socket.next() returns None
|
|
||||||
pub async fn next(&mut self) -> Option<TtResult<DevserverMsg>> {
|
|
||||||
loop {
|
|
||||||
let res = self.socket.next().await?;
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Ok(res) => match res {
|
|
||||||
Message::Text(text) => {
|
|
||||||
// let leaked: &'static str = Box::leak(text.into_boxed_str());
|
|
||||||
let msg = serde_json::from_str::<DevserverMsg>(&text);
|
|
||||||
if let Ok(msg) = msg {
|
|
||||||
return Some(Ok(msg));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// send a pong
|
|
||||||
Message::Ping(_) => {
|
|
||||||
let _ = self.socket.send(Message::Pong(vec![])).await;
|
|
||||||
}
|
|
||||||
Message::Close(_) => return None,
|
|
||||||
Message::Binary(_) => {}
|
|
||||||
Message::Pong(_) => {}
|
|
||||||
Message::Frame(_) => {}
|
|
||||||
},
|
|
||||||
Err(e) => return Some(Err(e)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,8 +26,8 @@ dioxus-html = { workspace = true, features = ["serialize", "document", "mounted"
|
||||||
rustc-hash = { workspace = true }
|
rustc-hash = { workspace = true }
|
||||||
dioxus-core = { workspace = true, features = ["serialize"] }
|
dioxus-core = { workspace = true, features = ["serialize"] }
|
||||||
dioxus-interpreter-js = { workspace = true, features = ["binary-protocol"] }
|
dioxus-interpreter-js = { workspace = true, features = ["binary-protocol"] }
|
||||||
dioxus-hot-reload = { workspace = true, optional = true, features = ["serve", "client"] }
|
dioxus-devtools = { workspace = true, optional = true }
|
||||||
dioxus-cli-config = { workspace = true, features = ["read-config", "read-from-args"] }
|
dioxus-cli-config = { workspace = true }
|
||||||
generational-box = { workspace = true }
|
generational-box = { workspace = true }
|
||||||
|
|
||||||
# axum
|
# axum
|
||||||
|
@ -41,10 +41,10 @@ tower = { workspace = true }
|
||||||
dioxus = { workspace = true }
|
dioxus = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["hot-reload", "multi-thread"]
|
default = ["devtools", "multi-thread"]
|
||||||
axum = ["dep:axum"]
|
axum = ["dep:axum"]
|
||||||
multi-thread = ["tokio/rt-multi-thread"]
|
multi-thread = ["tokio/rt-multi-thread"]
|
||||||
hot-reload = ["dep:dioxus-hot-reload"]
|
devtools = ["dep:dioxus-devtools"]
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "axum"
|
name = "axum"
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
use dioxus_cli_config::{RuntimeCLIArguments, CURRENT_CONFIG};
|
|
||||||
use dioxus_core::VirtualDom;
|
use dioxus_core::VirtualDom;
|
||||||
|
|
||||||
use crate::LiveviewRouter;
|
use crate::LiveviewRouter;
|
||||||
|
|
||||||
pub(crate) fn app_title() -> String {
|
pub(crate) fn app_title() -> String {
|
||||||
CURRENT_CONFIG
|
dioxus_cli_config::app_title().unwrap_or_else(|| "Dioxus Liveview App".to_string())
|
||||||
.as_ref()
|
|
||||||
.map(|c| c.web.app.title.clone())
|
|
||||||
.unwrap_or_else(|_| "Dioxus Liveview App".to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A configuration for the LiveView server.
|
/// A configuration for the LiveView server.
|
||||||
|
@ -19,15 +15,9 @@ pub struct Config<R: LiveviewRouter> {
|
||||||
|
|
||||||
impl<R: LiveviewRouter> Default for Config<R> {
|
impl<R: LiveviewRouter> Default for Config<R> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let address = RuntimeCLIArguments::from_cli()
|
|
||||||
.map(|args| args.fullstack_address().address())
|
|
||||||
.unwrap_or(std::net::SocketAddr::V4(std::net::SocketAddrV4::new(
|
|
||||||
std::net::Ipv4Addr::new(127, 0, 0, 1),
|
|
||||||
8080,
|
|
||||||
)));
|
|
||||||
Self {
|
Self {
|
||||||
|
address: dioxus_cli_config::fullstack_address_or_localhost(),
|
||||||
router: R::create_default_liveview_router(),
|
router: R::create_default_liveview_router(),
|
||||||
address,
|
|
||||||
route: "/".to_string(),
|
route: "/".to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ use crate::{
|
||||||
LiveViewError,
|
LiveViewError,
|
||||||
};
|
};
|
||||||
use dioxus_core::prelude::*;
|
use dioxus_core::prelude::*;
|
||||||
use dioxus_hot_reload::DevserverMsg;
|
|
||||||
use dioxus_html::{EventData, HtmlEvent, PlatformEventData};
|
use dioxus_html::{EventData, HtmlEvent, PlatformEventData};
|
||||||
use dioxus_interpreter_js::MutationState;
|
use dioxus_interpreter_js::MutationState;
|
||||||
use futures_util::{pin_mut, SinkExt, StreamExt};
|
use futures_util::{pin_mut, SinkExt, StreamExt};
|
||||||
|
@ -117,10 +116,12 @@ impl<S> LiveViewSocket for S where
|
||||||
///
|
///
|
||||||
/// You might need to transform the error types of the web backend into the LiveView error type.
|
/// You might need to transform the error types of the web backend into the LiveView error type.
|
||||||
pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), LiveViewError> {
|
pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), LiveViewError> {
|
||||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
let mut hot_reload_rx = {
|
let mut hot_reload_rx = {
|
||||||
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
|
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
|
||||||
dioxus_hot_reload::connect(move |template| _ = tx.send(template));
|
if let Some(endpoint) = dioxus_cli_config::devserver_ws_endpoint() {
|
||||||
|
dioxus_devtools::connect(endpoint, move |template| _ = tx.send(template));
|
||||||
|
}
|
||||||
rx
|
rx
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -157,9 +158,9 @@ pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), Li
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
let hot_reload_wait = hot_reload_rx.recv();
|
let hot_reload_wait = hot_reload_rx.recv();
|
||||||
#[cfg(not(all(feature = "hot-reload", debug_assertions)))]
|
#[cfg(not(all(feature = "devtools", debug_assertions)))]
|
||||||
let hot_reload_wait: std::future::Pending<Option<()>> = std::future::pending();
|
let hot_reload_wait: std::future::Pending<Option<()>> = std::future::pending();
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
@ -213,22 +214,22 @@ pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), Li
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(msg) = hot_reload_wait => {
|
Some(msg) = hot_reload_wait => {
|
||||||
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
match msg{
|
match msg{
|
||||||
DevserverMsg::HotReload(msg)=> {
|
dioxus_devtools::DevserverMsg::HotReload(msg)=> {
|
||||||
dioxus_hot_reload::apply_changes(&mut vdom, &msg);
|
dioxus_devtools::apply_changes(&vdom, &msg);
|
||||||
}
|
}
|
||||||
DevserverMsg::Shutdown => {
|
dioxus_devtools::DevserverMsg::Shutdown => {
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
},
|
},
|
||||||
DevserverMsg::FullReloadCommand
|
dioxus_devtools::DevserverMsg::FullReloadCommand
|
||||||
| DevserverMsg::FullReloadStart
|
| dioxus_devtools::DevserverMsg::FullReloadStart
|
||||||
| DevserverMsg::FullReloadFailed => {
|
| dioxus_devtools::DevserverMsg::FullReloadFailed => {
|
||||||
// usually only web gets this message - what are we supposed to do?
|
// usually only web gets this message - what are we supposed to do?
|
||||||
// Maybe we could just binary patch ourselves in place without losing window state?
|
// Maybe we could just binary patch ourselves in place without losing window state?
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
#[cfg(not(all(feature = "hot-reload", debug_assertions)))]
|
#[cfg(not(all(feature = "devtools", debug_assertions)))]
|
||||||
let () = msg;
|
let () = msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ dioxus-ssr = { workspace = true, optional = true }
|
||||||
http = { workspace = true, optional = true }
|
http = { workspace = true, optional = true }
|
||||||
dioxus-fullstack = { workspace = true, optional = true }
|
dioxus-fullstack = { workspace = true, optional = true }
|
||||||
tokio = { workspace = true, features = ["full"], optional = true }
|
tokio = { workspace = true, features = ["full"], optional = true }
|
||||||
dioxus-cli-config = { workspace = true, features = ["read-config"] }
|
dioxus-cli-config = { workspace = true }
|
||||||
rustversion = "1.0.17"
|
rustversion = "1.0.17"
|
||||||
|
|
||||||
# you need to comment this out when publishing since cargo workspaces is not smart enough to wipe this when dropping
|
# you need to comment this out when publishing since cargo workspaces is not smart enough to wipe this when dropping
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use std::sync::{Arc, Mutex};
|
use std::{
|
||||||
|
path::PathBuf,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
use gloo::{console::error, events::EventListener, render::AnimationFrame};
|
use gloo::{console::error, events::EventListener, render::AnimationFrame};
|
||||||
|
|
||||||
|
@ -14,12 +17,12 @@ use super::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn base_path() -> Option<&'static str> {
|
fn base_path() -> Option<PathBuf> {
|
||||||
tracing::trace!(
|
tracing::trace!(
|
||||||
"Using base_path from Dioxus.toml: {:?}",
|
"Using base_path from the CLI: {:?}",
|
||||||
dioxus_cli_config::BASE_PATH
|
dioxus_cli_config::base_path()
|
||||||
);
|
);
|
||||||
dioxus_cli_config::BASE_PATH
|
dioxus_cli_config::base_path()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::extra_unused_type_parameters)]
|
#[allow(clippy::extra_unused_type_parameters)]
|
||||||
|
@ -97,7 +100,7 @@ impl<R: Routable> WebHistory<R> {
|
||||||
|
|
||||||
let prefix = prefix
|
let prefix = prefix
|
||||||
// If there isn't a base path, try to grab one from the CLI
|
// If there isn't a base path, try to grab one from the CLI
|
||||||
.or_else(|| base_path().map(|s| s.to_string()))
|
.or_else(|| base_path().map(|s| s.display().to_string()))
|
||||||
// Normalize the prefix to start and end with no slashes
|
// Normalize the prefix to start and end with no slashes
|
||||||
.map(|prefix| prefix.trim_matches('/').to_string())
|
.map(|prefix| prefix.trim_matches('/').to_string())
|
||||||
// If the prefix is empty, don't add it
|
// If the prefix is empty, don't add it
|
||||||
|
|
4
packages/rsx/.vscode/settings.json
vendored
4
packages/rsx/.vscode/settings.json
vendored
|
@ -1,8 +1,4 @@
|
||||||
{
|
{
|
||||||
"rust-analyzer.check.workspace": false,
|
"rust-analyzer.check.workspace": false,
|
||||||
// "rust-analyzer.check.extraArgs": [
|
|
||||||
// "--features",
|
|
||||||
// "hot_reload"
|
|
||||||
// ],
|
|
||||||
"rust-analyzer.cargo.features": "all"
|
"rust-analyzer.cargo.features": "all"
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ dioxus-ssr = { workspace = true, optional = true }
|
||||||
dioxus-isrg = { workspace = true, optional = true }
|
dioxus-isrg = { workspace = true, optional = true }
|
||||||
axum = { workspace = true, features = ["ws", "macros"], optional = true }
|
axum = { workspace = true, features = ["ws", "macros"], optional = true }
|
||||||
tower-http = { workspace = true, features = ["fs"], optional = true }
|
tower-http = { workspace = true, features = ["fs"], optional = true }
|
||||||
dioxus-hot-reload = { workspace = true, features = ["serve"], optional = true }
|
dioxus-devtools = { workspace = true, optional = true }
|
||||||
dioxus-cli-config = { workspace = true, features = ["read-config"], optional = true }
|
dioxus-cli-config = { workspace = true, optional = true }
|
||||||
dioxus-web = { workspace = true, features = ["hydrate"], optional = true }
|
dioxus-web = { workspace = true, features = ["hydrate"], optional = true }
|
||||||
tokio = { workspace = true, optional = true }
|
tokio = { workspace = true, optional = true }
|
||||||
http = { workspace = true, optional = true }
|
http = { workspace = true, optional = true }
|
||||||
|
@ -32,7 +32,7 @@ criterion = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
server = ["dioxus-fullstack/server", "dioxus-router/ssr", "dep:dioxus-ssr", "dep:tokio", "dep:http", "dep:axum", "dep:tower-http", "dep:dioxus-hot-reload", "dep:dioxus-cli-config", "dep:tower", "dep:dioxus-isrg"]
|
server = ["dioxus-fullstack/server", "dioxus-router/ssr", "dep:dioxus-ssr", "dep:tokio", "dep:http", "dep:axum", "dep:tower-http", "dep:dioxus-devtools", "dep:dioxus-cli-config", "dep:tower", "dep:dioxus-isrg"]
|
||||||
web = ["dioxus-fullstack/web", "dioxus-router/web", "dep:dioxus-web"]
|
web = ["dioxus-fullstack/web", "dioxus-router/web", "dep:dioxus-web"]
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
|
|
@ -41,19 +41,12 @@ pub fn launch(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Serve the program if we are running with cargo
|
// Serve the program if we are running with cargo
|
||||||
if std::env::var_os("CARGO").is_some() || std::env::var_os("DIOXUS_ACTIVE").is_some() {
|
if std::env::var_os("CARGO").is_some() || dioxus_cli_config::is_cli_enabled() {
|
||||||
// Get the address the server should run on. If the CLI is running, the CLI proxies static generation into the main address
|
// Get the address the server should run on. If the CLI is running, the CLI proxies static generation into the main address
|
||||||
// and we use the generated address the CLI gives us
|
// and we use the generated address the CLI gives us
|
||||||
let cli_args = dioxus_cli_config::RuntimeCLIArguments::from_cli();
|
let serve_address = dioxus_cli_config::fullstack_address_or_localhost();
|
||||||
let address = cli_args
|
|
||||||
.as_ref()
|
|
||||||
.map(|args| args.fullstack_address().address())
|
|
||||||
.unwrap_or_else(|| std::net::SocketAddr::from(([127, 0, 0, 1], 8080)));
|
|
||||||
|
|
||||||
// Point the user to the CLI address if the CLI is running or the fullstack address if not
|
// Point the user to the CLI address if the CLI is running or the fullstack address if not
|
||||||
let serve_address = cli_args
|
|
||||||
.map(|args| args.cli_address())
|
|
||||||
.unwrap_or_else(|| address);
|
|
||||||
println!(
|
println!(
|
||||||
"Serving static files from {} at http://{serve_address}",
|
"Serving static files from {} at http://{serve_address}",
|
||||||
path.display()
|
path.display()
|
||||||
|
@ -77,7 +70,7 @@ pub fn launch(
|
||||||
})))
|
})))
|
||||||
};
|
};
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind(address).await.unwrap();
|
let listener = tokio::net::TcpListener::bind(serve_address).await.unwrap();
|
||||||
axum::serve(listener, router.into_make_service())
|
axum::serve(listener, router.into_make_service())
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -65,10 +65,7 @@ pub async fn generate_static_site(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy over the web output dir into the static output dir
|
// Copy over the web output dir into the static output dir
|
||||||
let assets_path = dioxus_cli_config::CURRENT_CONFIG
|
let assets_path = dioxus_cli_config::out_dir().unwrap_or("./dist".into());
|
||||||
.as_ref()
|
|
||||||
.map(|c| c.application.out_dir.clone())
|
|
||||||
.unwrap_or("./dist".into());
|
|
||||||
|
|
||||||
let assets_path = assets_path.join("public");
|
let assets_path = assets_path.join("public");
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ keywords = ["dom", "ui", "gui", "react", "wasm"]
|
||||||
dioxus-core = { workspace = true }
|
dioxus-core = { workspace = true }
|
||||||
dioxus-core-types = { workspace = true }
|
dioxus-core-types = { workspace = true }
|
||||||
dioxus-html = { workspace = true, features = ["wasm-bind"] }
|
dioxus-html = { workspace = true, features = ["wasm-bind"] }
|
||||||
dioxus-hot-reload = { workspace = true, features = ["client"] }
|
dioxus-devtools = { workspace = true }
|
||||||
dioxus-signals = { workspace = true }
|
dioxus-signals = { workspace = true }
|
||||||
dioxus-interpreter-js = { workspace = true, features = [
|
dioxus-interpreter-js = { workspace = true, features = [
|
||||||
"minimal_bindings",
|
"minimal_bindings",
|
||||||
|
@ -59,14 +59,14 @@ features = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["panic_hook", "mounted", "file_engine", "hot_reload", "document"]
|
default = ["panic_hook", "mounted", "file_engine", "devtools", "document"]
|
||||||
panic_hook = ["dep:console_error_panic_hook"]
|
panic_hook = ["dep:console_error_panic_hook"]
|
||||||
hydrate = ["web-sys/Comment", "ciborium", "dep:serde"]
|
hydrate = ["web-sys/Comment", "ciborium", "dep:serde"]
|
||||||
mounted = ["web-sys/Element", "dioxus-html/mounted"]
|
mounted = ["web-sys/Element", "dioxus-html/mounted"]
|
||||||
file_engine = [
|
file_engine = [
|
||||||
"dioxus-html/file-engine",
|
"dioxus-html/file-engine",
|
||||||
]
|
]
|
||||||
hot_reload = ["web-sys/MessageEvent", "web-sys/WebSocket", "web-sys/Location", "dep:serde_json", "dep:serde", "dioxus-core/serialize"]
|
devtools = ["web-sys/MessageEvent", "web-sys/WebSocket", "web-sys/Location", "dep:serde_json", "dep:serde", "dioxus-core/serialize"]
|
||||||
document = ["dioxus-html/document", "dep:serde-wasm-bindgen", "dep:serde_json", "dep:serde"]
|
document = ["dioxus-html/document", "dep:serde-wasm-bindgen", "dep:serde_json", "dep:serde"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::fmt::Display;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use dioxus_core::ScopeId;
|
use dioxus_core::ScopeId;
|
||||||
use dioxus_hot_reload::{DevserverMsg, HotReloadMsg};
|
use dioxus_devtools::{DevserverMsg, HotReloadMsg};
|
||||||
use dioxus_html::prelude::eval;
|
use dioxus_html::prelude::eval;
|
||||||
use futures_channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
|
use futures_channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender};
|
||||||
use js_sys::JsString;
|
use js_sys::JsString;
|
|
@ -39,8 +39,8 @@ mod document;
|
||||||
#[cfg(feature = "document")]
|
#[cfg(feature = "document")]
|
||||||
pub use document::WebDocument;
|
pub use document::WebDocument;
|
||||||
|
|
||||||
#[cfg(all(feature = "hot_reload", debug_assertions))]
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
mod hot_reload;
|
mod devtools;
|
||||||
|
|
||||||
mod hydration;
|
mod hydration;
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -67,8 +67,8 @@ pub async fn run(mut virtual_dom: VirtualDom, web_config: Config) -> ! {
|
||||||
console_error_panic_hook::set_once();
|
console_error_panic_hook::set_once();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "hot_reload", debug_assertions))]
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
let mut hotreload_rx = hot_reload::init();
|
let mut hotreload_rx = devtools::init();
|
||||||
|
|
||||||
let runtime = virtual_dom.runtime();
|
let runtime = virtual_dom.runtime();
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ pub async fn run(mut virtual_dom: VirtualDom, web_config: Config) -> ! {
|
||||||
loop {
|
loop {
|
||||||
// if virtual dom has nothing, wait for it to have something before requesting idle time
|
// if virtual dom has nothing, wait for it to have something before requesting idle time
|
||||||
// if there is work then this future resolves immediately.
|
// if there is work then this future resolves immediately.
|
||||||
#[cfg(all(feature = "hot_reload", debug_assertions))]
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
let template;
|
let template;
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
let mut hydration_work: Option<SuspenseMessage> = None;
|
let mut hydration_work: Option<SuspenseMessage> = None;
|
||||||
|
@ -137,15 +137,15 @@ pub async fn run(mut virtual_dom: VirtualDom, web_config: Config) -> ! {
|
||||||
.flatten();
|
.flatten();
|
||||||
let mut rx_hydration = hydration_receiver_iter.select_next_some();
|
let mut rx_hydration = hydration_receiver_iter.select_next_some();
|
||||||
|
|
||||||
#[cfg(all(feature = "hot_reload", debug_assertions))]
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
{
|
{
|
||||||
let mut hot_reload_next = hotreload_rx.select_next_some();
|
let mut devtools_next = hotreload_rx.select_next_some();
|
||||||
select! {
|
select! {
|
||||||
_ = work => {
|
_ = work => {
|
||||||
template = None;
|
template = None;
|
||||||
},
|
},
|
||||||
new_template = hot_reload_next => {
|
new_template = devtools_next => {
|
||||||
template = Some(new_template);
|
template = Some(new_template);
|
||||||
},
|
},
|
||||||
hydration_data = rx_hydration => {
|
hydration_data = rx_hydration => {
|
||||||
|
@ -158,7 +158,7 @@ pub async fn run(mut virtual_dom: VirtualDom, web_config: Config) -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(all(feature = "hot_reload", debug_assertions)))]
|
#[cfg(not(all(feature = "devtools", debug_assertions)))]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
{
|
{
|
||||||
select! {
|
select! {
|
||||||
|
@ -173,13 +173,13 @@ pub async fn run(mut virtual_dom: VirtualDom, web_config: Config) -> ! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "hot_reload", debug_assertions))]
|
#[cfg(all(feature = "devtools", debug_assertions))]
|
||||||
if let Some(hr_msg) = template {
|
if let Some(hr_msg) = template {
|
||||||
// Replace all templates
|
// Replace all templates
|
||||||
dioxus_hot_reload::apply_changes(&mut virtual_dom, &hr_msg);
|
dioxus_devtools::apply_changes(&virtual_dom, &hr_msg);
|
||||||
|
|
||||||
if !hr_msg.assets.is_empty() {
|
if !hr_msg.assets.is_empty() {
|
||||||
crate::hot_reload::invalidate_browser_asset_cache();
|
crate::devtools::invalidate_browser_asset_cache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue