Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
283 changes: 282 additions & 1 deletion crates/bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
///
Expand All @@ -1461,6 +1465,7 @@ pub trait DbContext {
fn db_read_only(&self) -> &LocalReadOnly;
}

#[allow(deprecated)]
impl DbContext for AnonymousViewContext {
type DbView = LocalReadOnly;

Expand All @@ -1473,6 +1478,7 @@ impl DbContext for AnonymousViewContext {
}
}

#[allow(deprecated)]
impl DbContext for ReducerContext {
type DbView = Local;

Expand All @@ -1485,6 +1491,7 @@ impl DbContext for ReducerContext {
}
}

#[allow(deprecated)]
impl DbContext for TxContext {
type DbView = Local;

Expand All @@ -1497,6 +1504,7 @@ impl DbContext for TxContext {
}
}

#[allow(deprecated)]
impl DbContext for ViewContext {
type DbView = LocalReadOnly;

Expand Down Expand Up @@ -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<T>(&mut self, body: impl Fn(&TxContext) -> T) -> T;
fn try_with_tx<T, E>(&mut self, body: impl Fn(&TxContext) -> Result<T, E>) -> Result<T, E>;
}

impl CtxWithTxManagement for ProcedureContext {
fn with_tx<T>(&mut self, body: impl Fn(&TxContext) -> T) -> T {
self.with_tx(body)
}

fn try_with_tx<T, E>(&mut self, body: impl Fn(&TxContext) -> Result<T, E>) -> Result<T, E> {
self.try_with_tx(body)
}
}

impl CtxWithTxManagement for HandlerContext {
fn with_tx<T>(&mut self, body: impl Fn(&TxContext) -> T) -> T {
self.with_tx(body)
}

fn try_with_tx<T, E>(&mut self, body: impl Fn(&TxContext) -> Result<T, E>) -> Result<T, E> {
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<T>(&self) -> T
where
Standard: Distribution<T>;
}

impl CtxWithRng for ProcedureContext {
fn rng(&self) -> &StdbRng {
self.rng()
}

fn random<T>(&self) -> T
where
Standard: Distribution<T>,
{
self.random()
}
}

impl CtxWithRng for HandlerContext {
fn rng(&self) -> &StdbRng {
self.rng()
}

fn random<T>(&self) -> T
where
Standard: Distribution<T>,
{
self.random()
}
}

impl CtxWithRng for ReducerContext {
fn rng(&self) -> &StdbRng {
self.rng()
}

fn random<T>(&self) -> T
where
Standard: Distribution<T>,
{
self.random()
}
}

impl CtxWithRng for TxContext {
fn rng(&self) -> &StdbRng {
self.0.rng()
}

fn random<T>(&self) -> T
where
Standard: Distribution<T>,
{
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
Expand Down