use axum::Router;
use std::net::SocketAddr;
use crate::{
error::AppResult,
handlers::{SseHandler, SseHandlerConfig, StreamableHttpHandler},
};
use oauth_provider_rs::{DefaultClientManager, OAuthProvider, OAuthProviderTrait, OAuthStorage};
pub struct MicrokernelServer<
P: OAuthProviderTrait<S, DefaultClientManager<S>> + 'static,
S: OAuthStorage + Clone + 'static,
> {
oauth_provider: Option<OAuthProvider<P, S>>,
streamable_handler: Option<StreamableHttpHandler<P, S>>,
sse_handler: Option<SseHandler<P, S>>,
sse_config: SseHandlerConfig,
}
impl<P: OAuthProviderTrait<S, DefaultClientManager<S>> + 'static, S: OAuthStorage + Clone + 'static>
MicrokernelServer<P, S>
{
pub fn new() -> Self {
Self {
oauth_provider: None,
streamable_handler: None,
sse_handler: None,
sse_config: SseHandlerConfig::default(),
}
}
pub fn with_oauth_provider(mut self, oauth_provider: OAuthProvider<P, S>) -> Self {
self.oauth_provider = Some(oauth_provider);
self
}
pub fn with_streamable_handler(
mut self,
streamable_handler: StreamableHttpHandler<P, S>,
) -> Self {
self.streamable_handler = Some(streamable_handler);
self
}
pub fn with_sse_handler(
mut self,
sse_handler: SseHandler<P, S>,
config: SseHandlerConfig,
) -> Self {
self.sse_handler = Some(sse_handler);
self.sse_config = config;
self
}
pub fn build_router(self) -> AppResult<Router> {
let mut router = Router::new();
if let Some(oauth_provider) = self.oauth_provider {
let oauth_router = oauth_provider.router();
router = router.merge(oauth_router);
tracing::debug!("✓ OAuth provider router composed");
}
if let Some(streamable_handler) = self.streamable_handler {
let streamable_router = streamable_handler.router();
router = router.merge(streamable_router);
tracing::debug!("✓ Streamable HTTP handler router composed");
}
if let Some(sse_handler) = self.sse_handler {
let sse_router = sse_handler.router(self.sse_config)?;
router = router.merge(sse_router);
tracing::debug!("✓ SSE handler router composed");
}
Ok(router)
}
pub async fn serve(self, bind_address: SocketAddr) -> AppResult<()> {
let router = self.build_router()?;
let listener = tokio::net::TcpListener::bind(bind_address)
.await
.map_err(|e| crate::error::AppError::Internal(format!("Failed to bind: {}", e)))?;
tracing::info!("🏛️ Microkernel server listening on {}", bind_address);
axum::serve(listener, router)
.await
.map_err(|e| crate::error::AppError::Internal(format!("Server error: {}", e)))?;
Ok(())
}
}
impl<P: OAuthProviderTrait<S, DefaultClientManager<S>>, S: OAuthStorage + Clone + 'static> Default
for MicrokernelServer<P, S>
{
fn default() -> Self {
Self::new()
}
}