use crate::domain_client::DomainClient as r_DomainClient;
use crate::domain_client::ListDomainsQuery as r_ListDomainsQuery;
use crate::domain_data::{
DownloadQuery as r_DownloadQuery, UploadDomainData as r_UploadDomainData,
};
use crate::reconstruction::JobRequest as r_JobRequest;
use serde_wasm_bindgen::{from_value, to_value};
use wasm_bindgen::prelude::*;
use wasm_bindgen::{JsError, JsValue};
use wasm_bindgen_futures::{
future_to_promise,
js_sys::{Promise, Uint8Array},
};
use wasm_streams::readable::sys;
#[wasm_bindgen(typescript_custom_section)]
const TS_APPEND_CONTENT: &'static str = r#"
export type DownloadQuery = { ids: string[], name: string | null, data_type: string | null };
export type UploadDomainData = { id?: string, name?: string, data_type?: string, data: Uint8Array };
export type DomainDataMetadata = { id: string, name: string, data_type: string, size: number, created_at: string, updated_at: string };
export type DomainData = { metadata: DomainDataMetadata, data: Uint8Array };
export type DomainServer = { id: string, url: string, organization_id: string, name: string };
export type DomainWithServer = { id: string, name: string, organization_id: string, domain_server_id: string, redirect_url: string | null, domain_server: DomainServer };
export type JobRequest = { data_ids: string[], processing_type: string, server_api_key: string, server_url: string };
/**
* ListDomainsQuery specifies the parameters for listing domains the caller has access to.
*
* - org: (required) The organization to list domains from:
* - "own": returns domains in your own organization.
* - a UUID: returns domains in that specific organization.
* - "all": returns domains across all organizations. When filtering by 'portal' (see below), this works without restrictions.
* Otherwise, 'domain_server_id' is required and the domain server must belong to your org.
* Not available for app tokens without a portal filter.
* - portal_id: (optional) Full UUID of a portal to filter domains. Mutually exclusive with 'portal_short_id'.
* - portal_short_id: (optional) Short ID of a portal to filter domains. Mutually exclusive with 'portal_id'.
* - domain_server_id: (optional) UUID of the domain server to filter domains. Ignored if a portal filter is active.
*/
export type ListDomainsQuery = { portal_id?: string | null, portal_short_id?: string | null, org: string, domain_server_id?: string | null };
/**
* Signs in with application credentials to obtain a DomainClient instance. Make sure to call .free() to free the memory when you are done with the client.
*
* @param api_url - The base URL for the API service.
* @param dds_url - The URL for the Domain Discovery Service.
* @param client_id - Unique identifier for this client.
* @param app_key - Application key for authentication.
* @param app_secret - Application secret for authentication.
* @returns Promise that resolves to a DomainClient instance.
*
* @example
* const client = await signInWithAppCredential(
* "https://api.auki.network",
* "https://dds.auki.network",
* "my-client-id",
* "app-key-123",
* "app-secret-456"
* );
* client.free(); // free the memory when you are done with the client
*/
export function signInWithAppCredential(
api_url: string,
dds_url: string,
client_id: string,
app_key: string,
app_secret: string
): Promise<DomainClient>;
/**
* Signs in with user credentials to obtain a DomainClient instance. Make sure to call .free() to free the memory when you are done with the client.
*
* @param api_url - The base URL for the API service.
* @param dds_url - The URL for the Domain Discovery Service.
* @param client_id - Unique identifier for this client.
* @param email - User's email address.
* @param password - User's password.
* @param remember_password - Set to `true` if you want to automatically relogin with the same credentials after refreshtoken expires, it is NOT recommended to set to `true` in client side as storing credentials in the browser increases security risks (e.g., XSS attacks).
* @returns Promise that resolves to a DomainClient instance.
*
* @example
* const client = await signInWithUserCredential(
* "https://api.auki.network",
* "https://dds.auki.network",
* "my-client-id",
* "user@example.com",
* "password123",
* false
* );
* client.free(); // free the memory when you are done with the client
*/
export function signInWithUserCredential(
api_url: string,
dds_url: string,
client_id: string,
email: string,
password: string,
logout: boolean
): Promise<DomainClient>;
"#;
#[wasm_bindgen(getter_with_clone)]
pub struct DomainClient {
domain_client: r_DomainClient,
}
#[wasm_bindgen(js_name = "signInWithAppCredential")]
pub fn sign_in_with_app_credential(
api_url: String,
dds_url: String,
client_id: String,
app_key: String,
app_secret: String,
) -> Promise {
let future = async move {
let res = r_DomainClient::new_with_app_credential(
&api_url,
&dds_url,
&client_id,
&app_key,
&app_secret,
)
.await;
match res {
Ok(domain_client) => Ok(JsValue::from(DomainClient {
domain_client: domain_client,
})),
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
};
future_to_promise(future)
}
#[wasm_bindgen(js_name = "signInWithUserCredential")]
pub fn sign_in_with_user_credential(
api_url: String,
dds_url: String,
client_id: String,
email: String,
password: String,
remember_password: bool,
) -> Promise {
let future = async move {
let res = r_DomainClient::new_with_user_credential(
&api_url,
&dds_url,
&client_id,
&email,
&password,
remember_password,
)
.await;
match res {
Ok(domain_client) => Ok(JsValue::from(DomainClient {
domain_client: domain_client,
})),
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
};
future_to_promise(future)
}
#[wasm_bindgen]
impl DomainClient {
#[wasm_bindgen(constructor)]
pub fn new(api_url: String, dds_url: String, client_id: String) -> Self {
Self {
domain_client: r_DomainClient::new(&api_url, &dds_url, &client_id),
}
}
#[wasm_bindgen(js_name = "withOIDCAccessToken")]
pub fn with_oidc_access_token(&self, oidc_access_token: String) -> Self {
Self {
domain_client: self
.domain_client
.with_oidc_access_token(&oidc_access_token),
}
}
#[wasm_bindgen(js_name = "downloadDomainDataMetadata")]
pub fn download_domain_data_metadata(&self, domain_id: String, query: JsValue) -> Promise {
let domain_client = self.domain_client.clone();
let future = async move {
let parse = from_value::<r_DownloadQuery>(query);
if let Err(e) = parse {
return Err(JsError::new(&e.to_string()).into());
}
let query = parse.unwrap();
let res = domain_client.download_metadata(&domain_id, &query).await;
match res {
Ok(data) => match to_value(&data) {
Ok(value) => Ok(value),
Err(e) => Err(JsError::new(&e.to_string()).into()),
},
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
};
future_to_promise(future)
}
#[wasm_bindgen(js_name = "downloadDomainData")]
pub fn download_domain_data(&self, domain_id: String, query: JsValue) -> Promise {
let domain_client = self.domain_client.clone();
let future = async move {
let parse = from_value::<r_DownloadQuery>(query);
if let Err(e) = parse {
return Err(JsError::new(&e.to_string()).into());
}
let query = parse.unwrap();
let res = domain_client.download_domain_data(&domain_id, &query).await;
if let Err(e) = res {
return Err(JsError::new(&e.to_string()).into());
}
let response = res.unwrap();
to_value(&response).map_err(|e| JsError::new(&e.to_string()).into())
};
future_to_promise(future)
}
#[wasm_bindgen(js_name = "downloadDomainDataStream")]
pub fn download_domain_data_stream(
&self,
domain_id: String,
query: JsValue,
) -> sys::ReadableStream {
use futures::{SinkExt, StreamExt};
use wasm_bindgen_futures::spawn_local;
let (mut tx, rx) = futures::channel::mpsc::unbounded::<Result<JsValue, JsValue>>();
let domain_client = self.domain_client.clone();
spawn_local(async move {
let query = match from_value::<r_DownloadQuery>(query) {
Ok(q) => q,
Err(e) => {
tx.send(Err(JsError::new(&e.to_string()).into())).await.ok();
return;
}
};
let res = domain_client
.download_domain_data_stream(&domain_id, &query)
.await;
if let Ok(mut download_rx) = res {
while let Some(result) = download_rx.next().await {
match result {
Ok(data) => match to_value(&data) {
Ok(value) => {
tx.send(Ok(value)).await.ok();
}
Err(e) => {
tx.send(Err(JsError::new(&e.to_string()).into())).await.ok();
}
},
Err(e) => {
tx.send(Err(JsError::new(&e.to_string()).into())).await.ok();
}
}
}
}
});
wasm_streams::ReadableStream::into_raw(wasm_streams::ReadableStream::from_stream(rx))
}
#[wasm_bindgen(js_name = "uploadDomainData")]
pub fn upload_domain_data(&self, domain_id: String, data: JsValue) -> Promise {
let domain_client = self.domain_client.clone();
let future = async move {
match from_value::<Vec<r_UploadDomainData>>(data) {
Ok(upload) => {
let res = domain_client.upload_domain_data(&domain_id, upload).await;
match res {
Ok(data) => match to_value(&data) {
Ok(value) => Ok(value),
Err(e) => Err(JsError::new(&e.to_string()).into()),
},
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
}
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
};
future_to_promise(future)
}
#[wasm_bindgen(js_name = "downloadDomainDataById")]
pub fn download_domain_data_by_id(&self, domain_id: String, id: String) -> Promise {
let domain_client = self.domain_client.clone();
let future = async move {
let res = domain_client
.download_domain_data_by_id(&domain_id, &id)
.await;
match res {
Ok(data) => Ok(JsValue::from(Uint8Array::from(data.as_slice()))),
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
};
future_to_promise(future)
}
#[wasm_bindgen(js_name = "deleteDomainDataById")]
pub fn delete_domain_data_by_id(&self, domain_id: String, id: String) -> Promise {
let domain_client = self.domain_client.clone();
let future = async move {
let res = domain_client
.delete_domain_data_by_id(&domain_id, &id)
.await;
match res {
Ok(()) => Ok(JsValue::undefined()),
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
};
future_to_promise(future)
}
#[wasm_bindgen(js_name = "submitJobV1")]
pub fn submit_job_v1(&self, domain_id: String, request: JsValue) -> Promise {
let domain_client = self.domain_client.clone();
let future = async move {
match from_value::<r_JobRequest>(request) {
Ok(process_request) => {
let res = domain_client
.submit_job_request_v1(&domain_id, &process_request)
.await;
match res {
Ok(response) => {
let body = response
.text()
.await
.map_err(|e| JsError::new(&e.to_string()))?;
Ok(JsValue::from_str(&body))
}
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
}
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
};
future_to_promise(future)
}
#[wasm_bindgen(js_name = "listDomains")]
pub fn list_domains(&self, query: JsValue) -> Promise {
let domain_client = self.domain_client.clone();
let future = async move {
let query = match from_value::<r_ListDomainsQuery>(query) {
Ok(q) => q,
Err(e) => {
return Err(JsError::new(&e.to_string()).into());
}
};
let res = domain_client.list_domains(&query).await;
match res {
Ok(response) => match to_value(&response.domains) {
Ok(value) => Ok(value),
Err(e) => Err(JsError::new(&e.to_string()).into()),
},
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
};
future_to_promise(future)
}
#[wasm_bindgen(js_name = "createDomain")]
pub fn create_domain(
&self,
name: String,
domain_server_id: Option<String>,
domain_server_url: Option<String>,
redirect_url: Option<String>,
) -> Promise {
let domain_client = self.domain_client.clone();
let future = async move {
let res = domain_client
.create_domain(&name, domain_server_id, domain_server_url, redirect_url)
.await;
match res {
Ok(domain) => match to_value(&domain.domain) {
Ok(value) => Ok(value),
Err(e) => Err(JsError::new(&e.to_string()).into()),
},
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
};
future_to_promise(future)
}
#[wasm_bindgen(js_name = "deleteDomain")]
pub fn delete_domain(&self, domain_id: String) -> Promise {
let domain_client = self.domain_client.clone();
let future = async move {
let res = domain_client.delete_domain(&domain_id).await;
match res {
Ok(()) => Ok(JsValue::undefined()),
Err(e) => Err(JsError::new(&e.to_string()).into()),
}
};
future_to_promise(future)
}
}
#[wasm_bindgen(start)]
pub fn start() -> Result<(), JsValue> {
console_error_panic_hook::set_once();
let config = tracing_wasm::WASMLayerConfigBuilder::new()
.set_max_level(tracing::Level::DEBUG)
.build();
tracing_wasm::set_as_global_default_with_config(config);
tracing::info!("Starting log for DOMAIN-HTTP");
Ok(())
}