idb_sys/request/
database_request.rs

1use js_sys::Object;
2use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
3use web_sys::{DomException, Event, EventTarget, IdbOpenDbRequest, IdbVersionChangeEvent};
4
5use crate::{Database, Error, Request, RequestReadyState, Transaction, VersionChangeEvent};
6
7/// Request returned by [`Factory`](crate::Factory) when opening or deleting a database.
8#[derive(Debug)]
9pub struct DatabaseRequest {
10    inner: IdbOpenDbRequest,
11    success_callback: Option<Closure<dyn FnMut(Event)>>,
12    error_callback: Option<Closure<dyn FnMut(Event)>>,
13    blocked_callback: Option<Closure<dyn FnMut(IdbVersionChangeEvent)>>,
14    upgrade_needed_callback: Option<Closure<dyn FnMut(IdbVersionChangeEvent)>>,
15}
16
17impl DatabaseRequest {
18    /// Returns the database associated with this request
19    pub fn database(&self) -> Result<Database, Error> {
20        self.result().map(TryInto::try_into)?
21    }
22
23    /// Adds an event handler for `blocked` event.
24    pub fn on_blocked<F>(&mut self, callback: F)
25    where
26        F: FnOnce(VersionChangeEvent) + 'static,
27    {
28        let f = move |event: IdbVersionChangeEvent| {
29            let event = VersionChangeEvent::from(event);
30            callback(event);
31        };
32
33        let closure = Closure::once(f);
34
35        self.inner
36            .set_onblocked(Some(closure.as_ref().unchecked_ref()));
37        self.blocked_callback = Some(closure);
38    }
39
40    /// Adds an event handler for `upgradeneeded` event.
41    pub fn on_upgrade_needed<F>(&mut self, callback: F)
42    where
43        F: FnOnce(VersionChangeEvent) + 'static,
44    {
45        let f = move |event: IdbVersionChangeEvent| {
46            let event = VersionChangeEvent::from(event);
47            callback(event);
48        };
49
50        let closure = Closure::once(f);
51
52        self.inner
53            .set_onupgradeneeded(Some(closure.as_ref().unchecked_ref()));
54        self.upgrade_needed_callback = Some(closure);
55    }
56}
57
58impl Request for DatabaseRequest {
59    fn result(&self) -> Result<JsValue, Error> {
60        self.inner.result().map_err(Error::RequestResultNotFound)
61    }
62
63    fn error(&self) -> Result<Option<DomException>, Error> {
64        self.inner.error().map_err(Error::RequestErrorNotFound)
65    }
66
67    fn source(&self) -> Result<Object, Error> {
68        self.inner.source().ok_or(Error::RequestSourceNotFound)
69    }
70
71    fn transaction(&self) -> Option<Transaction> {
72        self.inner.transaction().map(Into::into)
73    }
74
75    fn ready_state(&self) -> Result<RequestReadyState, Error> {
76        self.inner.ready_state().try_into()
77    }
78
79    fn on_success<F>(&mut self, callback: F)
80    where
81        F: FnOnce(Event) + 'static,
82    {
83        let closure = Closure::once(callback);
84        self.inner
85            .set_onsuccess(Some(closure.as_ref().unchecked_ref()));
86        self.success_callback = Some(closure);
87    }
88
89    fn on_error<F>(&mut self, callback: F)
90    where
91        F: FnOnce(Event) + 'static,
92    {
93        let closure = Closure::once(callback);
94        self.inner
95            .set_onerror(Some(closure.as_ref().unchecked_ref()));
96        self.error_callback = Some(closure);
97    }
98}
99
100impl TryFrom<EventTarget> for DatabaseRequest {
101    type Error = Error;
102
103    fn try_from(target: EventTarget) -> Result<Self, Self::Error> {
104        let target: JsValue = target.into();
105        target
106            .dyn_into::<IdbOpenDbRequest>()
107            .map(Into::into)
108            .map_err(|value| Error::UnexpectedJsType("IdbOpenDbRequest", value))
109    }
110}
111
112impl From<IdbOpenDbRequest> for DatabaseRequest {
113    fn from(inner: IdbOpenDbRequest) -> Self {
114        Self {
115            inner,
116            success_callback: None,
117            error_callback: None,
118            blocked_callback: None,
119            upgrade_needed_callback: None,
120        }
121    }
122}
123
124impl From<DatabaseRequest> for IdbOpenDbRequest {
125    fn from(request: DatabaseRequest) -> Self {
126        request.inner
127    }
128}
129
130impl TryFrom<JsValue> for DatabaseRequest {
131    type Error = Error;
132
133    fn try_from(value: JsValue) -> Result<Self, Self::Error> {
134        value
135            .dyn_into::<IdbOpenDbRequest>()
136            .map(Into::into)
137            .map_err(|value| Error::UnexpectedJsType("IdbOpenDbRequest", value))
138    }
139}
140
141impl From<DatabaseRequest> for JsValue {
142    fn from(value: DatabaseRequest) -> Self {
143        value.inner.into()
144    }
145}