posemesh_domain_http/
lib.rs

1use futures::channel::mpsc::Receiver;
2
3#[cfg(target_family = "wasm")]
4use crate::domain_data::UploadDomainData;
5use crate::domain_data::{download_v1_stream, DomainData, DownloadQuery};
6
7mod auth;
8pub mod config;
9pub mod domain_data;
10pub mod discovery;
11#[cfg(target_family = "wasm")]
12pub mod wasm;
13
14use crate::discovery::DiscoveryService;
15
16pub struct DomainClient {
17    discovery_client: DiscoveryService,
18    pub client_id: String,
19}
20
21impl DomainClient {
22    fn new(api_url: &str, dds_url: &str, client_id: &str) -> Self {
23        if client_id.is_empty() {
24            panic!("client_id is empty");
25        }
26        Self {
27            discovery_client: DiscoveryService::new(api_url, dds_url, client_id),
28            client_id: client_id.to_string(),
29        }
30    }
31
32    pub async fn new_with_app_credential(api_url: &str, dds_url: &str, client_id: &str, app_key: &str, app_secret: &str) -> Result<Self, Box<dyn std::error::Error>> {
33        let mut dc = DomainClient::new(api_url, dds_url, client_id);
34        let _ = dc.discovery_client.sign_in_as_auki_app(app_key, app_secret).await?;
35        Ok(dc)
36    }
37
38    pub async fn new_with_user_credential(api_url: &str, dds_url: &str, client_id: &str, email: &str, password: &str) -> Result<Self, Box<dyn std::error::Error>> {
39        let mut dc = DomainClient::new(api_url, dds_url, client_id);
40        let _ = dc.discovery_client.sign_in_with_auki_account(email, password).await?;
41        Ok(dc)
42    }
43
44    pub async fn download_domain_data(&self, domain_id: &str, query: &DownloadQuery) -> Result<Receiver<Result<DomainData, Box<dyn std::error::Error + Send + Sync>>>, Box<dyn std::error::Error>> {
45        let domain = self.discovery_client.auth_domain(domain_id).await?;
46        let rx = download_v1_stream(&domain.domain.domain_server.url, &self.client_id, &domain.access_token, domain_id, query).await?;
47        Ok(rx)
48    }
49
50    #[cfg(not(target_family = "wasm"))]
51    pub async fn upload_domain_data(&self, domain_id: &str, data: Receiver<domain_data::UploadDomainData>) -> Result<Vec<DomainData>, Box<dyn std::error::Error>> {
52        use crate::domain_data::upload_v1_stream;
53        let domain = self.discovery_client.auth_domain(domain_id).await?;
54        upload_v1_stream(&domain.domain.domain_server.url, &domain.access_token, domain_id, data).await
55    }
56
57    #[cfg(target_family = "wasm")]
58    pub async fn upload_domain_data(&self, domain_id: &str, data: Vec<UploadDomainData>) -> Result<(), Box<dyn std::error::Error>> {
59        let domain = self.discovery_client.auth_domain(domain_id).await?;
60        upload_v1(&domain.domain.domain_server.url, &domain.access_token, domain_id, data).await
61    }
62}
63
64#[cfg(not(target_family = "wasm"))]
65#[cfg(test)]
66mod tests {
67    use crate::domain_data::{UpdateDomainData, UploadDomainData};
68
69    use super::*;
70    use futures::{channel::mpsc, StreamExt};
71    use tokio::spawn;
72
73    fn get_config() -> config::Config {
74        if std::path::Path::new("../.env.local").exists() {
75            dotenvy::from_filename("../.env.local").ok();
76            dotenvy::dotenv().ok();
77        }
78        let config = config::Config::from_env().unwrap();
79        config
80    }
81
82    #[tokio::test]
83    async fn test_download_domain_data_with_app_credential() {
84        // Create a test client
85        let config = get_config();
86        let client = DomainClient::new_with_app_credential(&config.api_url, &config.dds_url, &config.client_id, &config.app_key, &config.app_secret).await.expect("Failed to create client");
87        
88        // Create a test query
89        let query = DownloadQuery {
90            ids: vec![],
91            name: None,
92            data_type: Some("dmt_accel_csv".to_string()),
93        };
94
95        // Test the download function
96        let result = client.download_domain_data(
97            &config.domain_id,
98            &query
99        ).await;
100
101        assert!(result.is_ok(), "error message : {:?}", result.err());
102
103        let mut count = 0;
104        let mut rx = result.unwrap();
105        while let Some(Ok(_)) = rx.next().await {
106            count += 1;
107        }
108        assert!(count > 0);
109    }
110
111    #[tokio::test]
112    async fn test_upload_domain_data_with_user_credential() {
113        use futures::SinkExt;
114        let config = get_config();
115        let user_email = std::env::var("USER_EMAIL").unwrap();
116        let user_password = std::env::var("USER_PASSWORD").unwrap();
117        let client = DomainClient::new_with_user_credential(&config.api_url, &config.dds_url, &config.client_id, &user_email, &user_password).await.expect("Failed to create client");
118
119        let data = vec![UploadDomainData {
120            create: None,
121            update: Some(UpdateDomainData {
122                id: "a84a36e5-312b-4f80-974a-06f5d19c1e16".to_string(),
123            }),
124            data: "{\"test\": \"test updated\"}".as_bytes().to_vec(),
125        }, UploadDomainData {
126            create: None,
127            update: Some(UpdateDomainData {
128                id: "a08dc12f-c79e-4f5e-b388-c09ad6d8cfd8".to_string(),
129            }),
130            data: "{\"test\": \"test updated\"}".as_bytes().to_vec(),
131        }];
132        let (mut tx, rx) = mpsc::channel(10);
133        spawn(async move {
134            for d in data {
135                tx.send(d).await.unwrap();
136            }
137            tx.close().await.unwrap();
138        });
139        let result = client.upload_domain_data(&config.domain_id, rx).await;
140
141        assert!(result.is_ok(), "error message : {:?}", result.err());
142        assert_eq!(result.unwrap().len(), 2);
143    }
144}
145