branch: main
durable.rs
32475 bytesRaw
//! Durable Objects provide low-latency coordination and consistent storage for the Workers platform.
//! A given namespace can support essentially unlimited Durable Objects, with each Object having
//! access to a transactional, key-value storage API.
//!
//! Durable Objects consist of two components: a class that defines a template for creating Durable
//! Objects and a Workers script that instantiates and uses those Durable Objects.
//!
//! The class and the Workers script are linked together with a binding.
//!
//! [Learn more](https://developers.cloudflare.com/workers/learning/using-durable-objects) about
//! using Durable Objects.

use std::{fmt::Display, ops::Deref, panic::AssertUnwindSafe, time::Duration};

use crate::{
    container::Container,
    date::Date,
    env::{Env, EnvBinding},
    error::Error,
    request::Request,
    response::Response,
    Result, WebSocket,
};

use chrono::{DateTime, Utc};
use futures_util::Future;
use js_sys::{Map, Number, Object};
use serde::{de::DeserializeOwned, Serialize};
use wasm_bindgen::{prelude::*, JsCast};
use worker_sys::{
    DurableObject as EdgeDurableObject, DurableObjectId,
    DurableObjectNamespace as EdgeObjectNamespace, DurableObjectState, DurableObjectStorage,
    DurableObjectTransaction,
};
// use wasm_bindgen_futures::future_to_promise;
use wasm_bindgen_futures::{future_to_promise, JsFuture};

/// A Durable Object stub is a client object used to send requests to a remote Durable Object.
#[derive(Debug)]
pub struct Stub {
    inner: EdgeDurableObject,
}

unsafe impl Send for Stub {}
unsafe impl Sync for Stub {}

impl Stub {
    /// Send an internal Request to the Durable Object to which the stub points.
    pub async fn fetch_with_request(&self, req: Request) -> Result<Response> {
        let promise = self.inner.fetch_with_request(req.inner())?;
        let response = JsFuture::from(promise).await?;
        Ok(response.dyn_into::<web_sys::Response>()?.into())
    }

    /// Construct a Request from a URL to the Durable Object to which the stub points.
    pub async fn fetch_with_str(&self, url: &str) -> Result<Response> {
        let promise = self.inner.fetch_with_str(url)?;
        let response = JsFuture::from(promise).await?;
        Ok(response.dyn_into::<web_sys::Response>()?.into())
    }

    pub fn into_rpc<T: JsCast>(self) -> T {
        self.inner.unchecked_into()
    }
}

/// Use an ObjectNamespace to get access to Stubs for communication with a Durable Object instance.
/// A given namespace can support essentially unlimited Durable Objects, with each Object having
/// access to a transactional, key-value storage API.
#[derive(Debug, Clone)]
pub struct ObjectNamespace {
    inner: EdgeObjectNamespace,
}

unsafe impl Send for ObjectNamespace {}
unsafe impl Sync for ObjectNamespace {}

