Refactor: untangle framework library from todo example
The codebase is now split into two clear layers: Framework library (src/): - lib.rs — public API surface, re-exports all framework types - signal.rs — SignalOpts, Signal, SignalStore, mangle/global/client_only helpers - query.rs — Query trait, CacheKey, query_one!/query_all! macros (macro paths updated from $crate::framework::* to $crate::*) - context.rs — RenderContext, ComponentTree, ComponentNode - connection.rs — ConnectionManager, SubscriptionRegistry, ConnectionState - sse.rs — format_patch_elements, format_patch_signals - server.rs — AppState, SharedState, sse_handler (pure framework plumbing) Todo example (examples/todo/): - main.rs — SQLite setup, seeding, server bootstrap - app.rs — router, document_shell, resolve_and_render, render_page, action_then_render, and all HTTP handlers - queries.rs — Todo model, ListTodos/GetTodo queries, mutation helpers - todo_list.rs — TodoList page component - about.rs — About page component Run the example independently with: cargo run --example todo https://claude.ai/code/session_01JThiQbp3Bn9J1VhBpRuz4u
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
mod app;
|
||||
mod queries;
|
||||
mod todo_list;
|
||||
mod about;
|
||||
|
||||
use livevue_rs::{AppState, ConnectionManager, SubscriptionRegistry};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
// -----------------------------------------------------------------------
|
||||
// Database setup
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// SQLite with create-if-missing. In-memory `:memory:` also works for dev.
|
||||
let db = sqlx::SqlitePool::connect("sqlite:todo.db?mode=rwc").await?;
|
||||
|
||||
// Run migrations inline (no migration files needed for v0).
|
||||
sqlx::query(
|
||||
"CREATE TABLE IF NOT EXISTS todos (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT NOT NULL,
|
||||
completed BOOLEAN NOT NULL DEFAULT FALSE
|
||||
)",
|
||||
)
|
||||
.execute(&db)
|
||||
.await?;
|
||||
|
||||
// Seed a few todos if the table is empty (nice for first run)
|
||||
let count: (i64,) = sqlx::query_as("SELECT COUNT(*) FROM todos")
|
||||
.fetch_one(&db)
|
||||
.await?;
|
||||
if count.0 == 0 {
|
||||
for title in &["Learn Rust", "Build LiveVue.rs", "Ship v0"] {
|
||||
sqlx::query("INSERT INTO todos (title, completed) VALUES (?, false)")
|
||||
.bind(title)
|
||||
.execute(&db)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Application state
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
let state = Arc::new(AppState {
|
||||
db,
|
||||
connections: ConnectionManager::new(),
|
||||
subscriptions: SubscriptionRegistry::new(),
|
||||
});
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Server
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
let app = app::router(state);
|
||||
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await?;
|
||||
println!("Todo example listening on http://localhost:3000");
|
||||
|
||||
axum::serve(listener, app).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user