use axum::extract::FromRef; use sea_orm::DatabaseConnection; use crate::config::AppConfig; use erp_core::events::EventBus; use erp_core::module::ModuleRegistry; /// Axum shared application state. /// All handlers access database connections, configuration, etc. through `State`. #[derive(Clone)] pub struct AppState { pub db: DatabaseConnection, pub config: AppConfig, pub event_bus: EventBus, pub module_registry: ModuleRegistry, pub redis: redis::Client, /// 实际的默认租户 ID,从数据库种子数据中获取。 pub default_tenant_id: uuid::Uuid, } /// Allow handlers to extract `DatabaseConnection` directly from `State`. impl FromRef for DatabaseConnection { fn from_ref(state: &AppState) -> Self { state.db.clone() } } /// Allow handlers to extract `EventBus` directly from `State`. impl FromRef for EventBus { fn from_ref(state: &AppState) -> Self { state.event_bus.clone() } } /// Allow erp-auth handlers to extract their required state without depending on erp-server. /// /// This bridges the gap: erp-auth defines `AuthState` with the fields it needs, /// and erp-server fills them from `AppState`. impl FromRef for erp_auth::AuthState { fn from_ref(state: &AppState) -> Self { use erp_auth::auth_state::parse_ttl; Self { db: state.db.clone(), event_bus: state.event_bus.clone(), jwt_secret: state.config.jwt.secret.clone(), access_ttl_secs: parse_ttl(&state.config.jwt.access_token_ttl), refresh_ttl_secs: parse_ttl(&state.config.jwt.refresh_token_ttl), default_tenant_id: state.default_tenant_id, } } } /// Allow erp-config handlers to extract their required state without depending on erp-server. impl FromRef for erp_config::ConfigState { fn from_ref(state: &AppState) -> Self { Self { db: state.db.clone(), event_bus: state.event_bus.clone(), } } } /// Allow erp-workflow handlers to extract their required state without depending on erp-server. impl FromRef for erp_workflow::WorkflowState { fn from_ref(state: &AppState) -> Self { Self { db: state.db.clone(), event_bus: state.event_bus.clone(), } } } /// Allow erp-message handlers to extract their required state without depending on erp-server. impl FromRef for erp_message::MessageState { fn from_ref(state: &AppState) -> Self { Self { db: state.db.clone(), event_bus: state.event_bus.clone(), } } }