impl ObjectNamespace {
    /// This method derives a unique object ID from the given name string. It will always return the
    /// same ID when given the same name as input.
    pub fn id_from_name(&self, name: &str) -> Result<ObjectId<'_>> {
        self.inner
            .id_from_name(name)
            .map_err(Error::from)
            .map(|id| ObjectId {
                inner: id,
                namespace: Some(self),
            })
    }

    /// This method parses an ID that was previously stringified. This is useful in particular with
    /// IDs created using `unique_id(&self)`, as these IDs need to be stored somewhere, probably as
    // as a string.
    ///
    /// A stringified object ID is a 64-digit hexadecimal number. However, not all 64-digit hex
    /// numbers are valid IDs. This method will throw if it is passed an ID that was not originally
    /// created by newUniqueId() or idFromName(). It will also throw if the ID was originally
    /// created for a different namespace.
    pub fn id_from_string(&self, hex_id: &str) -> Result<ObjectId<'_>> {
        self.inner
            .id_from_string(hex_id)
            .map_err(Error::from)
            .map(|id| ObjectId {
                inner: id,
                namespace: Some(self),
            })
    }

    /// Creates a new object ID randomly. This method will never return the same ID twice, and thus
    /// it is guaranteed that the object does not yet exist and has never existed at the time the
    /// method returns.
    pub fn unique_id(&self) -> Result<ObjectId<'_>> {
        self.inner
            .new_unique_id()
            .map_err(Error::from)
            .map(|id| ObjectId {
                inner: id,
                namespace: Some(self),
            })
    }

    /// Durable Objects can be created so that they only run and store data within a specific
    /// jurisdiction to comply with local regulations. You must specify the jurisdiction when
    /// generating the Durable Object's id.
    ///
    /// Jurisdiction constraints can only be used with ids created by `unique_id()` and are not
    /// currently compatible with ids created by `id_from_name()`.
    ///
    /// See supported jurisdictions and more documentation at:
    /// <https://developers.cloudflare.com/durable-objects/reference/data-location/#restrict-durable-objects-to-a-jurisdiction>
    pub fn unique_id_with_jurisdiction(&self, jd: &str) -> Result<ObjectId<'_>> {
        let options = Object::new();
        js_sys::Reflect::set(&options, &JsValue::from("jurisdiction"), &jd.into())?;
        self.inner
            .new_unique_id_with_options(&options)
            .map_err(Error::from)
            .map(|id| ObjectId {
                inner: id,
                namespace: Some(self),
            })
    }

    /// Get a Durable Object stub directly by name. This combines the functionality of
    /// `id_from_name()` and `get_stub()` into a single method call.
    pub fn get_by_name(&self, name: &str) -> Result<Stub> {
        self.inner
            .get_by_name(name)
            .map_err(Error::from)
            .map(|stub| Stub { inner: stub })
    }

    /// Get a Durable Object stub directly by name with options (such as location hints).
    /// This combines the functionality of `id_from_name()` and `get_stub_with_location_hint()`
    /// into a single method call.
    pub fn get_by_name_with_location_hint(&self, name: &str, location_hint: &str) -> Result<Stub> {
        let options = Object::new();
        js_sys::Reflect::set(
            &options,
            &JsValue::from("locationHint"),
            &location_hint.into(),
        )?;
        self.inner
            .get_by_name_with_options(name, &options)
            .map_err(Error::from)
            .map(|stub| Stub { inner: stub })
    }
}

/// An ObjectId is used to identify, locate, and access a Durable Object via interaction with its
/// Stub.
#[derive(Debug)]
pub struct ObjectId<'a> {
    inner: DurableObjectId,
    namespace: Option<&'a ObjectNamespace>,
}

impl ObjectId<'_> {
    /// Get a Stub for the Durable Object instance identified by this ObjectId.
    pub fn get_stub(&self) -> Result<Stub> {
        self.namespace
            .ok_or_else(|| JsValue::from("Cannot get stub from within a Durable Object"))
            .and_then(|n| {
                Ok(Stub {
                    inner: n.inner.get(&self.inner)?,
                })
            })
            .map_err(Error::from)
    }

    pub fn get_stub_with_location_hint(&self, location_hint: &str) -> Result<Stub> {
        let options = Object::new();
        js_sys::Reflect::set(
            &options,
            &JsValue::from("locationHint"),
            &location_hint.into(),
        )?;

        self.namespace
            .ok_or_else(|| JsValue::from("Cannot get stub from within a Durable Object"))
            .and_then(|n| {
                Ok(Stub {
                    inner: n.inner.get_with_options(&self.inner, &options)?,
                })
            })
            .map_err(Error::from)
    }

    /// The name that was used to create the `ObjectId` via [`id_from_name`](https://developers.cloudflare.com/durable-objects/api/namespace/#idfromname).
    /// `None` is returned if the `ObjectId` was constructed using [`unique_id`](https://developers.cloudflare.com/durable-objects/api/namespace/#newuniqueid).
    /// `None` is also returned within the Durable Object constructor, as the `name` property is not accessible there (see <https://github.com/cloudflare/workerd/issues/2240>).
    pub fn name(&self) -> Option<String> {
        self.inner.name()
    }
}

