diff --git a/crates/bindings/src/lib.rs b/crates/bindings/src/lib.rs index 62b78e14be4..3d826cc7cb1 100644 --- a/crates/bindings/src/lib.rs +++ b/crates/bindings/src/lib.rs @@ -24,11 +24,12 @@ pub use spacetimedb_query_builder as query_builder; #[cfg(feature = "unstable")] pub use client_visibility_filter::Filter; pub use log; +#[cfg(feature = "rand08")] +use rand::distributions::{Distribution, Standard}; #[cfg(feature = "rand")] pub use rand08 as rand; #[cfg(feature = "rand")] use rand08::RngCore; -#[cfg(feature = "rand08")] pub use rng::StdbRng; pub use sats::SpacetimeType; #[doc(hidden)] @@ -912,6 +913,8 @@ pub use spacetimedb_bindings_macro::view; pub struct QueryBuilder {} pub use query_builder::{Query, RawQuery}; +use crate::http::{HandlerContext, HttpClient}; + /// One of two possible types that can be passed as the first argument to a `#[view]`. /// The other is [`ViewContext`]. /// Use this type if the view does not depend on the caller's identity. @@ -1440,6 +1443,7 @@ impl ProcedureContext { } /// A handle on a database with a particular table schema. +#[deprecated(note = "Use the capability based traits (CtxDbRead, CtxDbWrite) instead!")] pub trait DbContext { /// A view into the tables of a database. /// @@ -1461,6 +1465,7 @@ pub trait DbContext { fn db_read_only(&self) -> &LocalReadOnly; } +#[allow(deprecated)] impl DbContext for AnonymousViewContext { type DbView = LocalReadOnly; @@ -1473,6 +1478,7 @@ impl DbContext for AnonymousViewContext { } } +#[allow(deprecated)] impl DbContext for ReducerContext { type DbView = Local; @@ -1485,6 +1491,7 @@ impl DbContext for ReducerContext { } } +#[allow(deprecated)] impl DbContext for TxContext { type DbView = Local; @@ -1497,6 +1504,7 @@ impl DbContext for TxContext { } } +#[allow(deprecated)] impl DbContext for ViewContext { type DbView = LocalReadOnly; @@ -1526,6 +1534,279 @@ impl Local { } } +/// Contexts which provide read access to the database. +/// +/// This trait is useful for writing reusable logic which is generic over the context type, +/// allowing it to be used from views, reducers, and transactions started by procedures and HTTP handlers. +/// +/// When operating on a concrete-typed [`ViewContext`], [`ReducerContext`] or [`TxContext`], +/// this trait is not necessary, as the context's `db` field provides the same (or greater, read-write) access. +pub trait CtxDbRead { + fn db_read_only(&self) -> &LocalReadOnly; +} + +impl CtxDbRead for TxContext { + fn db_read_only(&self) -> &LocalReadOnly { + &LocalReadOnly {} + } +} + +impl CtxDbRead for ReducerContext { + fn db_read_only(&self) -> &LocalReadOnly { + &LocalReadOnly {} + } +} + +impl CtxDbRead for ViewContext { + fn db_read_only(&self) -> &LocalReadOnly { + &LocalReadOnly {} + } +} + +impl CtxDbRead for AnonymousViewContext { + fn db_read_only(&self) -> &LocalReadOnly { + &LocalReadOnly {} + } +} + +/// Contexts which provide read-write access to the database. +/// +/// This trait is useful for writing reusable logic which is generic over the context type, +/// allowing it to be used from reducers and from transactions started by procedures and HTTP handlers. +/// +/// When operating on a concrete-typed [`ReducerContext`] or [`TxContext`], this trait is not necessary, +/// as the context's `db` field provides the same access. +pub trait CtxDbWrite: CtxDbRead { + fn db(&self) -> &Local; +} + +impl CtxDbWrite for TxContext { + fn db(&self) -> &Local { + &Local {} + } +} + +impl CtxDbWrite for ReducerContext { + fn db(&self) -> &Local { + &Local {} + } +} + +/// Contexts which can retrieve the sender [`Identity`]. +/// +/// This trait is useful for writing reusable logic which is generic over the context type, +/// allowing it to be used from views, reducers, and transactions started by procedures and HTTP handlers. +/// +/// When operating on a concrete-typed [`ViewContext`], [`ReducerContext`], [`ProcedureContext`] or [`TxContext`], this trait is not necessary, +/// as the context's inherent `sender` method provides the same access. +pub trait CtxWithSender { + fn sender(&self) -> Identity; +} + +impl CtxWithSender for ViewContext { + fn sender(&self) -> Identity { + self.sender + } +} + +impl CtxWithSender for ReducerContext { + fn sender(&self) -> Identity { + self.sender + } +} + +impl CtxWithSender for TxContext { + fn sender(&self) -> Identity { + self.0.sender + } +} + +impl CtxWithSender for ProcedureContext { + fn sender(&self) -> Identity { + self.sender + } +} + +/// Contexts which can retrieve the current [`Timestamp`]. +/// +/// This trait is useful for writing reusable logic which is generic over the context type, +/// allowing it to be used from reducers, procedures, HTTP handlers, +/// and transactions started by procedures and HTTP handlers. +/// +/// When operating on a concrete-typed [`ReducerContext`], [`ProcedureContext`], [`HandlerContext`] or [`TxContext`], +/// this trait is not necessary, as the context's `timestamp` field provides the same access. +pub trait CtxWithTimestamp { + fn timestamp(&self) -> Timestamp; +} + +impl CtxWithTimestamp for ReducerContext { + fn timestamp(&self) -> Timestamp { + self.timestamp + } +} + +impl CtxWithTimestamp for TxContext { + fn timestamp(&self) -> Timestamp { + self.timestamp + } +} + +impl CtxWithTimestamp for ProcedureContext { + fn timestamp(&self) -> Timestamp { + self.timestamp + } +} + +impl CtxWithTimestamp for HandlerContext { + fn timestamp(&self) -> Timestamp { + self.timestamp + } +} + +/// Contexts which can retrieve the current [`AuthCtx`]. +/// +/// This trait is useful for writing reusable logic which is generic over the context type, +/// allowing it to be used from reducers and procedures. +/// +/// When operating on a concrete-typed [`ReducerContext`], [`ProcedureContext`], [`TxContext`], +/// this trait is not necessary, as the context's sender_auth method provides the same access. +pub trait CtxWithSenderAuth { + fn sender_auth(&self) -> &AuthCtx; +} + +impl CtxWithSenderAuth for ReducerContext { + fn sender_auth(&self) -> &AuthCtx { + self.sender_auth() + } +} + +impl CtxWithSenderAuth for TxContext { + fn sender_auth(&self) -> &AuthCtx { + self.0.sender_auth() + } +} + +/// Contexts which can enter a start a transaction with a [`TxContext`] inside the function. +/// +/// This trait is useful for writing reusable logic which is generic over the context type, +/// allowing it to be used from reducers and procedures. +/// +/// When operating on a concrete-typed [`HandlerContext`], [`ProcedureContext`], +/// this trait is not necessary, as the context's methods provide the same access. +pub trait CtxWithTxManagement { + fn with_tx(&mut self, body: impl Fn(&TxContext) -> T) -> T; + fn try_with_tx(&mut self, body: impl Fn(&TxContext) -> Result) -> Result; +} + +impl CtxWithTxManagement for ProcedureContext { + fn with_tx(&mut self, body: impl Fn(&TxContext) -> T) -> T { + self.with_tx(body) + } + + fn try_with_tx(&mut self, body: impl Fn(&TxContext) -> Result) -> Result { + self.try_with_tx(body) + } +} + +impl CtxWithTxManagement for HandlerContext { + fn with_tx(&mut self, body: impl Fn(&TxContext) -> T) -> T { + self.with_tx(body) + } + + fn try_with_tx(&mut self, body: impl Fn(&TxContext) -> Result) -> Result { + self.try_with_tx(body) + } +} + +/// Contexts which can retrieve the current [`StdbRng`] state. +/// +/// This trait is useful for writing reusable logic which is generic over the context type, +/// allowing it to be used from reducers and procedures. +/// +/// When operating on a concrete-typed [`HandlerContext`], [`ProcedureContext`], [`ReducerContext`], [`TxContext`] +/// this trait is not necessary, as the context's methods provide the same access. +pub trait CtxWithRng { + fn rng(&self) -> &StdbRng; + fn random(&self) -> T + where + Standard: Distribution; +} + +impl CtxWithRng for ProcedureContext { + fn rng(&self) -> &StdbRng { + self.rng() + } + + fn random(&self) -> T + where + Standard: Distribution, + { + self.random() + } +} + +impl CtxWithRng for HandlerContext { + fn rng(&self) -> &StdbRng { + self.rng() + } + + fn random(&self) -> T + where + Standard: Distribution, + { + self.random() + } +} + +impl CtxWithRng for ReducerContext { + fn rng(&self) -> &StdbRng { + self.rng() + } + + fn random(&self) -> T + where + Standard: Distribution, + { + self.random() + } +} + +impl CtxWithRng for TxContext { + fn rng(&self) -> &StdbRng { + self.0.rng() + } + + fn random(&self) -> T + where + Standard: Distribution, + { + self.0.random() + } +} + +/// Contexts which can perform outgoing HTTP requests. +/// +/// This type is useful for writing reusable logic which is generic over the context type, +/// allowing it to be used from procedures and HTTP handlers. +/// +/// When operating on a concrete-typed [`ProcedureContext`] or [`HandlerContext`], this trait is not necessary, +/// as the context's `http` field provides the same access. +pub trait CtxWithHttp { + fn http(&self) -> &HttpClient; +} + +impl CtxWithHttp for HandlerContext { + fn http(&self) -> &HttpClient { + &self.http + } +} + +impl CtxWithHttp for ProcedureContext { + fn http(&self) -> &HttpClient { + &self.http + } +} + /// The [JWT] of an [`AuthCtx`]. /// /// [JWT]: https://en.wikipedia.org/wiki/JSON_Web_Token