1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
use serde::{Deserialize, Serialize};
use wasm_bindgen::prelude::*;

#[macro_export]
macro_rules! bind {
    ($namespace:ident, $target:ident) => {
        #[wasm_bindgen]
        extern "C" {
            type $namespace;

            #[wasm_bindgen(catch, js_name = "get", static_method_of = $namespace)]
            async fn get(key: JsValue, value_type: JsValue) -> Result<JsValue, JsValue>;

            #[wasm_bindgen(catch, js_name = "getWithMetadata", static_method_of = $namespace)]
            async fn get_with_metadata(
                key: JsValue,
                value_type: JsValue,
            ) -> Result<JsValue, JsValue>;

            #[wasm_bindgen(catch, js_name = "put", static_method_of = $namespace)]
            async fn put(key: JsValue, value: JsValue, options: JsValue) -> Result<(), JsValue>;

            #[wasm_bindgen(catch, js_name = "delete", static_method_of = $namespace)]
            async fn delete(key: JsValue) -> Result<(), JsValue>;

            #[wasm_bindgen(catch, js_name = "list", static_method_of = $namespace)]
            async fn list(options: JsValue) -> Result<JsValue, JsValue>;
        }

        struct $target;

        impl $target {
            pub async fn list(options: Option<ListOptions>) -> Result<JsValue, JsValue> {
                // Convert the options into a JS value:
                let options = match options {
                    Some(options) => JsValue::from(options),
                    None => JsValue::undefined(),
                };
                // Call the imported list JS method:
                match KV::list(options).await {
                    Ok(value) => Ok(value.into()),
                    Err(err) => Err(err),
                }
            }
        }
    };
}

#[derive(Debug, Deserialize, Serialize)]
pub struct ListOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub prefix: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub cursor: Option<String>,
}

impl From<ListOptions> for JsValue {
    fn from(t: ListOptions) -> JsValue {
        JsValue::from_serde(&t).unwrap()
    }
}

impl From<JsValue> for ListOptions {
    fn from(t: JsValue) -> ListOptions {
        t.into_serde().unwrap()
    }
}