impl PartialEq for ObjectId<'_> {
    /// Compare equality between two ObjectIds using [`equals`](<https://developers.cloudflare.com/durable-objects/api/id/#equals>).
    /// <div class="warning">The equality check ignores the namespace.</div>
    fn eq(&self, other: &Self) -> bool {
        self.inner.equals(&other.inner)
    }
}

impl Display for ObjectId<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        write!(
            f,
            "{}",
            self.inner.to_string().map_err(|_| { std::fmt::Error })?
        )
    }
}

/// Passed from the runtime to provide access to the Durable Object's storage as well as various
/// metadata about the Object.
#[derive(Debug)]
pub struct State {
    inner: DurableObjectState,
}

impl State {
    /// The ID of this Durable Object which can be converted into a hex string using its `to_string()`
    /// method.
    pub fn id(&self) -> ObjectId<'_> {
        ObjectId {
            inner: self.inner.id().unwrap(),
            namespace: None,
        }
    }

    /// Contains methods for accessing persistent storage via the transactional storage API. See
    /// [Transactional Storage API](https://developers.cloudflare.com/workers/runtime-apis/durable-objects#transactional-storage-api) for a detailed reference.
    pub fn storage(&self) -> Storage {
        Storage {
            inner: self.inner.storage().unwrap(),
        }
    }

    pub fn container(&self) -> Option<Container> {
        self.inner.container().map(|inner| Container { inner })
    }

    pub fn wait_until<F>(&self, future: F)
    where
        F: Future<Output = ()> + 'static,
    {
        self.inner
            .wait_until(&future_to_promise(AssertUnwindSafe(async {
                future.await;
                Ok(JsValue::UNDEFINED)
            })))
            .unwrap()
    }

    // needs to be accessed by the `#[durable_object]` macro in a conversion step
    pub fn _inner(self) -> DurableObjectState {
        self.inner
    }

    pub fn accept_web_socket(&self, ws: &WebSocket) {
        self.inner.accept_websocket(ws.as_ref()).unwrap()
    }

    pub fn accept_websocket_with_tags(&self, ws: &WebSocket, tags: &[&str]) {
        let tags = tags.iter().map(|it| (*it).into()).collect();

        self.inner
            .accept_websocket_with_tags(ws.as_ref(), tags)
            .unwrap();
    }

    pub fn get_websockets(&self) -> Vec<WebSocket> {
        self.inner
            .get_websockets()
            .unwrap()
            .into_iter()
            .map(Into::into)
            .collect()
    }

    pub fn get_websockets_with_tag(&self, tag: &str) -> Vec<WebSocket> {
        self.inner
            .get_websockets_with_tag(tag)
            .unwrap()
            .into_iter()
            .map(Into::into)
            .collect()
    }

    /// Retrieve tags from a hibernatable websocket
    pub fn get_tags(&self, websocket: &WebSocket) -> Vec<String> {
        self.inner.get_tags(websocket.as_ref()).unwrap()
    }

    pub fn set_websocket_auto_response(&self, pair: &worker_sys::WebSocketRequestResponsePair) {
        self.inner.set_websocket_auto_response(pair).unwrap();
    }

    pub fn get_websocket_auto_response(&self) -> Option<worker_sys::WebSocketRequestResponsePair> {
        self.inner.get_websocket_auto_response().unwrap()
    }
}

impl From<DurableObjectState> for State {
    fn from(o: DurableObjectState) -> Self {
        Self { inner: o }
    }
}

/// Access a Durable Object's Storage API. Each method is implicitly wrapped inside a transaction,
/// such that its results are atomic and isolated from all other storage operations, even when
/// accessing multiple key-value pairs.
pub struct Storage {
    inner: DurableObjectStorage,
}

