Răsfoiți Sursa

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

* feat: document and re-export dioxus-cli-config
Jonathan Kelley 5 luni în urmă
părinte
comite
bb3fd38231

+ 1 - 0
Cargo.lock

@@ -5021,6 +5021,7 @@ dependencies = [
  "axum_session",
  "axum_session_auth",
  "dioxus",
+ "dioxus-cli-config",
  "dioxus-fullstack",
  "dioxus-web",
  "execute",

+ 2 - 2
examples/fullstack-auth/src/main.rs

@@ -63,8 +63,8 @@ fn main() {
                     )
                     .layer(axum_session::SessionLayer::new(session_store));
 
-                // run it
-                let addr = dioxus_cli_config::fullstack_address_or_localhost();
+                // serve the app using the address passed by the CLI
+                let addr = dioxus::cli_config::fullstack_address_or_localhost();
                 let listener = tokio::net::TcpListener::bind(&addr).await.unwrap();
 
                 axum::serve(listener, app.into_make_service())

+ 159 - 18
packages/cli-config/src/lib.rs

@@ -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::{
     net::{IpAddr, Ipv4Addr, SocketAddr},
     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 ASSET_ROOT_ENV: &str = "DIOXUS_ASSET_ROOT";
 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";
 
 /// 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
 ///
-/// 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> {
     // On android, 10.0.2.2 is the default loopback
     if cfg!(target_os = "android") {
@@ -50,59 +110,110 @@ pub fn devserver_raw_addr() -> Option<SocketAddr> {
         .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> {
     let addr = devserver_raw_addr()?;
     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> {
     std::env::var(SERVER_IP_ENV)
         .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> {
     std::env::var(SERVER_PORT_ENV)
         .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 {
     let ip = server_ip().unwrap_or_else(|| IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
     let port = server_port().unwrap_or(8080);
     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> {
     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> {
     std::env::var(ALWAYS_ON_TOP_ENV)
         .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 {
+    // todo: (jon) - on android and web we should fix this...
     std::env::var(CLI_ENABLED_ENV).is_ok()
 }
 
-#[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 will be served from. This is used by the router to format the URLs.
+/// Get the path where the application will be served from.
+///
+/// This is used by the router to format the URLs. For example, an app with a base path of `dogapp` will
+/// be served at `http://localhost:8080/dogapp`.
+///
+/// All assets will be served from this base path as well, ie `http://localhost:8080/dogapp/assets/logo.png`.
 pub fn base_path() -> Option<String> {
     // 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
@@ -115,7 +226,24 @@ pub fn base_path() -> Option<String> {
     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.
+///
+/// This uses wasm_bindgen on the browser to extract the base path from a meta element.
 #[cfg(feature = "web")]
 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
@@ -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 {
     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> {
-    std::env::var(OUT_DIR).ok().map(PathBuf::from)
+    #[allow(deprecated)]
+    {
+        std::env::var(OUT_DIR).ok().map(PathBuf::from)
+    }
 }

+ 3 - 2
packages/dioxus/Cargo.toml

@@ -37,7 +37,7 @@ dioxus-cli-config = { workspace = true, optional = true }
 dioxus-devtools = { workspace = true, optional = true }
 
 [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"]
 signals = ["dep:dioxus-signals"]
 macro = ["dep:dioxus-core-macro"]
@@ -49,6 +49,7 @@ file_engine = ["dioxus-web?/file_engine"]
 asset = ["dep:manganis"]
 document = ["dioxus-web?/document", "dep:dioxus-document", "dep:dioxus-history"]
 logger = ["dep:dioxus-logger"]
+cli-config = ["dep:dioxus-cli-config"]
 warnings = ["dep:warnings"]
 
 launch = ["dep:dioxus-config-macro"]
@@ -58,7 +59,7 @@ router = ["dep:dioxus-router"]
 fullstack = ["dep:dioxus-fullstack", "dioxus-config-macro/fullstack", "dep:serde"]
 desktop = ["dep:dioxus-desktop", "dioxus-fullstack?/desktop", "dioxus-config-macro/desktop"]
 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"]
 liveview = ["dep:dioxus-liveview", "dioxus-config-macro/liveview"]
 server = ["dioxus-fullstack?/axum", "dioxus-fullstack?/server", "ssr", "dioxus-liveview?/axum"]

+ 4 - 0
packages/dioxus/src/lib.rs

@@ -70,6 +70,10 @@ pub use dioxus_core_macro as core_macro;
 #[cfg_attr(docsrs, doc(cfg(feature = "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 {
     #[cfg(feature = "document")]
     #[cfg_attr(docsrs, doc(cfg(feature = "document")))]

+ 1 - 1
packages/fullstack/README.md

@@ -93,7 +93,7 @@ use dioxus::prelude::*;
 async fn main() {
     // 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
-    let address = dioxus_cli_config::fullstack_address_or_localhost();
+    let address = dioxus::cli_config::fullstack_address_or_localhost();
 
     // Set up the axum router
     let router = axum::Router::new()

+ 6 - 6
packages/fullstack/src/server/mod.rs

@@ -16,7 +16,7 @@
 //!             .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
 //!                 // 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)
 //!                     .await
 //!                     .unwrap();
@@ -85,7 +85,7 @@ pub trait DioxusRouterExt<S> {
     /// # use dioxus_fullstack::prelude::*;
     /// #[tokio::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()
     ///         // Register server functions routes with the default handler
     ///         .register_server_functions()
@@ -110,7 +110,7 @@ pub trait DioxusRouterExt<S> {
     /// # use std::sync::Arc;
     /// #[tokio::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()
     ///         // Register server functions routes with the default handler
     ///         .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::*;
     /// #[tokio::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()
     ///         // Server side render the application, serve static assets, and register server functions
     ///         .serve_static_assets()
@@ -155,7 +155,7 @@ pub trait DioxusRouterExt<S> {
     /// # use dioxus_fullstack::prelude::*;
     /// #[tokio::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()
     ///         // Server side render the application, serve static assets, and register server functions
     ///         .serve_dioxus_application(ServeConfig::new().unwrap(), app)
@@ -361,7 +361,7 @@ impl RenderHandleState {
 ///
 /// #[tokio::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()
 ///         // Register server functions, etc.
 ///         // Note you can use `register_server_functions_with_context`