1use std::{fmt::Display, ops::Deref, panic::AssertUnwindSafe, time::Duration};
14
15use crate::{
16 container::Container,
17 date::Date,
18 env::{Env, EnvBinding},
19 error::Error,
20 request::Request,
21 response::Response,
22 Result, WebSocket,
23};
24
25use chrono::{DateTime, Utc};
26use futures_util::Future;
27use js_sys::{Map, Number, Object};
28use serde::{de::DeserializeOwned, Serialize};
29use wasm_bindgen::{prelude::*, JsCast};
30use worker_sys::{
31 DurableObject as EdgeDurableObject, DurableObjectId,
32 DurableObjectNamespace as EdgeObjectNamespace, DurableObjectState, DurableObjectStorage,
33 DurableObjectTransaction,
34};
35use wasm_bindgen_futures::{future_to_promise, JsFuture};
37
38#[derive(Debug)]
40pub struct Stub {
41 inner: EdgeDurableObject,
42}
43
44unsafe impl Send for Stub {}
45unsafe impl Sync for Stub {}
46
47impl Stub {
48 pub async fn fetch_with_request(&self, req: Request) -> Result<Response> {
50 let promise = self.inner.fetch_with_request(req.inner())?;
51 let response = JsFuture::from(promise).await?;
52 Ok(response.dyn_into::<web_sys::Response>()?.into())
53 }
54
55 pub async fn fetch_with_str(&self, url: &str) -> Result<Response> {
57 let promise = self.inner.fetch_with_str(url)?;
58 let response = JsFuture::from(promise).await?;
59 Ok(response.dyn_into::<web_sys::Response>()?.into())
60 }
61
62 pub fn into_rpc<T: JsCast>(self) -> T {
63 self.inner.unchecked_into()
64 }
65}
66
67#[derive(Debug, Clone)]
71pub struct ObjectNamespace {
72 inner: EdgeObjectNamespace,
73}
74
75unsafe impl Send for ObjectNamespace {}
76unsafe impl Sync for ObjectNamespace {}
77
78impl ObjectNamespace {
79 pub fn id_from_name(&self, name: &str) -> Result<ObjectId<'_>> {
82 self.inner
83 .id_from_name(name)
84 .map_err(Error::from)
85 .map(|id| ObjectId {
86 inner: id,
87 namespace: Some(self),
88 })
89 }
90
91 pub fn id_from_string(&self, hex_id: &str) -> Result<ObjectId<'_>> {
100 self.inner
101 .id_from_string(hex_id)
102 .map_err(Error::from)
103 .map(|id| ObjectId {
104 inner: id,
105 namespace: Some(self),
106 })
107 }
108
109 pub fn unique_id(&self) -> Result<ObjectId<'_>> {
113 self.inner
114 .new_unique_id()
115 .map_err(Error::from)
116 .map(|id| ObjectId {
117 inner: id,
118 namespace: Some(self),
119 })
120 }
121
122 pub fn unique_id_with_jurisdiction(&self, jd: &str) -> Result<ObjectId<'_>> {
132 let options = Object::new();
133 js_sys::Reflect::set(&options, &JsValue::from("jurisdiction"), &jd.into())?;
134 self.inner
135 .new_unique_id_with_options(&options)
136 .map_err(Error::from)
137 .map(|id| ObjectId {
138 inner: id,
139 namespace: Some(self),
140 })
141 }
142
143 pub fn get_by_name(&self, name: &str) -> Result<Stub> {
146 self.inner
147 .get_by_name(name)
148 .map_err(Error::from)
149 .map(|stub| Stub { inner: stub })
150 }
151
152 pub fn get_by_name_with_location_hint(&self, name: &str, location_hint: &str) -> Result<Stub> {
156 let options = Object::new();
157 js_sys::Reflect::set(
158 &options,
159 &JsValue::from("locationHint"),
160 &location_hint.into(),
161 )?;
162 self.inner
163 .get_by_name_with_options(name, &options)
164 .map_err(Error::from)
165 .map(|stub| Stub { inner: stub })
166 }
167}
168
169#[derive(Debug)]
172pub struct ObjectId<'a> {
173 inner: DurableObjectId,
174 namespace: Option<&'a ObjectNamespace>,
175}
176
177impl ObjectId<'_> {
178 pub fn get_stub(&self) -> Result<Stub> {
180 self.namespace
181 .ok_or_else(|| JsValue::from("Cannot get stub from within a Durable Object"))
182 .and_then(|n| {
183 Ok(Stub {
184 inner: n.inner.get(&self.inner)?,
185 })
186 })
187 .map_err(Error::from)
188 }
189
190 pub fn get_stub_with_location_hint(&self, location_hint: &str) -> Result<Stub> {
191 let options = Object::new();
192 js_sys::Reflect::set(
193 &options,
194 &JsValue::from("locationHint"),
195 &location_hint.into(),
196 )?;
197
198 self.namespace
199 .ok_or_else(|| JsValue::from("Cannot get stub from within a Durable Object"))
200 .and_then(|n| {
201 Ok(Stub {
202 inner: n.inner.get_with_options(&self.inner, &options)?,
203 })
204 })
205 .map_err(Error::from)
206 }
207
208 pub fn name(&self) -> Option<String> {
212 self.inner.name()
213 }
214}
215
216impl PartialEq for ObjectId<'_> {
217 fn eq(&self, other: &Self) -> bool {
220 self.inner.equals(&other.inner)
221 }
222}
223
224impl Display for ObjectId<'_> {
225 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
226 write!(
227 f,
228 "{}",
229 self.inner.to_string().map_err(|_| { std::fmt::Error })?
230 )
231 }
232}
233
234#[derive(Debug)]
237pub struct State {
238 inner: DurableObjectState,
239}
240
241impl State {
242 pub fn id(&self) -> ObjectId<'_> {
245 ObjectId {
246 inner: self.inner.id().unwrap(),
247 namespace: None,
248 }
249 }
250
251 pub fn storage(&self) -> Storage {
254 Storage {
255 inner: self.inner.storage().unwrap(),
256 }
257 }
258
259 pub fn container(&self) -> Option<Container> {
260 self.inner.container().map(|inner| Container { inner })
261 }
262
263 pub fn wait_until<F>(&self, future: F)
264 where
265 F: Future<Output = ()> + 'static,
266 {
267 self.inner
268 .wait_until(&future_to_promise(AssertUnwindSafe(async {
269 future.await;
270 Ok(JsValue::UNDEFINED)
271 })))
272 .unwrap()
273 }
274
275 pub fn _inner(self) -> DurableObjectState {
277 self.inner
278 }
279
280 pub fn accept_web_socket(&self, ws: &WebSocket) {
281 self.inner.accept_websocket(ws.as_ref()).unwrap()
282 }
283
284 pub fn accept_websocket_with_tags(&self, ws: &WebSocket, tags: &[&str]) {
285 let tags = tags.iter().map(|it| (*it).into()).collect();
286
287 self.inner
288 .accept_websocket_with_tags(ws.as_ref(), tags)
289 .unwrap();
290 }
291
292 pub fn get_websockets(&self) -> Vec<WebSocket> {
293 self.inner
294 .get_websockets()
295 .unwrap()
296 .into_iter()
297 .map(Into::into)
298 .collect()
299 }
300
301 pub fn get_websockets_with_tag(&self, tag: &str) -> Vec<WebSocket> {
302 self.inner
303 .get_websockets_with_tag(tag)
304 .unwrap()
305 .into_iter()
306 .map(Into::into)
307 .collect()
308 }
309
310 pub fn get_tags(&self, websocket: &WebSocket) -> Vec<String> {
312 self.inner.get_tags(websocket.as_ref()).unwrap()
313 }
314
315 pub fn set_websocket_auto_response(&self, pair: &worker_sys::WebSocketRequestResponsePair) {
316 self.inner.set_websocket_auto_response(pair).unwrap();
317 }
318
319 pub fn get_websocket_auto_response(&self) -> Option<worker_sys::WebSocketRequestResponsePair> {
320 self.inner.get_websocket_auto_response().unwrap()
321 }
322}
323
324impl From<DurableObjectState> for State {
325 fn from(o: DurableObjectState) -> Self {
326 Self { inner: o }
327 }
328}
329
330pub struct Storage {
334 inner: DurableObjectStorage,
335}
336
337impl core::fmt::Debug for Storage {
338 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
339 f.debug_struct("Storage").finish()
340 }
341}
342
343impl Storage {
344 pub async fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>> {
349 let res = match JsFuture::from(self.inner.get(key)?).await {
350 Ok(val) if val.is_undefined() => Ok(None),
352 Ok(val) => {
354 serde_wasm_bindgen::from_value(val).map_err(|e| JsValue::from(e.to_string()))
355 }
356 Err(e) => Err(e),
358 };
359
360 res.map_err(Error::from)
361 }
362
363 pub async fn get_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<Map> {
365 let keys = self.inner.get_multiple(
366 keys.into_iter()
367 .map(|key| JsValue::from(key.deref()))
368 .collect(),
369 )?;
370 let keys = JsFuture::from(keys).await?;
371 keys.dyn_into::<Map>().map_err(Error::from)
372 }
373
374 pub async fn put<T: Serialize>(&self, key: &str, value: T) -> Result<()> {
376 self.put_raw(key, serde_wasm_bindgen::to_value(&value)?)
377 .await
378 }
379
380 pub async fn put_raw(&self, key: &str, value: impl Into<JsValue>) -> Result<()> {
381 JsFuture::from(self.inner.put(key, value.into())?)
382 .await
383 .map_err(Error::from)
384 .map(|_| ())
385 }
386
387 pub async fn put_multiple<T: Serialize>(&self, values: T) -> Result<()> {
389 let values = serde_wasm_bindgen::to_value(&values)?;
390 if !values.is_object() {
391 return Err("Must pass in a struct type".to_string().into());
392 }
393 self.put_multiple_raw(values.dyn_into().unwrap()).await
394 }
395
396 pub async fn put_multiple_raw(&self, values: Object) -> Result<()> {
410 JsFuture::from(self.inner.put_multiple(values.into())?)
411 .await
412 .map_err(Error::from)
413 .map(|_| ())
414 }
415
416 pub async fn delete(&self, key: &str) -> Result<bool> {
418 let fut: JsFuture = self.inner.delete(key)?.into();
419 fut.await
420 .and_then(|jsv| {
421 jsv.as_bool()
422 .ok_or_else(|| JsValue::from("Promise did not return bool"))
423 })
424 .map_err(Error::from)
425 }
426
427 pub async fn delete_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<usize> {
430 let fut: JsFuture = self
431 .inner
432 .delete_multiple(
433 keys.into_iter()
434 .map(|key| JsValue::from(key.deref()))
435 .collect(),
436 )?
437 .into();
438 fut.await
439 .and_then(|jsv| {
440 jsv.as_f64()
441 .map(|f| f as usize)
442 .ok_or_else(|| JsValue::from("Promise did not return number"))
443 })
444 .map_err(Error::from)
445 }
446
447 pub async fn delete_all(&self) -> Result<()> {
451 let fut: JsFuture = self.inner.delete_all()?.into();
452 fut.await.map(|_| ()).map_err(Error::from)
453 }
454
455 pub async fn list(&self) -> Result<Map> {
463 let fut: JsFuture = self.inner.list()?.into();
464 fut.await
465 .and_then(|jsv| jsv.dyn_into())
466 .map_err(Error::from)
467 }
468
469 pub async fn list_with_options(&self, opts: ListOptions<'_>) -> Result<Map> {
472 let fut: JsFuture = self
473 .inner
474 .list_with_options(serde_wasm_bindgen::to_value(&opts)?.into())?
475 .into();
476 fut.await
477 .and_then(|jsv| jsv.dyn_into())
478 .map_err(Error::from)
479 }
480
481 pub async fn get_alarm(&self) -> Result<Option<i64>> {
485 let fut: JsFuture = self.inner.get_alarm(JsValue::NULL.into())?.into();
486 fut.await
487 .map(|jsv| jsv.as_f64().map(|f| f as i64))
488 .map_err(Error::from)
489 }
490
491 pub async fn get_alarm_with_options(&self, options: GetAlarmOptions) -> Result<Option<i64>> {
492 let fut: JsFuture = self
493 .inner
494 .get_alarm(serde_wasm_bindgen::to_value(&options)?.into())?
495 .into();
496 fut.await
497 .map(|jsv| jsv.as_f64().map(|f| f as i64))
498 .map_err(Error::from)
499 }
500
501 pub async fn set_alarm(&self, scheduled_time: impl Into<ScheduledTime>) -> Result<()> {
510 let fut: JsFuture = self
511 .inner
512 .set_alarm(scheduled_time.into().schedule(), JsValue::NULL.into())?
513 .into();
514 fut.await.map(|_| ()).map_err(Error::from)
515 }
516
517 pub async fn set_alarm_with_options(
518 &self,
519 scheduled_time: impl Into<ScheduledTime>,
520 options: SetAlarmOptions,
521 ) -> Result<()> {
522 let fut: JsFuture = self
523 .inner
524 .set_alarm(
525 scheduled_time.into().schedule(),
526 serde_wasm_bindgen::to_value(&options)?.into(),
527 )?
528 .into();
529 fut.await.map(|_| ()).map_err(Error::from)
530 }
531
532 pub async fn delete_alarm(&self) -> Result<()> {
535 let fut: JsFuture = self.inner.delete_alarm(JsValue::NULL.into())?.into();
536 fut.await.map(|_| ()).map_err(Error::from)
537 }
538
539 pub async fn delete_alarm_with_options(&self, options: SetAlarmOptions) -> Result<()> {
540 let fut: JsFuture = self
541 .inner
542 .delete_alarm(serde_wasm_bindgen::to_value(&options)?.into())?
543 .into();
544 fut.await.map(|_| ()).map_err(Error::from)
545 }
546
547 pub async fn transaction<F, Fut>(&self, closure: F) -> Result<()>
548 where
549 F: FnOnce(Transaction) -> Fut + 'static,
550 Fut: Future<Output = Result<()>> + 'static,
551 {
552 let inner: Box<dyn FnOnce(DurableObjectTransaction) -> js_sys::Promise> =
553 Box::new(move |t: DurableObjectTransaction| -> js_sys::Promise {
554 future_to_promise(AssertUnwindSafe(async move {
555 closure(Transaction { inner: t })
556 .await
557 .map_err(JsValue::from)
558 .map(|_| JsValue::NULL)
559 }))
560 });
561 let clos = wasm_bindgen::closure::Closure::once_assert_unwind_safe(inner);
562 JsFuture::from(self.inner.transaction(&clos)?)
563 .await
564 .map_err(Error::from)
565 .map(|_| ())
566 }
567
568 pub fn sql(&self) -> crate::sql::SqlStorage {
570 crate::sql::SqlStorage::new(self.inner.sql())
571 }
572}
573
574#[derive(Debug)]
575pub struct Transaction {
576 inner: DurableObjectTransaction,
577}
578
579impl Transaction {
580 pub async fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T> {
581 JsFuture::from(self.inner.get(key)?)
582 .await
583 .and_then(|val| {
584 if val.is_undefined() {
585 Err(JsValue::from("No such value in storage."))
586 } else {
587 serde_wasm_bindgen::from_value(val).map_err(std::convert::Into::into)
588 }
589 })
590 .map_err(Error::from)
591 }
592
593 pub async fn get_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<Map> {
594 let keys = self.inner.get_multiple(
595 keys.into_iter()
596 .map(|key| JsValue::from(key.deref()))
597 .collect(),
598 )?;
599 let keys = JsFuture::from(keys).await?;
600 keys.dyn_into::<Map>().map_err(Error::from)
601 }
602
603 pub async fn put<T: Serialize>(&self, key: &str, value: T) -> Result<()> {
604 JsFuture::from(self.inner.put(key, serde_wasm_bindgen::to_value(&value)?)?)
605 .await
606 .map_err(Error::from)
607 .map(|_| ())
608 }
609
610 pub async fn put_multiple<T: Serialize>(&self, values: T) -> Result<()> {
612 let values = serde_wasm_bindgen::to_value(&values)?;
613 if !values.is_object() {
614 return Err("Must pass in a struct type".to_string().into());
615 }
616 JsFuture::from(self.inner.put_multiple(values)?)
617 .await
618 .map_err(Error::from)
619 .map(|_| ())
620 }
621
622 pub async fn delete(&self, key: &str) -> Result<bool> {
623 let fut: JsFuture = self.inner.delete(key)?.into();
624 fut.await
625 .and_then(|jsv| {
626 jsv.as_bool()
627 .ok_or_else(|| JsValue::from("Promise did not return bool"))
628 })
629 .map_err(Error::from)
630 }
631
632 pub async fn delete_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<usize> {
633 let fut: JsFuture = self
634 .inner
635 .delete_multiple(
636 keys.into_iter()
637 .map(|key| JsValue::from(key.deref()))
638 .collect(),
639 )?
640 .into();
641 fut.await
642 .and_then(|jsv| {
643 jsv.as_f64()
644 .map(|f| f as usize)
645 .ok_or_else(|| JsValue::from("Promise did not return number"))
646 })
647 .map_err(Error::from)
648 }
649
650 pub async fn delete_all(&self) -> Result<()> {
651 let fut: JsFuture = self.inner.delete_all()?.into();
652 fut.await.map(|_| ()).map_err(Error::from)
653 }
654
655 pub async fn list(&self) -> Result<Map> {
656 let fut: JsFuture = self.inner.list()?.into();
657 fut.await
658 .and_then(|jsv| jsv.dyn_into())
659 .map_err(Error::from)
660 }
661
662 pub async fn list_with_options(&self, opts: ListOptions<'_>) -> Result<Map> {
663 let fut: JsFuture = self
664 .inner
665 .list_with_options(serde_wasm_bindgen::to_value(&opts)?.into())?
666 .into();
667 fut.await
668 .and_then(|jsv| jsv.dyn_into())
669 .map_err(Error::from)
670 }
671
672 pub fn rollback(&self) -> Result<()> {
673 self.inner.rollback().map_err(Error::from)
674 }
675}
676
677#[derive(Default, Serialize, Debug)]
678pub struct ListOptions<'a> {
679 #[serde(skip_serializing_if = "Option::is_none")]
681 start: Option<&'a str>,
682 #[serde(skip_serializing_if = "Option::is_none")]
684 end: Option<&'a str>,
685 #[serde(skip_serializing_if = "Option::is_none")]
687 prefix: Option<&'a str>,
688 #[serde(skip_serializing_if = "Option::is_none")]
691 reverse: Option<bool>,
692 #[serde(skip_serializing_if = "Option::is_none")]
694 limit: Option<usize>,
695}
696
697impl<'a> ListOptions<'a> {
698 pub fn new() -> Self {
700 Default::default()
701 }
702
703 pub fn start(mut self, val: &'a str) -> Self {
705 self.start = Some(val);
706 self
707 }
708
709 pub fn end(mut self, val: &'a str) -> Self {
711 self.end = Some(val);
712 self
713 }
714
715 pub fn prefix(mut self, val: &'a str) -> Self {
717 self.prefix = Some(val);
718 self
719 }
720
721 pub fn reverse(mut self, val: bool) -> Self {
724 self.reverse = Some(val);
725 self
726 }
727
728 pub fn limit(mut self, val: usize) -> Self {
730 self.limit = Some(val);
731 self
732 }
733}
734#[derive(Debug)]
735enum ScheduledTimeInit {
736 Date(js_sys::Date),
737 Offset(f64),
738}
739
740#[derive(Debug)]
750pub struct ScheduledTime {
751 init: ScheduledTimeInit,
752}
753
754impl ScheduledTime {
755 pub fn new(date: js_sys::Date) -> Self {
756 Self {
757 init: ScheduledTimeInit::Date(date),
758 }
759 }
760
761 fn schedule(self) -> js_sys::Date {
762 match self.init {
763 ScheduledTimeInit::Date(date) => date,
764 ScheduledTimeInit::Offset(offset_ms) => {
765 let now = Date::now().as_millis() as f64;
766 js_sys::Date::new(&Number::from(now + offset_ms))
767 }
768 }
769 }
770}
771
772impl From<i64> for ScheduledTime {
773 fn from(offset_ms: i64) -> Self {
774 ScheduledTime {
775 init: ScheduledTimeInit::Offset(offset_ms as f64),
776 }
777 }
778}
779
780impl From<DateTime<Utc>> for ScheduledTime {
781 fn from(date: DateTime<Utc>) -> Self {
782 ScheduledTime {
783 init: ScheduledTimeInit::Date(js_sys::Date::new(&Number::from(
784 date.timestamp_millis() as f64,
785 ))),
786 }
787 }
788}
789
790impl From<Duration> for ScheduledTime {
791 fn from(offset: Duration) -> Self {
792 ScheduledTime {
793 init: ScheduledTimeInit::Offset(offset.as_millis() as f64),
794 }
795 }
796}
797
798#[derive(Debug, Clone, Default, Serialize)]
799pub struct GetAlarmOptions {
800 #[serde(skip_serializing_if = "Option::is_none")]
801 pub allow_concurrency: Option<bool>,
802}
803
804#[derive(Debug, Clone, Default, Serialize)]
805pub struct SetAlarmOptions {
806 #[serde(skip_serializing_if = "Option::is_none")]
807 pub allow_concurrency: Option<bool>,
808 #[serde(skip_serializing_if = "Option::is_none")]
809 pub allow_unconfirmed: Option<bool>,
810}
811
812impl EnvBinding for ObjectNamespace {
813 const TYPE_NAME: &'static str = "DurableObjectNamespace";
814}
815
816impl JsCast for ObjectNamespace {
817 fn instanceof(val: &JsValue) -> bool {
818 val.is_instance_of::<EdgeObjectNamespace>()
819 }
820
821 fn unchecked_from_js(val: JsValue) -> Self {
822 Self { inner: val.into() }
823 }
824
825 fn unchecked_from_js_ref(val: &JsValue) -> &Self {
826 unsafe { &*(val as *const JsValue as *const Self) }
827 }
828}
829
830impl From<ObjectNamespace> for JsValue {
831 fn from(ns: ObjectNamespace) -> Self {
832 JsValue::from(ns.inner)
833 }
834}
835
836impl AsRef<JsValue> for ObjectNamespace {
837 fn as_ref(&self) -> &JsValue {
838 &self.inner
839 }
840}
841
842#[derive(Debug)]
843pub enum WebSocketIncomingMessage {
844 String(String),
845 Binary(Vec<u8>),
846}
847
848#[allow(async_fn_in_trait)] pub trait DurableObject: has_durable_object_attribute {
884 fn new(state: State, env: Env) -> Self;
885
886 async fn fetch(&self, req: Request) -> Result<Response>;
887
888 #[allow(clippy::diverging_sub_expression)]
889 async fn alarm(&self) -> Result<Response> {
890 worker_sys::console_error!("alarm() handler not implemented");
891 unimplemented!("alarm() handler")
892 }
893
894 #[allow(unused_variables, clippy::diverging_sub_expression)]
895 async fn websocket_message(
896 &self,
897 ws: WebSocket,
898 message: WebSocketIncomingMessage,
899 ) -> Result<()> {
900 worker_sys::console_error!("websocket_message() handler not implemented");
901 unimplemented!("websocket_message() handler")
902 }
903
904 #[allow(unused_variables, clippy::diverging_sub_expression)]
905 async fn websocket_close(
906 &self,
907 ws: WebSocket,
908 code: usize,
909 reason: String,
910 was_clean: bool,
911 ) -> Result<()> {
912 worker_sys::console_error!("websocket_close() handler not implemented");
913 unimplemented!("websocket_close() handler")
914 }
915
916 #[allow(unused_variables, clippy::diverging_sub_expression)]
917 async fn websocket_error(&self, ws: WebSocket, error: Error) -> Result<()> {
918 worker_sys::console_error!("websocket_error() handler not implemented");
919 unimplemented!("websocket_error() handler")
920 }
921}
922
923#[doc(hidden)]
924#[allow(non_camel_case_types)]
925pub trait has_durable_object_attribute {}