impl core::fmt::Debug for Storage {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Storage").finish()
    }
}

impl Storage {
    /// Retrieves the value associated with the given key. The type of the returned value will be
    /// whatever was previously written for the key.
    ///
    /// Returns `Ok(None)` if the key does not exist.
    pub async fn get<T: DeserializeOwned>(&self, key: &str) -> Result<Option<T>> {
        let res = match JsFuture::from(self.inner.get(key)?).await {
            // If we successfully retrived `undefined`, that means the key doesn't exist
            Ok(val) if val.is_undefined() => Ok(None),
            // Otherwise deserialize whatever we successfully received
            Ok(val) => {
                serde_wasm_bindgen::from_value(val).map_err(|e| JsValue::from(e.to_string()))
            }
            // Forward any error, rewrap to make the typechecker happy
            Err(e) => Err(e),
        };

        res.map_err(Error::from)
    }

    /// Retrieves the values associated with each of the provided keys.
    pub async fn get_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<Map> {
        let keys = self.inner.get_multiple(
            keys.into_iter()
                .map(|key| JsValue::from(key.deref()))
                .collect(),
        )?;
        let keys = JsFuture::from(keys).await?;
        keys.dyn_into::<Map>().map_err(Error::from)
    }

    /// Stores the value and associates it with the given key.
    pub async fn put<T: Serialize>(&self, key: &str, value: T) -> Result<()> {
        self.put_raw(key, serde_wasm_bindgen::to_value(&value)?)
            .await
    }

    pub async fn put_raw(&self, key: &str, value: impl Into<JsValue>) -> Result<()> {
        JsFuture::from(self.inner.put(key, value.into())?)
            .await
            .map_err(Error::from)
            .map(|_| ())
    }

    /// Takes a serializable struct and stores each of its keys and values to storage.
    pub async fn put_multiple<T: Serialize>(&self, values: T) -> Result<()> {
        let values = serde_wasm_bindgen::to_value(&values)?;
        if !values.is_object() {
            return Err("Must pass in a struct type".to_string().into());
        }
        self.put_multiple_raw(values.dyn_into().unwrap()).await
    }

    /// Takes an object and stores each of its keys and values to storage.
    ///
    /// ```no_run
    /// # use worker::Storage;
    /// use worker::JsValue;
    ///
    /// # let storage: Storage = todo!();
    ///
    /// let obj = js_sys::Object::new();
    /// js_sys::Reflect::set(&obj, &JsValue::from_str("foo"), JsValue::from_u64(1));
    ///
    /// storage.put_multiple_raw(obj);
    /// ```
    pub async fn put_multiple_raw(&self, values: Object) -> Result<()> {
        JsFuture::from(self.inner.put_multiple(values.into())?)
            .await
            .map_err(Error::from)
            .map(|_| ())
    }

    /// Deletes the key and associated value. Returns true if the key existed or false if it didn't.
    pub async fn delete(&self, key: &str) -> Result<bool> {
        let fut: JsFuture = self.inner.delete(key)?.into();
        fut.await
            .and_then(|jsv| {
                jsv.as_bool()
                    .ok_or_else(|| JsValue::from("Promise did not return bool"))
            })
            .map_err(Error::from)
    }

    /// Deletes the provided keys and their associated values. Returns a count of the number of
    /// key-value pairs deleted.
    pub async fn delete_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<usize> {
        let fut: JsFuture = self
            .inner
            .delete_multiple(
                keys.into_iter()
                    .map(|key| JsValue::from(key.deref()))
                    .collect(),
            )?
            .into();
        fut.await
            .and_then(|jsv| {
                jsv.as_f64()
                    .map(|f| f as usize)
                    .ok_or_else(|| JsValue::from("Promise did not return number"))
            })
            .map_err(Error::from)
    }

