use authkestra::flow::Engine;
use authkestra_axum::{AxumExt, AxumState};
use authkestra_engine::auth::SessionStore;
use authkestra_engine::SessionConfig;
use authkestra_macros::KvStore;
use axum::Router;
use sqlx::sqlite::SqlitePoolOptions;
use std::sync::Arc;
use tower_cookies::CookieManagerLayer;
use tower_http::services::ServeDir;
#[derive(KvStore)]
pub struct MySqliteSessionStore(authkestra_engine::store::sql::SqlKvStore<sqlx::Sqlite>);
#[derive(Clone, AxumState)]
struct AppState {
#[authkestra(engine)]
auth: authkestra_engine::AkWebAppEngine,
}
#[tokio::main]
async fn main() {
let pool = SqlitePoolOptions::new()
.connect("sqlite::memory:")
.await
.expect("Failed to connect to SQLite");
sqlx::query(
"CREATE TABLE IF NOT EXISTS user_sessions (
key TEXT PRIMARY KEY,
value TEXT NOT NULL,
expires_at DATETIME NOT NULL
)",
)
.execute(&pool)
.await
.unwrap();
let sql_store = authkestra_engine::store::sql::SqlKvStore::with_table_name(
pool,
"user_sessions".to_string(),
);
let session_store = MySqliteSessionStore(sql_store);
let session_store_arc: Arc<dyn SessionStore> = Arc::new(session_store);
let auth_engine = Engine::builder()
.session_store(session_store_arc)
.session_config(SessionConfig {
secure: false,
..Default::default()
})
.build();
let state = AppState {
auth: auth_engine.clone(),
};
let app = Router::new()
.fallback_service(ServeDir::new(concat!(
env!("CARGO_MANIFEST_DIR"),
"/examples/static"
)))
.merge(auth_engine.axum_router::<AppState>())
.layer(CookieManagerLayer::new())
.with_state(state);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
println!("🚀 Axum Data Layer Macros Example running on http://localhost:3000");
axum::serve(listener, app).await.unwrap();
}