use crate::error::LxAppError;
use std::sync::OnceLock;
pub use lingxia_observability::LogProvider;
pub use lingxia_provider::{
BoxFuture, FingerprintError, FingerprintProvider, ProviderError, ProviderErrorCode,
PushNotificationProvider,
};
pub use lingxia_update::{LxAppUpdateQuery, UpdatePackageInfo, UpdateProvider, UpdateTarget};
pub trait ProviderErrorExt {
fn to_lxapp_error(&self) -> LxAppError;
}
impl ProviderErrorExt for ProviderError {
fn to_lxapp_error(&self) -> LxAppError {
provider_error_to_lxapp_error(self)
}
}
pub(crate) fn provider_error_to_lxapp_error(error: &ProviderError) -> LxAppError {
let biz_code = error.biz_code();
let detail = error.detail().to_string();
LxAppError::RongJSHost {
code: biz_code.to_string(),
message: detail.clone(),
data: Some(serde_json::json!({
"bizCode": biz_code,
"providerCode": error.code().as_str(),
"detail": detail,
})),
}
}
pub trait Provider: UpdateProvider + FingerprintProvider + PushNotificationProvider {}
impl<T> Provider for T where T: UpdateProvider + FingerprintProvider + PushNotificationProvider {}
pub struct NoOpProvider;
impl UpdateProvider for NoOpProvider {
fn check_update<'a>(
&'a self,
_target: UpdateTarget,
) -> BoxFuture<'a, Result<Option<UpdatePackageInfo>, ProviderError>> {
Box::pin(async { Ok(None) })
}
}
impl FingerprintProvider for NoOpProvider {}
impl PushNotificationProvider for NoOpProvider {}
impl LogProvider for NoOpProvider {}
static PROVIDER: OnceLock<Box<dyn Provider>> = OnceLock::new();
static LOG_PROVIDER: OnceLock<Box<dyn LogProvider>> = OnceLock::new();
pub fn register_provider(provider: Box<dyn Provider>) {
if PROVIDER.set(provider).is_err() {
panic!("register_provider called more than once");
}
}
pub fn register_log_provider(provider: Box<dyn LogProvider>) {
if LOG_PROVIDER.set(provider).is_err() {
panic!("register_log_provider called more than once");
}
}
pub(crate) fn get_provider() -> &'static dyn Provider {
PROVIDER.get().map(|b| b.as_ref()).unwrap_or(&NoOpProvider)
}
pub(crate) fn get_log_provider() -> &'static dyn LogProvider {
LOG_PROVIDER
.get()
.map(|b| b.as_ref())
.unwrap_or(&NoOpProvider)
}
pub async fn bind_push_token(token: String) -> Result<(), ProviderError> {
get_provider().bind_push_token(token).await
}