    /// Deletes all keys and associated values, effectively deallocating all storage used by the
    /// Durable Object. In the event of a failure while the operation is still in flight, it may be
    /// that only a subset of the data is properly deleted.
    pub async fn delete_all(&self) -> Result<()> {
        let fut: JsFuture = self.inner.delete_all()?.into();
        fut.await.map(|_| ()).map_err(Error::from)
    }

    /// Returns all keys and values associated with the current Durable Object in ascending
    /// lexicographic sorted order.
    ///
    /// Be aware of how much data may be stored in your Durable Object before calling this version
    /// of list without options, because it will all be loaded into the Durable Object's memory,
    /// potentially hitting its [limit](https://developers.cloudflare.com/workers/platform/limits#durable-objects-limits).
    /// If that is a concern, use the alternate `list_with_options()` method.
    pub async fn list(&self) -> Result<Map> {
        let fut: JsFuture = self.inner.list()?.into();
        fut.await
            .and_then(|jsv| jsv.dyn_into())
            .map_err(Error::from)
    }

    /// Returns keys associated with the current Durable Object according to the parameters in the
    /// provided options object.
    pub async fn list_with_options(&self, opts: ListOptions<'_>) -> Result<Map> {
        let fut: JsFuture = self
            .inner
            .list_with_options(serde_wasm_bindgen::to_value(&opts)?.into())?
            .into();
        fut.await
            .and_then(|jsv| jsv.dyn_into())
            .map_err(Error::from)
    }

    /// Retrieves the current alarm time (if set) as integer milliseconds since epoch.
    /// The alarm is considered to be set if it has not started, or if it has failed
    /// and any retry has not begun. If no alarm is set, `get_alarm()` returns `None`.
    pub async fn get_alarm(&self) -> Result<Option<i64>> {
        let fut: JsFuture = self.inner.get_alarm(JsValue::NULL.into())?.into();
        fut.await
            .map(|jsv| jsv.as_f64().map(|f| f as i64))
            .map_err(Error::from)
    }

    pub async fn get_alarm_with_options(&self, options: GetAlarmOptions) -> Result<Option<i64>> {
        let fut: JsFuture = self
            .inner
            .get_alarm(serde_wasm_bindgen::to_value(&options)?.into())?
            .into();
        fut.await
            .map(|jsv| jsv.as_f64().map(|f| f as i64))
            .map_err(Error::from)
    }

    /// Sets the current alarm time to the given datetime.
    ///
    /// If `set_alarm()` is called with a time equal to or before Date.now(), the alarm
    /// will be scheduled for asynchronous execution in the immediate future. If the
    /// alarm handler is currently executing in this case, it will not be canceled.
    /// Alarms can be set to millisecond granularity and will usually execute within
    /// a few milliseconds after the set time, but can be delayed by up to a minute
    /// due to maintenance or failures while failover takes place.
    pub async fn set_alarm(&self, scheduled_time: impl Into<ScheduledTime>) -> Result<()> {
        let fut: JsFuture = self
            .inner
            .set_alarm(scheduled_time.into().schedule(), JsValue::NULL.into())?
            .into();
        fut.await.map(|_| ()).map_err(Error::from)
    }

    pub async fn set_alarm_with_options(
        &self,
        scheduled_time: impl Into<ScheduledTime>,
        options: SetAlarmOptions,
    ) -> Result<()> {
        let fut: JsFuture = self
            .inner
            .set_alarm(
                scheduled_time.into().schedule(),
                serde_wasm_bindgen::to_value(&options)?.into(),
            )?
            .into();
        fut.await.map(|_| ()).map_err(Error::from)
    }

    /// Deletes the alarm if one exists. Does not cancel the alarm handler if it is
    /// currently executing.
    pub async fn delete_alarm(&self) -> Result<()> {
        let fut: JsFuture = self.inner.delete_alarm(JsValue::NULL.into())?.into();
        fut.await.map(|_| ()).map_err(Error::from)
    }

