Implement Into<CaptureError> for the default server function error type (#4205)

* implement Into<CaptureError> for the server function error type

* document the server function error type

* fix tests
This commit is contained in:
Evan Almloff authored and GitHub committed 2025-06-20 18:37:51 -07:00
1 parent 67f717647f
commit f610c6b8c1
20 files changed
+316 -96

No files matched your search

+1 -1
View File
@@ -196,7 +196,7 @@ pub async fn connect_to_database() -> SqlitePool {
pub type Session =
axum_session_auth::AuthSession<crate::auth::User, i64, SessionSqlitePool, sqlx::SqlitePool>;
pub async fn get_session() -> Result<Session, ServerFnError> {
pub async fn get_session() -> ServerFnResult<Session> {
extract::<Session, _>()
.await
.map_err(|_| ServerFnError::new("AuthSessionLayer was not found"))
+11 -10
View File
@@ -75,7 +75,8 @@ fn app() -> Element {
div {
button { onclick: move |_| {
async move {
login().await.unwrap();
login().await?;
Ok(())
}
},
"Login Test User"
@@ -84,9 +85,9 @@ fn app() -> Element {
div {
button {
onclick: move |_| async move {
if let Ok(data) = get_user_name().await {
user_name.set(data);
}
let data = get_user_name().await?;
user_name.set(data);
Ok(())
},
"Get User Name"
}
@@ -95,9 +96,9 @@ fn app() -> Element {
div {
button {
onclick: move |_| async move {
if let Ok(data) = get_permissions().await {
permissions.set(data);
}
let data = get_permissions().await?;
permissions.set(data);
Ok(())
},
"Get Permissions"
}
@@ -107,20 +108,20 @@ fn app() -> Element {
}
#[server]
pub async fn get_user_name() -> Result<String, ServerFnError> {
pub async fn get_user_name() -> ServerFnResult<String> {
let auth = auth::get_session().await?;
Ok(auth.current_user.unwrap().username.to_string())
}
#[server]
pub async fn login() -> Result<(), ServerFnError> {
pub async fn login() -> ServerFnResult {
let auth = auth::get_session().await?;
auth.login_user(2);
Ok(())
}
#[server]
pub async fn get_permissions() -> Result<String, ServerFnError> {
pub async fn get_permissions() -> ServerFnResult<String> {
let method: axum::http::Method = extract().await?;
let auth = auth::get_session().await?;
let current_user = auth.current_user.clone().unwrap_or_default();
+9 -9
View File
@@ -18,11 +18,11 @@ pub fn app() -> Element {
button { onclick: move |_| count -= 1, "Down low!" }
button {
onclick: move |_| async move {
if let Ok(data) = get_server_data().await {
println!("Client received: {}", data);
text.set(data.clone());
post_server_data(data).await.unwrap();
}
let data = get_server_data().await?;
println!("Client received: {}", data);
text.set(data.clone());
post_server_data(data).await?;
Ok(())
},
"Run a server function"
}
@@ -30,14 +30,14 @@ pub fn app() -> Element {
}
}
#[server(PostServerData)]
async fn post_server_data(data: String) -> Result<(), ServerFnError> {
#[server]
async fn post_server_data(data: String) -> ServerFnResult {
println!("Server received: {}", data);
Ok(())
}
#[server(GetServerData)]
async fn get_server_data() -> Result<String, ServerFnError> {
#[server]
async fn get_server_data() -> ServerFnResult<String> {
Ok("Hello from the server!".to_string())
}
+7 -7
View File
@@ -20,11 +20,11 @@ fn app() -> Element {
button { onclick: move |_| count -= 1, "Down low!" }
button {
onclick: move |_| async move {
if let Ok(data) = get_server_data().await {
println!("Client received: {}", data);
text.set(data.clone());
post_server_data(data).await.unwrap();
}
let data = get_server_data().await?;
println!("Client received: {}", data);
text.set(data.clone());
post_server_data(data).await?;
Ok(())
},
"Run a server function!"
}
@@ -33,14 +33,14 @@ fn app() -> Element {
}
#[server]
async fn post_server_data(data: String) -> Result<(), ServerFnError> {
async fn post_server_data(data: String) -> ServerFnResult {
println!("Server received: {}", data);
Ok(())
}
#[server]
async fn get_server_data() -> Result<String, ServerFnError> {
async fn get_server_data() -> ServerFnResult<String> {
Ok(reqwest::get("https://httpbin.org/ip").await?.text().await?)
}
+17 -17
View File
@@ -52,34 +52,34 @@ fn Home() -> Element {
let mut text = use_signal(|| "...".to_string());
rsx! {
Link { to: Route::Blog { id: count() }, "Go to blog" }
div {
h1 { "High-Five counter: {count}" }
button { onclick: move |_| count += 1, "Up high!" }
button { onclick: move |_| count -= 1, "Down low!" }
button {
onclick: move |_| async move {
if let Ok(data) = get_server_data().await {
Link { to: Route::Blog { id: count() }, "Go to blog" }
div {
h1 { "High-Five counter: {count}" }
button { onclick: move |_| count += 1, "Up high!" }
button { onclick: move |_| count -= 1, "Down low!" }
button {
onclick: move |_| async move {
let data = get_server_data().await?;
println!("Client received: {}", data);
text.set(data.clone());
post_server_data(data).await.unwrap();
}
},
"Run server function!"
post_server_data(data).await?;
Ok(())
},
"Run server function!"
}
"Server said: {text}"
}
"Server said: {text}"
}
}
}
}
#[server(PostServerData)]
async fn post_server_data(data: String) -> Result<(), ServerFnError> {
async fn post_server_data(data: String) -> ServerFnResult {
println!("Server received: {}", data);
Ok(())
}
#[server(GetServerData)]
async fn get_server_data() -> Result<String, ServerFnError> {
async fn get_server_data() -> ServerFnResult<String> {
Ok("Hello from the server!".to_string())
}
+7 -7
View File
@@ -9,13 +9,13 @@ fn app() -> Element {
button {
onclick: move |_| async move {
response.write().clear();
if let Ok(stream) = test_stream().await {
response.write().push_str("Stream started\n");
let mut stream = stream.into_inner();
while let Some(Ok(text)) = stream.next().await {
response.write().push_str(&text);
}
let stream = test_stream().await?;
response.write().push_str("Stream started\n");
let mut stream = stream.into_inner();
while let Some(Ok(text)) = stream.next().await {
response.write().push_str(&text);
}
Ok(())
},
"Start stream"
}
@@ -24,7 +24,7 @@ fn app() -> Element {
}
#[server(output = StreamingText)]
pub async fn test_stream() -> Result<TextStream, ServerFnError> {
pub async fn test_stream() -> ServerFnResult<TextStream<ServerFnError>> {
let (tx, rx) = futures::channel::mpsc::unbounded();
tokio::spawn(async move {
loop {
+1 -1
View File
@@ -45,7 +45,7 @@ fn app() -> Element {
#[server(protocol = Websocket<JsonEncoding, JsonEncoding>)]
async fn uppercase_ws(
input: BoxedStream<String, ServerFnError>,
) -> Result<BoxedStream<String, ServerFnError>, ServerFnError> {
) -> ServerFnResult<BoxedStream<String, ServerFnError>> {
let mut input = input;
// Create a channel with the output of the websocket