codify "platform" into resolution logic, server-fn/fullstack overhaul (#4596)

overhaul dioxus fullstack using a new implementation of server_fn

This PR is a complete rewrite of dioxus fullstack designed to improve compatibility with axum and to fix a number of compilation errors based on feature flag unification plumbing through macros.
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2025-10-03 18:26:19 -07:00
1 parent 8421c3aef0
commit f2b1c6d97f
424 files changed
+17284 -6624

No files matched your search

@@ -0,0 +1,41 @@
use anyhow::Result;
use dioxus::prelude::*;
#[cfg(feature = "server")]
thread_local! {
static DB: std::sync::LazyLock<rusqlite::Connection> = std::sync::LazyLock::new(|| {
let conn = rusqlite::Connection::open("hotdogdb/hotdog.db").expect("Failed to open database");
conn.execute_batch(
"CREATE TABLE IF NOT EXISTS dogs (
id INTEGER PRIMARY KEY,
url TEXT NOT NULL
);",
)
.unwrap();
conn
});
}
#[get("/api/dogs")]
pub async fn list_dogs() -> Result<Vec<(usize, String)>> {
DB.with(|db| {
Ok(db
.prepare("SELECT id, url FROM dogs ORDER BY id DESC LIMIT 10")?
.query_map([], |row| Ok((row.get(0)?, row.get(1)?)))?
.collect::<Result<Vec<(usize, String)>, rusqlite::Error>>()?)
})
}
#[delete("/api/dogs/{id}")]
pub async fn remove_dog(id: usize) -> Result<()> {
DB.with(|db| db.execute("DELETE FROM dogs WHERE id = ?1", [id]))?;
Ok(())
}
#[post("/api/dogs")]
pub async fn save_dog(image: String) -> Result<()> {
DB.with(|db| db.execute("INSERT INTO dogs (url) VALUES (?1)", [&image]))?;
Ok(())
}
@@ -0,0 +1,71 @@
use dioxus::prelude::*;
use crate::{
backend::{list_dogs, remove_dog, save_dog},
Route,
};
#[component]
pub fn Favorites() -> Element {
let mut favorites = use_loader(list_dogs)?;
rsx! {
div { id: "favorites",
for (id , url) in favorites.cloned() {
div { class: "favorite-dog", key: "{id}",
img { src: "{url}" }
button {
onclick: move |_| async move {
_ = remove_dog(id).await;
favorites.restart();
},
"❌"
}
}
}
}
}
}
#[component]
pub fn NavBar() -> Element {
rsx! {
div { id: "title",
span {}
Link { to: Route::DogView, h1 { "🌭 HotDog! " } }
Link { to: Route::Favorites, id: "heart", "♥️" }
}
Outlet::<Route> {}
}
}
#[component]
pub fn DogView() -> Element {
let mut img_src = use_loader(|| async move {
anyhow::Ok(
reqwest::get("https://dog.ceo/api/breeds/image/random")
.await?
.json::<serde_json::Value>()
.await?["message"]
.to_string(),
)
})?;
rsx! {
div { id: "dogview",
img { id: "dogimg", src: "{img_src}" }
}
div { id: "buttons",
button {
id: "skip",
onclick: move |_| img_src.restart(),
"skip"
}
button {
id: "save",
onclick: move |_| async move { _ = save_dog(img_src()).await },
"save!"
}
}
}
}
+29
View File
@@ -0,0 +1,29 @@
mod backend;
mod frontend;
use dioxus::prelude::*;
use frontend::*;
#[derive(Routable, PartialEq, Clone)]
enum Route {
#[layout(NavBar)]
#[route("/")]
DogView,
#[route("/favorites")]
Favorites,
}
fn main() {
#[cfg(not(feature = "server"))]
dioxus::fullstack::set_server_url("https://hot-dog.fly.dev");
dioxus::launch(app);
}
fn app() -> Element {
rsx! {
Stylesheet { href: asset!("/assets/main.css") }
Router::<Route> {}
}
}