    pub async fn delete_alarm_with_options(&self, options: SetAlarmOptions) -> Result<()> {
        let fut: JsFuture = self
            .inner
            .delete_alarm(serde_wasm_bindgen::to_value(&options)?.into())?
            .into();
        fut.await.map(|_| ()).map_err(Error::from)
    }

    pub async fn transaction<F, Fut>(&self, closure: F) -> Result<()>
    where
        F: FnOnce(Transaction) -> Fut + 'static,
        Fut: Future<Output = Result<()>> + 'static,
    {
        let inner: Box<dyn FnOnce(DurableObjectTransaction) -> js_sys::Promise> =
            Box::new(move |t: DurableObjectTransaction| -> js_sys::Promise {
                future_to_promise(AssertUnwindSafe(async move {
                    closure(Transaction { inner: t })
                        .await
                        .map_err(JsValue::from)
                        .map(|_| JsValue::NULL)
                }))
            });
        let clos = wasm_bindgen::closure::Closure::once_assert_unwind_safe(inner);
        JsFuture::from(self.inner.transaction(&clos)?)
            .await
            .map_err(Error::from)
            .map(|_| ())
    }

    // Add new method to access SQLite APIs
    pub fn sql(&self) -> crate::sql::SqlStorage {
        crate::sql::SqlStorage::new(self.inner.sql())
    }
}

#[derive(Debug)]
pub struct Transaction {
    inner: DurableObjectTransaction,
}

impl Transaction {
    pub async fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T> {
        JsFuture::from(self.inner.get(key)?)
            .await
            .and_then(|val| {
                if val.is_undefined() {
                    Err(JsValue::from("No such value in storage."))
                } else {
                    serde_wasm_bindgen::from_value(val).map_err(std::convert::Into::into)
                }
            })
            .map_err(Error::from)
    }

    pub async fn get_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<Map> {
        let keys = self.inner.get_multiple(
            keys.into_iter()
                .map(|key| JsValue::from(key.deref()))
                .collect(),
        )?;
        let keys = JsFuture::from(keys).await?;
        keys.dyn_into::<Map>().map_err(Error::from)
    }

    pub async fn put<T: Serialize>(&self, key: &str, value: T) -> Result<()> {
        JsFuture::from(self.inner.put(key, serde_wasm_bindgen::to_value(&value)?)?)
            .await
            .map_err(Error::from)
            .map(|_| ())
    }

    // Each key-value pair in the serialized object will be added to the storage
    pub async fn put_multiple<T: Serialize>(&self, values: T) -> Result<()> {
        let values = serde_wasm_bindgen::to_value(&values)?;
        if !values.is_object() {
            return Err("Must pass in a struct type".to_string().into());
        }
        JsFuture::from(self.inner.put_multiple(values)?)
            .await
            .map_err(Error::from)
            .map(|_| ())
    }

    pub async fn delete(&self, key: &str) -> Result<bool> {
        let fut: JsFuture = self.inner.delete(key)?.into();
        fut.await
            .and_then(|jsv| {
                jsv.as_bool()
                    .ok_or_else(|| JsValue::from("Promise did not return bool"))
            })
            .map_err(Error::from)
    }

    pub async fn delete_multiple(&self, keys: Vec<impl Deref<Target = str>>) -> Result<usize> {
        let fut: JsFuture = self
            .inner
            .delete_multiple(
                keys.into_iter()
                    .map(|key| JsValue::from(key.deref()))
                    .collect(),
            )?
            .into();
        fut.await
            .and_then(|jsv| {
                jsv.as_f64()
                    .map(|f| f as usize)
                    .ok_or_else(|| JsValue::from("Promise did not return number"))
            })
            .map_err(Error::from)
    }

    pub async fn delete_all(&self) -> Result<()> {
        let fut: JsFuture = self.inner.delete_all()?.into();
        fut.await.map(|_| ()).map_err(Error::from)
    }

    pub async fn list(&self) -> Result<Map> {
        let fut: JsFuture = self.inner.list()?.into();
        fut.await
            .and_then(|jsv| jsv.dyn_into())
            .map_err(Error::from)
    }

