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