use std::ops::Deref; use async_trait::async_trait; use loco_rs::app::{AppContext, Initializer}; use once_cell::sync::OnceCell; use super::AppMikanConfig; use crate::{config::AppConfigExt, fetch::HttpClient}; static APP_MIKAN_CLIENT: OnceCell = OnceCell::new(); pub struct AppMikanClient { http_client: HttpClient, base_url: String, } impl AppMikanClient { pub fn new(config: AppMikanConfig) -> loco_rs::Result { let http_client = HttpClient::from_config(config.http_client).map_err(loco_rs::Error::wrap)?; let base_url = config.base_url; Ok(Self { http_client, base_url, }) } pub fn app_instance() -> &'static AppMikanClient { APP_MIKAN_CLIENT .get() .expect("AppMikanClient is not initialized") } pub fn base_url(&self) -> &str { &self.base_url } } impl Deref for AppMikanClient { type Target = HttpClient; fn deref(&self) -> &Self::Target { &self.http_client } } pub struct AppMikanClientInitializer; #[async_trait] impl Initializer for AppMikanClientInitializer { fn name(&self) -> String { "AppMikanClientInitializer".to_string() } async fn before_run(&self, app_context: &AppContext) -> loco_rs::Result<()> { let config = &app_context.config; let app_mikan_conf = config.get_app_conf()?.mikan; APP_MIKAN_CLIENT.get_or_try_init(|| AppMikanClient::new(app_mikan_conf))?; Ok(()) } }