    pub async fn list_with_options(&self, opts: ListOptions<'_>) -> Result<Map> {
        let fut: JsFuture = self
            .inner
            .list_with_options(serde_wasm_bindgen::to_value(&opts)?.into())?
            .into();
        fut.await
            .and_then(|jsv| jsv.dyn_into())
            .map_err(Error::from)
    }

    pub fn rollback(&self) -> Result<()> {
        self.inner.rollback().map_err(Error::from)
    }
}

#[derive(Default, Serialize, Debug)]
pub struct ListOptions<'a> {
    /// Key at which the list results should start, inclusive.
    #[serde(skip_serializing_if = "Option::is_none")]
    start: Option<&'a str>,
    /// Key at which the list results should end, exclusive.
    #[serde(skip_serializing_if = "Option::is_none")]
    end: Option<&'a str>,
    /// Restricts results to only include key-value pairs whose keys begin with the prefix.
    #[serde(skip_serializing_if = "Option::is_none")]
    prefix: Option<&'a str>,
    /// If true, return results in descending lexicographic order instead of the default ascending
    /// order.
    #[serde(skip_serializing_if = "Option::is_none")]
    reverse: Option<bool>,
    /// Maximum number of key-value pairs to return.
    #[serde(skip_serializing_if = "Option::is_none")]
    limit: Option<usize>,
}

impl<'a> ListOptions<'a> {
    /// Create a new ListOptions struct with no options set.
    pub fn new() -> Self {
        Default::default()
    }

    /// Key at which the list results should start, inclusive.
    pub fn start(mut self, val: &'a str) -> Self {
        self.start = Some(val);
        self
    }

    /// Key at which the list results should end, exclusive.
    pub fn end(mut self, val: &'a str) -> Self {
        self.end = Some(val);
        self
    }

    /// Restricts results to only include key-value pairs whose keys begin with the prefix.
    pub fn prefix(mut self, val: &'a str) -> Self {
        self.prefix = Some(val);
        self
    }

    /// If true, return results in descending lexicographic order instead of the default ascending
    /// order.
    pub fn reverse(mut self, val: bool) -> Self {
        self.reverse = Some(val);
        self
    }

    /// Maximum number of key-value pairs to return.
    pub fn limit(mut self, val: usize) -> Self {
        self.limit = Some(val);
        self
    }
}
#[derive(Debug)]
enum ScheduledTimeInit {
    Date(js_sys::Date),
    Offset(f64),
}

/// Determines when a Durable Object alarm should be ran, based on a timestamp or offset in milliseconds.
///
/// Implements [`From`] for:
/// - [`Duration`], interpreted as an offset (in milliseconds).
/// - [`i64`], interpreted as an offset (in milliseconds).
/// - [`DateTime`], interpreted as a timestamp.
///
/// When an offset is used, the time at which `set_alarm()` or `set_alarm_with_options()` is called
/// is used to compute the scheduled time. [`Date::now`] is used as the current time.
#[derive(Debug)]
pub struct ScheduledTime {
    init: ScheduledTimeInit,
}

impl ScheduledTime {
    pub fn new(date: js_sys::Date) -> Self {
        Self {
            init: ScheduledTimeInit::Date(date),
        }
    }

    fn schedule(self) -> js_sys::Date {
        match self.init {
            ScheduledTimeInit::Date(date) => date,
            ScheduledTimeInit::Offset(offset_ms) => {
                let now = Date::now().as_millis() as f64;
                js_sys::Date::new(&Number::from(now + offset_ms))
            }
        }
    }
}

impl From<i64> for ScheduledTime {
    fn from(offset_ms: i64) -> Self {
        ScheduledTime {
            init: ScheduledTimeInit::Offset(offset_ms as f64),
        }
    }
}

impl From<DateTime<Utc>> for ScheduledTime {
    fn from(date: DateTime<Utc>) -> Self {
        ScheduledTime {
            init: ScheduledTimeInit::Date(js_sys::Date::new(&Number::from(
                date.timestamp_millis() as f64,
            ))),
        }
    }
}

