#[command]Expand description
Re-export the #[command] attribute macro from conduit-derive.
This is conduit’s equivalent of #[tauri::command]. Use it for
named-parameter handlers:
ⓘ
use tauri_conduit::{command, handler};
#[command]
fn greet(name: String, greeting: String) -> String {
format!("{greeting}, {name}!")
}Attribute macro that transforms a function into a conduit command handler.
Preserves the original function and generates a hidden handler struct
(__conduit_handler_{fn_name}) implementing [conduit_core::ConduitHandler].
Use handler! to obtain the handler struct for registration.
This is conduit’s 1:1 equivalent of #[tauri::command]. The macro supports:
- Named parameters — generates a hidden args struct with
#[derive(Deserialize)]and#[serde(rename_all = "camelCase")]. Rust snake_case parameters are automatically converted to camelCase in JSON, matching#[tauri::command]behavior. State<T>injection — parameters whose type path ends inStateare extracted from the context (which must be anAppHandle<Wry>).AppHandleinjection — parameters whose type path ends inAppHandle.Window/WebviewWindowinjection — parameters whose type path ends inWindoworWebviewWindow, resolved viaapp_handle.get_webview_window(label).Webviewinjection — parameters whose type path ends inWebview, resolved viaapp_handle.get_webview(label).Result<T, E>returns — errors are converted viaDisplayintoconduit_core::Error::Handler.asyncfunctions — truly async, spawned on the tokio runtime (notblock_on).
§Examples
ⓘ
use tauri_conduit::command;
// Named parameters — frontend sends { "name": "Alice", "greeting": "Hi" }
#[command]
fn greet(name: String, greeting: String) -> String {
format!("{greeting}, {name}!")
}
// Result return — errors become conduit_core::Error::Handler
#[command]
fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 { Err("division by zero".into()) }
else { Ok(a / b) }
}
// State injection + async + Result
#[command]
async fn fetch_user(state: State<'_, Db>, id: u64) -> Result<User, String> {
state.get_user(id).await.map_err(|e| e.to_string())
}§Error handling
When a Result-returning handler returns Err(e), the error’s
Display text is sent to the frontend as a JSON error response.
This matches #[tauri::command] behavior. Be careful about what
information your error types expose via Display.
§Limitations
tauri::Wryonly: Generated handlers assumetauri::Wryas the runtime backend. This is the default (and typically only) runtime in Tauri v2.- Multiple
State<T>params: EachState<T>must use a distinct concrete typeT. Tauri’s state system is keyed byTypeId, so two params with the sameTwill receive the same instance. - Name-based injection detection:
State,AppHandle,Window,WebviewWindow, andWebvieware identified by the last path segment of the type. Any user type with these names will be misinterpreted as a Tauri injectable type. Rename your types to avoid false matches. - Name-based Result detection: The return type is detected as
Resultby checking the last path segment. Type aliases liketype MyResult<T> = Result<T, E>are NOT detected as Result returns and will be serialized directly instead of unwrappingOk/Err. - Window/Webview require label:
WindowandWebviewinjection requires the frontend to send theX-Conduit-Webviewheader (handled automatically by the TS client). If no label is available, the handler returns an error. - No
implblock support: The macro generates struct definitions at the call site, which is illegal insideimplblocks. Only use#[command]on free-standing functions.