telegram_webapp_sdk/api/
cloud_storage.rs1use js_sys::{Array, Function, Promise, Reflect};
5use wasm_bindgen::{JsCast, prelude::*};
6use web_sys::window;
7
8fn cloud_storage_object() -> Result<JsValue, JsValue> {
10 let win = window().ok_or_else(|| JsValue::from_str("no window"))?;
11 let tg = Reflect::get(&win, &JsValue::from_str("Telegram"))?;
12 let webapp = Reflect::get(&tg, &JsValue::from_str("WebApp"))?;
13 Reflect::get(&webapp, &JsValue::from_str("CloudStorage"))
14}
15
16pub fn get_item(key: &str) -> Result<Promise, JsValue> {
32 let storage = cloud_storage_object()?;
33 let func = Reflect::get(&storage, &JsValue::from_str("getItem"))?.dyn_into::<Function>()?;
34 func.call1(&storage, &JsValue::from_str(key))?
35 .dyn_into::<Promise>()
36}
37
38pub fn set_item(key: &str, value: &str) -> Result<Promise, JsValue> {
54 let storage = cloud_storage_object()?;
55 let func = Reflect::get(&storage, &JsValue::from_str("setItem"))?.dyn_into::<Function>()?;
56 func.call2(&storage, &JsValue::from_str(key), &JsValue::from_str(value))?
57 .dyn_into::<Promise>()
58}
59
60pub fn remove_item(key: &str) -> Result<Promise, JsValue> {
76 let storage = cloud_storage_object()?;
77 let func = Reflect::get(&storage, &JsValue::from_str("removeItem"))?.dyn_into::<Function>()?;
78 func.call1(&storage, &JsValue::from_str(key))?
79 .dyn_into::<Promise>()
80}
81
82pub fn get_items(keys: &[&str]) -> Result<Promise, JsValue> {
98 let storage = cloud_storage_object()?;
99 let func = Reflect::get(&storage, &JsValue::from_str("getItems"))?.dyn_into::<Function>()?;
100 let array = Array::new();
101 for key in keys {
102 array.push(&JsValue::from_str(key));
103 }
104 func.call1(&storage, &array.into())?.dyn_into::<Promise>()
105}
106
107pub fn remove_items(keys: &[&str]) -> Result<Promise, JsValue> {
123 let storage = cloud_storage_object()?;
124 let func =
125 Reflect::get(&storage, &JsValue::from_str("removeItems"))?.dyn_into::<Function>()?;
126 let array = Array::new();
127 for key in keys {
128 array.push(&JsValue::from_str(key));
129 }
130 func.call1(&storage, &array.into())?.dyn_into::<Promise>()
131}
132
133pub fn get_keys() -> Result<Promise, JsValue> {
149 let storage = cloud_storage_object()?;
150 let func = Reflect::get(&storage, &JsValue::from_str("getKeys"))?.dyn_into::<Function>()?;
151 func.call0(&storage)?.dyn_into::<Promise>()
152}
153
154#[cfg(test)]
155mod tests {
156 #![allow(dead_code)]
157 use js_sys::{Array, Function, Object, Reflect};
158 use wasm_bindgen_futures::JsFuture;
159 use wasm_bindgen_test::{wasm_bindgen_test, wasm_bindgen_test_configure};
160 use web_sys::window;
161
162 use super::*;
163
164 wasm_bindgen_test_configure!(run_in_browser);
165
166 fn setup_cloud_storage() -> Object {
167 let win = window().unwrap();
168 let telegram = Object::new();
169 let webapp = Object::new();
170 let storage = Object::new();
171 let _ = Reflect::set(&win, &"Telegram".into(), &telegram);
172 let _ = Reflect::set(&telegram, &"WebApp".into(), &webapp);
173 let _ = Reflect::set(&webapp, &"CloudStorage".into(), &storage);
174 storage
175 }
176
177 #[wasm_bindgen_test(async)]
178 async fn get_item_ok() {
179 let storage = setup_cloud_storage();
180 let func =
181 Function::new_with_args("key", "this.called = key; return Promise.resolve('val');");
182 let _ = Reflect::set(&storage, &"getItem".into(), &func);
183 let value = JsFuture::from(get_item("test").unwrap()).await.unwrap();
184 assert_eq!(value.as_string(), Some("val".to_string()));
185 assert_eq!(
186 Reflect::get(&storage, &"called".into())
187 .unwrap()
188 .as_string(),
189 Some("test".into())
190 );
191 }
192
193 #[wasm_bindgen_test]
194 fn get_item_err() {
195 let _ = setup_cloud_storage();
196 assert!(get_item("test").is_err());
197 }
198
199 #[wasm_bindgen_test(async)]
200 async fn set_item_ok() {
201 let storage = setup_cloud_storage();
202 let func = Function::new_with_args(
203 "key, value",
204 "this.called = key + ':' + value; return Promise.resolve();"
205 );
206 let _ = Reflect::set(&storage, &"setItem".into(), &func);
207 JsFuture::from(set_item("a", "b").unwrap()).await.unwrap();
208 assert_eq!(
209 Reflect::get(&storage, &"called".into())
210 .unwrap()
211 .as_string(),
212 Some("a:b".into())
213 );
214 }
215
216 #[wasm_bindgen_test]
217 fn set_item_err() {
218 let _ = setup_cloud_storage();
219 assert!(set_item("a", "b").is_err());
220 }
221
222 #[wasm_bindgen_test(async)]
223 async fn remove_item_ok() {
224 let storage = setup_cloud_storage();
225 let func = Function::new_with_args("key", "this.called = key; return Promise.resolve();");
226 let _ = Reflect::set(&storage, &"removeItem".into(), &func);
227 JsFuture::from(remove_item("k").unwrap()).await.unwrap();
228 assert_eq!(
229 Reflect::get(&storage, &"called".into())
230 .unwrap()
231 .as_string(),
232 Some("k".into())
233 );
234 }
235
236 #[wasm_bindgen_test]
237 fn remove_item_err() {
238 let _ = setup_cloud_storage();
239 assert!(remove_item("k").is_err());
240 }
241
242 #[wasm_bindgen_test(async)]
243 async fn get_items_ok() {
244 let storage = setup_cloud_storage();
245 let func = Function::new_with_args(
246 "keys",
247 "this.called = keys; return Promise.resolve({a: '1', b: '2'});"
248 );
249 let _ = Reflect::set(&storage, &"getItems".into(), &func);
250 let result = JsFuture::from(get_items(&["a", "b"]).unwrap())
251 .await
252 .unwrap();
253 let obj = result.dyn_into::<Object>().unwrap();
254 assert_eq!(
255 Reflect::get(&obj, &"a".into()).unwrap().as_string(),
256 Some("1".into())
257 );
258 assert_eq!(
259 Reflect::get(&obj, &"b".into()).unwrap().as_string(),
260 Some("2".into())
261 );
262 let called = Reflect::get(&storage, &"called".into()).unwrap();
263 let arr = Array::from(&called);
264 assert_eq!(arr.get(0).as_string(), Some("a".into()));
265 assert_eq!(arr.get(1).as_string(), Some("b".into()));
266 }
267
268 #[wasm_bindgen_test]
269 fn get_items_err() {
270 let _ = setup_cloud_storage();
271 assert!(get_items(&["a"]).is_err());
272 }
273
274 #[wasm_bindgen_test(async)]
275 async fn remove_items_ok() {
276 let storage = setup_cloud_storage();
277 let func =
278 Function::new_with_args("keys", "this.called = keys; return Promise.resolve();");
279 let _ = Reflect::set(&storage, &"removeItems".into(), &func);
280 JsFuture::from(remove_items(&["a", "b"]).unwrap())
281 .await
282 .unwrap();
283 let called = Reflect::get(&storage, &"called".into()).unwrap();
284 let arr = Array::from(&called);
285 assert_eq!(arr.get(0).as_string(), Some("a".into()));
286 assert_eq!(arr.get(1).as_string(), Some("b".into()));
287 }
288
289 #[wasm_bindgen_test]
290 fn remove_items_err() {
291 let _ = setup_cloud_storage();
292 assert!(remove_items(&["a"]).is_err());
293 }
294
295 #[wasm_bindgen_test(async)]
296 async fn get_keys_ok() {
297 let storage = setup_cloud_storage();
298 let func = Function::new_no_args("return Promise.resolve(['x', 'y']);");
299 let _ = Reflect::set(&storage, &"getKeys".into(), &func);
300 let result = JsFuture::from(get_keys().unwrap()).await.unwrap();
301 let arr = Array::from(&result);
302 assert_eq!(arr.get(0).as_string(), Some("x".into()));
303 assert_eq!(arr.get(1).as_string(), Some("y".into()));
304 }
305
306 #[wasm_bindgen_test]
307 fn get_keys_err() {
308 let _ = setup_cloud_storage();
309 assert!(get_keys().is_err());
310 }
311}