impl From<Duration> for ScheduledTime {
    fn from(offset: Duration) -> Self {
        ScheduledTime {
            init: ScheduledTimeInit::Offset(offset.as_millis() as f64),
        }
    }
}

#[derive(Debug, Clone, Default, Serialize)]
pub struct GetAlarmOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub allow_concurrency: Option<bool>,
}

#[derive(Debug, Clone, Default, Serialize)]
pub struct SetAlarmOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub allow_concurrency: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub allow_unconfirmed: Option<bool>,
}

impl EnvBinding for ObjectNamespace {
    const TYPE_NAME: &'static str = "DurableObjectNamespace";
}

impl JsCast for ObjectNamespace {
    fn instanceof(val: &JsValue) -> bool {
        val.is_instance_of::<EdgeObjectNamespace>()
    }

    fn unchecked_from_js(val: JsValue) -> Self {
        Self { inner: val.into() }
    }

    fn unchecked_from_js_ref(val: &JsValue) -> &Self {
        unsafe { &*(val as *const JsValue as *const Self) }
    }
}

impl From<ObjectNamespace> for JsValue {
    fn from(ns: ObjectNamespace) -> Self {
        JsValue::from(ns.inner)
    }
}

impl AsRef<JsValue> for ObjectNamespace {
    fn as_ref(&self) -> &JsValue {
        &self.inner
    }
}

#[derive(Debug)]
pub enum WebSocketIncomingMessage {
    String(String),
    Binary(Vec<u8>),
}

/**
**Note:** Implement this trait with a standard `impl DurableObject for YourType` block, but in order to
integrate them with the Workers Runtime, you must also add the **`#[durable_object]`** attribute
to the struct.

## Example
```no_run
use worker::*;

#[durable_object]
pub struct Chatroom {
    users: Vec<User>,
    messages: Vec<Message>,
    state: State,
    env: Env, // access `Env` across requests, use inside `fetch`
}

impl DurableObject for Chatroom {
    fn new(state: State, env: Env) -> Self {
        Self {
            users: vec![],
            messages: vec![],
            state,
            env,
        }
    }

    async fn fetch(&self, _req: Request) -> Result<Response> {
        // do some work when a worker makes a request to this DO
        Response::ok(&format!("{} active users.", self.users.len()))
    }
}
```
*/
#[allow(async_fn_in_trait)] // Send is not needed
pub trait DurableObject: has_durable_object_attribute {
    fn new(state: State, env: Env) -> Self;

    async fn fetch(&self, req: Request) -> Result<Response>;

    #[allow(clippy::diverging_sub_expression)]
    async fn alarm(&self) -> Result<Response> {
        worker_sys::console_error!("alarm() handler not implemented");
        unimplemented!("alarm() handler")
    }

    #[allow(unused_variables, clippy::diverging_sub_expression)]
    async fn websocket_message(
        &self,
        ws: WebSocket,
        message: WebSocketIncomingMessage,
    ) -> Result<()> {
        worker_sys::console_error!("websocket_message() handler not implemented");
        unimplemented!("websocket_message() handler")
    }

    #[allow(unused_variables, clippy::diverging_sub_expression)]
    async fn websocket_close(
        &self,
        ws: WebSocket,
        code: usize,
        reason: String,
        was_clean: bool,
    ) -> Result<()> {
        worker_sys::console_error!("websocket_close() handler not implemented");
        unimplemented!("websocket_close() handler")
    }

    #[allow(unused_variables, clippy::diverging_sub_expression)]
    async fn websocket_error(&self, ws: WebSocket, error: Error) -> Result<()> {
        worker_sys::console_error!("websocket_error() handler not implemented");
        unimplemented!("websocket_error() handler")
    }
}

#[doc(hidden)]
#[allow(non_camel_case_types)]
pub trait has_durable_object_attribute {}