bitwarden_server_communication_config/wasm/
js_repository.rs1use bitwarden_threading::ThreadBoundRunner;
2use wasm_bindgen::prelude::*;
3
4use crate::{ServerCommunicationConfig, ServerCommunicationConfigRepository};
5
6#[wasm_bindgen(typescript_custom_section)]
7const TS_CUSTOM_TYPES: &'static str = r#"
8/**
9 * Repository interface for storing server communication configuration.
10 *
11 * Implementations use StateProvider (or equivalent storage mechanism) to
12 * persist configuration across sessions. The hostname is typically the vault
13 * server's hostname (e.g., "vault.acme.com").
14 */
15export interface ServerCommunicationConfigRepository {
16 /**
17 * Retrieves the server communication configuration for a given hostname.
18 *
19 * @param hostname The server hostname (e.g., "vault.acme.com")
20 * @returns The configuration if it exists, undefined otherwise
21 */
22 get(hostname: string): Promise<ServerCommunicationConfig | undefined>;
23
24 /**
25 * Saves the server communication configuration for a given hostname.
26 *
27 * @param hostname The server hostname (e.g., "vault.acme.com")
28 * @param config The configuration to store
29 */
30 save(hostname: string, config: ServerCommunicationConfig): Promise<void>;
31}
32"#;
33
34#[wasm_bindgen]
35extern "C" {
36 #[wasm_bindgen(
38 js_name = ServerCommunicationConfigRepository,
39 typescript_type = "ServerCommunicationConfigRepository"
40 )]
41 pub type RawJsServerCommunicationConfigRepository;
42
43 #[wasm_bindgen(catch, method, structural)]
45 pub async fn get(
46 this: &RawJsServerCommunicationConfigRepository,
47 hostname: String,
48 ) -> Result<JsValue, JsValue>;
49
50 #[wasm_bindgen(catch, method, structural)]
52 pub async fn save(
53 this: &RawJsServerCommunicationConfigRepository,
54 hostname: String,
55 config: JsValue,
56 ) -> Result<(), JsValue>;
57}
58
59pub struct JsServerCommunicationConfigRepository(
65 ThreadBoundRunner<RawJsServerCommunicationConfigRepository>,
66);
67
68impl JsServerCommunicationConfigRepository {
69 pub fn new(repository: RawJsServerCommunicationConfigRepository) -> Self {
71 Self(ThreadBoundRunner::new(repository))
72 }
73}
74
75impl Clone for JsServerCommunicationConfigRepository {
76 fn clone(&self) -> Self {
77 Self(self.0.clone())
78 }
79}
80
81impl ServerCommunicationConfigRepository for JsServerCommunicationConfigRepository {
82 type GetError = String;
83 type SaveError = String;
84
85 async fn get(&self, hostname: String) -> Result<Option<ServerCommunicationConfig>, String> {
86 self.0
87 .run_in_thread(move |repo| async move {
88 let js_value = repo.get(hostname).await.map_err(|e| format!("{e:?}"))?;
89
90 if js_value.is_undefined() || js_value.is_null() {
91 return Ok(None);
92 }
93
94 Ok(Some(
95 serde_wasm_bindgen::from_value(js_value).map_err(|e| e.to_string())?,
96 ))
97 })
98 .await
99 .map_err(|e| e.to_string())?
100 }
101
102 async fn save(
103 &self,
104 hostname: String,
105 config: ServerCommunicationConfig,
106 ) -> Result<(), String> {
107 self.0
108 .run_in_thread(move |repo| async move {
109 let js_value = serde_wasm_bindgen::to_value(&config).map_err(|e| e.to_string())?;
110 repo.save(hostname, js_value)
111 .await
112 .map_err(|e| format!("{e:?}"))
113 })
114 .await
115 .map_err(|e| e.to_string())?
116 }
117}