service_kit 0.1.2

A foundational toolkit for building high-performance, modular services in Rust.
Documentation
use std::collections::HashMap;
use std::future::Future;
use std::pin::Pin;
use std::sync::{Arc, Mutex};
use axum::response::Response;
use axum::http::HeaderMap;
use once_cell::sync::Lazy;
use serde_json::Value;

pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

static API_HANDLERS: Lazy<Arc<Mutex<HashMap<&'static str, ApiMethodHandler>>>> =
    Lazy::new(|| Arc::new(Mutex::new(HashMap::new())));

pub fn register_handler(handler: ApiMethodHandler) {
    let operation_id = handler.operation_id;
    API_HANDLERS
        .lock()
        .expect("Failed to lock API_HANDLERS mutex")
        .insert(handler.operation_id, handler);
    println!("[service_kit] Registered API handler: {}", operation_id);
}

pub fn get_api_handlers() -> Arc<Mutex<HashMap<&'static str, ApiMethodHandler>>> {
    API_HANDLERS.clone()
}

pub struct ApiMethodHandler {
    pub operation_id: &'static str,
    pub handler: Arc<
        dyn for<'a> Fn(&'a Value) -> BoxFuture<'a, crate::error::Result<Response>> + Send + Sync,
    >,
}

impl Clone for ApiMethodHandler {
    fn clone(&self) -> Self {
        Self {
            operation_id: self.operation_id,
            handler: self.handler.clone(),
        }
    }
}

impl ApiMethodHandler {
    pub(crate) fn clone_for_mcp(
        &self,
    ) -> (
        String,
        Arc<
            dyn for<'a> Fn(
                    &'a Value,
                ) -> crate::handler::BoxFuture<'a, crate::error::Result<Response>>
                + Send
                + Sync,
        >,
    ) {
        (self.operation_id.to_string(), self.handler.clone())
    }
}

impl std::fmt::Debug for ApiMethodHandler {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ApiMethodHandler")
            .field("operation_id", &self.operation_id)
            .finish()
    }
}

pub type DynHandlerFuture = Pin<Box<dyn Future<Output = crate::error::Result<Response>> + Send + 'static>>;

pub struct ApiHandlerInventory {
    pub operation_id: &'static str,
    pub handler: fn(&Value, HeaderMap, Option<String>, Option<Arc<dyn std::any::Any + Send + Sync>>, Vec<u8>, Option<String>) -> DynHandlerFuture,
}

inventory::collect!(ApiHandlerInventory);