feat: document and re-export dioxus-cli-config (#3515)

* feat: document and re-export dioxus-cli-config
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2025-01-07 15:39:14 -08:00
1 parent d75cb59491
commit bb3fd38231
7 files changed
+176 -29

No files matched your search

Generated
+1
View File
@@ -5021,6 +5021,7 @@ dependencies = [
"axum_session", "axum_session",
"axum_session_auth", "axum_session_auth",
"dioxus", "dioxus",
"dioxus-cli-config",
"dioxus-fullstack", "dioxus-fullstack",
"dioxus-web", "dioxus-web",
"execute", "execute",
+2 -2
View File
@@ -63,8 +63,8 @@ fn main() {
) )
.layer(axum_session::SessionLayer::new(session_store)); .layer(axum_session::SessionLayer::new(session_store));
// run it // serve the app using the address passed by the CLI
let addr = dioxus_cli_config::fullstack_address_or_localhost(); let addr = dioxus::cli_config::fullstack_address_or_localhost();
let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
axum::serve(listener, app.into_make_service()) axum::serve(listener, app.into_make_service())
+159 -18
View File
@@ -1,3 +1,56 @@
//! <div align="center">
//! <img
//! src="https://github.com/user-attachments/assets/6c7e227e-44ff-4e53-824a-67949051149c"
//! alt="Build web, desktop, and mobile apps with a single codebase."
//! width="100%"
//! class="darkmode-image"
//! >
//! </div>
//!
//! # Dioxus CLI configuration
//!
//! This crate exposes the various configuration options that the Dioxus CLI sets when running the
//! application during development.
//!
//! Note that these functions will return a different value when running under the CLI, so make sure
//! not to rely on them when running in a production environment.
//!
//! ## Constants
//!
//! The various constants here are the names of the environment variables that the CLI sets. We recommend
//! using the functions in this crate to access the values of these environment variables indirectly.
//!
//! The CLI uses this crate and the associated constants to *set* the environment variables, but as
//! a consumer of the CLI, you would want to read the values of these environment variables using
//! the provided functions.
//!
//! ## Example Usage
//!
//! We recommend using the functions here to access the values of the environment variables set by the CLI.
//! For example, you might use the [`fullstack_address_or_localhost`] function to get the address that
//! the CLI is requesting the application to be served on.
//!
//! ```rust, ignore
//! async fn launch_axum(app: axum::Router<()>) {
//! // Read the PORT and ADDR environment variables set by the CLI
//! let addr = dioxus_cli_config::fullstack_address_or_localhost();
//!
//! // Bind to the address and serve the application
//! let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
//! axum::serve(listener, app.into_make_service())
//! .await
//! .unwrap();
//! }
//! ```
//!
//! ## Stability
//!
//! The *values* that these functions return are *not* guaranteed to be stable between patch releases
//! of Dioxus. At any time, we might change the values that the CLI sets or the way that they are read.
//!
//! We also don't guarantee the stability of the env var names themselves. If you want to rely on a
//! particular env var, use the defined constants in your code.
use std::{ use std::{
net::{IpAddr, Ipv4Addr, SocketAddr}, net::{IpAddr, Ipv4Addr, SocketAddr},
path::PathBuf, path::PathBuf,
@@ -10,6 +63,9 @@ pub const DEVSERVER_RAW_ADDR_ENV: &str = "DIOXUS_DEVSERVER_ADDR";
pub const ALWAYS_ON_TOP_ENV: &str = "DIOXUS_ALWAYS_ON_TOP"; pub const ALWAYS_ON_TOP_ENV: &str = "DIOXUS_ALWAYS_ON_TOP";
pub const ASSET_ROOT_ENV: &str = "DIOXUS_ASSET_ROOT"; pub const ASSET_ROOT_ENV: &str = "DIOXUS_ASSET_ROOT";
pub const APP_TITLE_ENV: &str = "DIOXUS_APP_TITLE"; pub const APP_TITLE_ENV: &str = "DIOXUS_APP_TITLE";
#[deprecated(since = "0.6.0", note = "The CLI currently does not set this.")]
#[doc(hidden)]
pub const OUT_DIR: &str = "DIOXUS_OUT_DIR"; pub const OUT_DIR: &str = "DIOXUS_OUT_DIR";
/// Reads an environment variable at runtime in debug mode or at compile time in /// Reads an environment variable at runtime in debug mode or at compile time in
@@ -37,7 +93,11 @@ macro_rules! read_env_config {
/// Get the address of the devserver for use over a raw socket /// Get the address of the devserver for use over a raw socket
/// ///
/// This is not a websocket! There's no protocol! /// This returns a [`SocketAddr`], meaning that you still need to connect to it using a socket with
/// the appropriate protocol and path.
///
/// For reference, the devserver typically lives on `127.0.0.1:8080` and serves the devserver websocket
/// on `127.0.0.1:8080/_dioxus`.
pub fn devserver_raw_addr() -> Option<SocketAddr> { pub fn devserver_raw_addr() -> Option<SocketAddr> {
// On android, 10.0.2.2 is the default loopback // On android, 10.0.2.2 is the default loopback
if cfg!(target_os = "android") { if cfg!(target_os = "android") {
@@ -50,59 +110,110 @@ pub fn devserver_raw_addr() -> Option<SocketAddr> {
.flatten() .flatten()
} }
/// Get the address of the devserver for use over a websocket
///
/// This is meant for internal use, though if you are building devtools around Dioxus, this would be
/// useful to connect as a "listener" to the devserver.
///
/// Unlike [`devserver_raw_addr`], this returns a string that can be used directly to connect to the
/// devserver over a websocket. IE `ws://127.0.0.1:8080/_dioxus`.
pub fn devserver_ws_endpoint() -> Option<String> { pub fn devserver_ws_endpoint() -> Option<String> {
let addr = devserver_raw_addr()?; let addr = devserver_raw_addr()?;
Some(format!("ws://{addr}/_dioxus")) Some(format!("ws://{addr}/_dioxus"))
} }
/// Get the IP that the server should be bound to.
///
/// This is set by the CLI and is used to bind the server to a specific address.
/// You can manually set the ip by setting the `IP` environment variable.
///
/// ```sh
/// IP=0.0.0.0 ./server
/// ```
pub fn server_ip() -> Option<IpAddr> { pub fn server_ip() -> Option<IpAddr> {
std::env::var(SERVER_IP_ENV) std::env::var(SERVER_IP_ENV)
.ok() .ok()
.and_then(|s| s.parse().ok()) .and_then(|s| s.parse().ok())
} }
/// Get the port that the server should listen on.
///
/// This is set by the CLI and is used to bind the server to a specific port.
/// You can manually set the port by setting the `PORT` environment variable.
///
/// ```sh
/// PORT=8081 ./server
/// ```
pub fn server_port() -> Option<u16> { pub fn server_port() -> Option<u16> {
std::env::var(SERVER_PORT_ENV) std::env::var(SERVER_PORT_ENV)
.ok() .ok()
.and_then(|s| s.parse().ok()) .and_then(|s| s.parse().ok())
} }
/// Get the full address that the server should listen on.
///
/// This is a convenience function that combines the `server_ip` and `server_port` functions and then
/// falls back to `localhost:8080` if the environment variables are not set.
///
/// ## Example
///
/// ```rust, ignore
/// async fn launch_axum(app: axum::Router<()>) {
/// // Read the PORT and ADDR environment variables set by the CLI
/// let addr = dioxus_cli_config::fullstack_address_or_localhost();
///
/// // Bind to the address and serve the application
/// let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
/// axum::serve(listener, app.into_make_service())
/// .await
/// .unwrap();
/// }
/// ```
///
/// ## Stability
///
/// In the future, we might change the address from 127.0.0.1 to 0.0.0.0.
pub fn fullstack_address_or_localhost() -> SocketAddr { pub fn fullstack_address_or_localhost() -> SocketAddr {
let ip = server_ip().unwrap_or_else(|| IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1))); let ip = server_ip().unwrap_or_else(|| IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
let port = server_port().unwrap_or(8080); let port = server_port().unwrap_or(8080);
SocketAddr::new(ip, port) SocketAddr::new(ip, port)
} }
/// Get the title of the application, usually set by the Dioxus.toml.
///
/// This is used to set the title of the desktop window if the app itself doesn't set it.
pub fn app_title() -> Option<String> { pub fn app_title() -> Option<String> {
read_env_config!("DIOXUS_APP_TITLE") read_env_config!("DIOXUS_APP_TITLE")
} }
/// Check if the application should forced to "float" on top of other windows.
///
/// The CLI sets this based on the `--always-on-top` flag and the settings system.
pub fn always_on_top() -> Option<bool> { pub fn always_on_top() -> Option<bool> {
std::env::var(ALWAYS_ON_TOP_ENV) std::env::var(ALWAYS_ON_TOP_ENV)
.ok() .ok()
.and_then(|s| s.parse().ok()) .and_then(|s| s.parse().ok())
} }
/// Check if the CLI is enabled when running the application.
///
/// The CLI *always* sets this value to true when running the application.
///
/// ## Note
///
/// On Android and the Web, this *might* not be reliable since there isn't always a consistent way to
/// pass off the CLI environment variables to the application.
pub fn is_cli_enabled() -> bool { pub fn is_cli_enabled() -> bool {
// todo: (jon) - on android and web we should fix this...
std::env::var(CLI_ENABLED_ENV).is_ok() std::env::var(CLI_ENABLED_ENV).is_ok()
} }
#[cfg(feature = "web")] /// Get the path where the application will be served from.
#[wasm_bindgen::prelude::wasm_bindgen(inline_js = r#" ///
export function getMetaContents(meta_name) { /// This is used by the router to format the URLs. For example, an app with a base path of `dogapp` will
const selector = document.querySelector(`meta[name="${meta_name}"]`); /// be served at `http://localhost:8080/dogapp`.
if (!selector) { ///
return null; /// All assets will be served from this base path as well, ie `http://localhost:8080/dogapp/assets/logo.png`.
}
return selector.content;
}
"#)]
extern "C" {
#[wasm_bindgen(js_name = getMetaContents)]
pub fn get_meta_contents(selector: &str) -> Option<String>;
}
/// Get the path where the application will be served from. This is used by the router to format the URLs.
pub fn base_path() -> Option<String> { pub fn base_path() -> Option<String> {
// This may trigger when compiling to the server if you depend on another crate that pulls in // This may trigger when compiling to the server if you depend on another crate that pulls in
// the web feature. It might be better for the renderers to provide the current platform // the web feature. It might be better for the renderers to provide the current platform
@@ -115,7 +226,24 @@ pub fn base_path() -> Option<String> {
read_env_config!("DIOXUS_ASSET_ROOT") read_env_config!("DIOXUS_ASSET_ROOT")
} }
#[cfg(feature = "web")]
#[wasm_bindgen::prelude::wasm_bindgen(inline_js = r#"
export function getMetaContents(meta_name) {
const selector = document.querySelector(`meta[name="${meta_name}"]`);
if (!selector) {
return null;
}
return selector.content;
}
"#)]
extern "C" {
#[wasm_bindgen(js_name = getMetaContents)]
pub fn get_meta_contents(selector: &str) -> Option<String>;
}
/// Get the path where the application is served from in the browser. /// Get the path where the application is served from in the browser.
///
/// This uses wasm_bindgen on the browser to extract the base path from a meta element.
#[cfg(feature = "web")] #[cfg(feature = "web")]
pub fn web_base_path() -> Option<String> { pub fn web_base_path() -> Option<String> {
// In debug mode, we get the base path from the meta element which can be hot reloaded and changed without recompiling // In debug mode, we get the base path from the meta element which can be hot reloaded and changed without recompiling
@@ -134,10 +262,23 @@ pub fn web_base_path() -> Option<String> {
} }
} }
/// Format a meta element for the base path to be used in the output HTML
#[doc(hidden)]
pub fn format_base_path_meta_element(base_path: &str) -> String { pub fn format_base_path_meta_element(base_path: &str) -> String {
format!(r#"<meta name="{ASSET_ROOT_ENV}" content="{base_path}">"#,) format!(r#"<meta name="{ASSET_ROOT_ENV}" content="{base_path}">"#,)
} }
/// Get the path to the output directory where the application is being built.
///
/// This might not return a valid path - we don't recommend relying on this.
#[doc(hidden)]
#[deprecated(
since = "0.6.0",
note = "The does not set the OUT_DIR environment variable."
)]
pub fn out_dir() -> Option<PathBuf> { pub fn out_dir() -> Option<PathBuf> {
std::env::var(OUT_DIR).ok().map(PathBuf::from) #[allow(deprecated)]
{
std::env::var(OUT_DIR).ok().map(PathBuf::from)
}
} }
+3 -2
View File
@@ -37,7 +37,7 @@ dioxus-cli-config = { workspace = true, optional = true }
dioxus-devtools = { workspace = true, optional = true } dioxus-devtools = { workspace = true, optional = true }
[features] [features]
default = ["macro", "html", "signals", "hooks", "launch", "mounted", "file_engine", "document", "asset", "devtools", "logger", "warnings"] default = ["macro", "html", "signals", "hooks", "launch", "mounted", "file_engine", "document", "asset", "devtools", "logger", "warnings", "cli-config"]
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"]
@@ -49,6 +49,7 @@ file_engine = ["dioxus-web?/file_engine"]
asset = ["dep:manganis"] asset = ["dep:manganis"]
document = ["dioxus-web?/document", "dep:dioxus-document", "dep:dioxus-history"] document = ["dioxus-web?/document", "dep:dioxus-document", "dep:dioxus-history"]
logger = ["dep:dioxus-logger"] logger = ["dep:dioxus-logger"]
cli-config = ["dep:dioxus-cli-config"]
warnings = ["dep:warnings"] warnings = ["dep:warnings"]
launch = ["dep:dioxus-config-macro"] launch = ["dep:dioxus-config-macro"]
@@ -58,7 +59,7 @@ router = ["dep:dioxus-router"]
fullstack = ["dep:dioxus-fullstack", "dioxus-config-macro/fullstack", "dep:serde"] fullstack = ["dep:dioxus-fullstack", "dioxus-config-macro/fullstack", "dep:serde"]
desktop = ["dep:dioxus-desktop", "dioxus-fullstack?/desktop", "dioxus-config-macro/desktop"] desktop = ["dep:dioxus-desktop", "dioxus-fullstack?/desktop", "dioxus-config-macro/desktop"]
mobile = ["dep:dioxus-mobile", "dioxus-fullstack?/mobile", "dioxus-config-macro/mobile"] mobile = ["dep:dioxus-mobile", "dioxus-fullstack?/mobile", "dioxus-config-macro/mobile"]
web = ["dep:dioxus-web", "dioxus-fullstack?/web", "dioxus-config-macro/web", "dioxus-cli-config", "dioxus-cli-config/web"] web = ["dep:dioxus-web", "dioxus-fullstack?/web", "dioxus-config-macro/web", "dep:dioxus-cli-config", "dioxus-cli-config?/web"]
ssr = ["dep:dioxus-ssr", "dioxus-config-macro/ssr"] ssr = ["dep:dioxus-ssr", "dioxus-config-macro/ssr"]
liveview = ["dep:dioxus-liveview", "dioxus-config-macro/liveview"] liveview = ["dep:dioxus-liveview", "dioxus-config-macro/liveview"]
server = ["dioxus-fullstack?/axum", "dioxus-fullstack?/server", "ssr", "dioxus-liveview?/axum"] server = ["dioxus-fullstack?/axum", "dioxus-fullstack?/server", "ssr", "dioxus-liveview?/axum"]
+4
View File
@@ -70,6 +70,10 @@ pub use dioxus_core_macro as core_macro;
#[cfg_attr(docsrs, doc(cfg(feature = "logger")))] #[cfg_attr(docsrs, doc(cfg(feature = "logger")))]
pub use dioxus_logger as logger; pub use dioxus_logger as logger;
#[cfg(feature = "cli-config")]
#[cfg_attr(docsrs, doc(cfg(feature = "cli-config")))]
pub use dioxus_cli_config as cli_config;
pub mod prelude { pub mod prelude {
#[cfg(feature = "document")] #[cfg(feature = "document")]
#[cfg_attr(docsrs, doc(cfg(feature = "document")))] #[cfg_attr(docsrs, doc(cfg(feature = "document")))]
+1 -1
View File
@@ -93,7 +93,7 @@ use dioxus::prelude::*;
async fn main() { async fn main() {
// 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 address = dioxus_cli_config::fullstack_address_or_localhost(); let address = dioxus::cli_config::fullstack_address_or_localhost();
// Set up the axum router // Set up the axum router
let router = axum::Router::new() let router = axum::Router::new()
+6 -6
View File
@@ -16,7 +16,7 @@
//! .block_on(async move { //! .block_on(async move {
//! // 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 address = dioxus_cli_config::fullstack_address_or_localhost(); //! let address = dioxus::cli_config::fullstack_address_or_localhost();
//! let listener = tokio::net::TcpListener::bind(address) //! let listener = tokio::net::TcpListener::bind(address)
//! .await //! .await
//! .unwrap(); //! .unwrap();
@@ -85,7 +85,7 @@ pub trait DioxusRouterExt<S> {
/// # use dioxus_fullstack::prelude::*; /// # use dioxus_fullstack::prelude::*;
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let addr = dioxus_cli_config::fullstack_address_or_localhost(); /// let addr = dioxus::cli_config::fullstack_address_or_localhost();
/// let router = axum::Router::new() /// let router = axum::Router::new()
/// // Register server functions routes with the default handler /// // Register server functions routes with the default handler
/// .register_server_functions() /// .register_server_functions()
@@ -110,7 +110,7 @@ pub trait DioxusRouterExt<S> {
/// # use std::sync::Arc; /// # use std::sync::Arc;
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let addr = dioxus_cli_config::fullstack_address_or_localhost(); /// let addr = dioxus::cli_config::fullstack_address_or_localhost();
/// let router = axum::Router::new() /// let router = axum::Router::new()
/// // Register server functions routes with the default handler /// // Register server functions routes with the default handler
/// .register_server_functions_with_context(Arc::new(vec![Box::new(|| Box::new(1234567890u32))])) /// .register_server_functions_with_context(Arc::new(vec![Box::new(|| Box::new(1234567890u32))]))
@@ -130,7 +130,7 @@ pub trait DioxusRouterExt<S> {
/// # use dioxus_fullstack::prelude::*; /// # use dioxus_fullstack::prelude::*;
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let addr = dioxus_cli_config::fullstack_address_or_localhost(); /// let addr = dioxus::cli_config::fullstack_address_or_localhost();
/// let router = axum::Router::new() /// let router = axum::Router::new()
/// // Server side render the application, serve static assets, and register server functions /// // Server side render the application, serve static assets, and register server functions
/// .serve_static_assets() /// .serve_static_assets()
@@ -155,7 +155,7 @@ pub trait DioxusRouterExt<S> {
/// # use dioxus_fullstack::prelude::*; /// # use dioxus_fullstack::prelude::*;
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let addr = dioxus_cli_config::fullstack_address_or_localhost(); /// let addr = dioxus::cli_config::fullstack_address_or_localhost();
/// let router = axum::Router::new() /// let router = axum::Router::new()
/// // Server side render the application, serve static assets, and register server functions /// // Server side render the application, serve static assets, and register server functions
/// .serve_dioxus_application(ServeConfig::new().unwrap(), app) /// .serve_dioxus_application(ServeConfig::new().unwrap(), app)
@@ -361,7 +361,7 @@ impl RenderHandleState {
/// ///
/// #[tokio::main] /// #[tokio::main]
/// async fn main() { /// async fn main() {
/// let addr = dioxus_cli_config::fullstack_address_or_localhost(); /// let addr = dioxus::cli_config::fullstack_address_or_localhost();
/// let router = axum::Router::new() /// let router = axum::Router::new()
/// // Register server functions, etc. /// // Register server functions, etc.
/// // Note you can use `register_server_functions_with_context` /// // Note you can use `register_server_functions_with_context`