Skip to content

Commit 9ec9ff6

Browse files
committed
Add web feature flag to the rust sdk
1 parent b4a0872 commit 9ec9ff6

File tree

5 files changed

+78
-58
lines changed

5 files changed

+78
-58
lines changed

crates/sdk/Cargo.toml

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ description = "A Rust SDK for clients to interface with SpacetimeDB"
77

88
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
99

10+
[features]
11+
default = []
12+
web = [
13+
"dep:futures-util",
14+
"dep:getrandom",
15+
"dep:gloo-console",
16+
"dep:gloo-storage",
17+
"dep:rustls-pki-types",
18+
"dep:tokio-tungstenite-wasm",
19+
"dep:wasm-bindgen",
20+
"dep:wasm-bindgen-futures",
21+
"dep:web-sys",
22+
]
23+
1024
[dependencies]
1125
spacetimedb-data-structures.workspace = true
1226
spacetimedb-sats.workspace = true
@@ -27,25 +41,25 @@ once_cell.workspace = true
2741
prometheus.workspace = true
2842
rand.workspace = true
2943

44+
futures-util = { version = "0.3", default-features = false, features = ["sink", "std"], optional = true }
45+
getrandom = { version = "0.3.2", features = ["wasm_js"], optional = true }
46+
gloo-console = { version = "0.3.0", optional = true }
47+
gloo-storage = { version = "0.3.0", optional = true }
48+
rustls-pki-types = { version = "1.11.0", features = ["web"], optional = true }
49+
tokio-tungstenite-wasm = { version = "0.6.0", optional = true }
50+
wasm-bindgen = { version = "0.2.100", optional = true }
51+
wasm-bindgen-futures = { version = "0.4.45", optional = true }
52+
web-sys = { version = "0.3.77", features = [ "Document", "HtmlDocument", "Window" ], optional = true}
53+
3054
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
3155
home.workspace = true
3256
tokio.workspace = true
3357
tokio-tungstenite.workspace = true
3458

3559
[target.'cfg(target_arch = "wasm32")'.dependencies]
36-
futures-util = { version = "0.3", default-features = false, features = ["sink", "std"] }
37-
getrandom = { version = "0.3.2", features = ["wasm_js"]}
38-
gloo-console = "0.3.0"
39-
gloo-storage = "0.3.0"
40-
rustls-pki-types = { version = "1.11.0", features = ["web"] }
4160
tokio = { version = "1.37", default-features = false, features = [
4261
"rt", "macros", "sync", "io-util"
4362
] }
44-
tokio-tungstenite-wasm = "0.6.0"
45-
tungstenite = { version = "0.26.2", features = ["rustls"] }
46-
wasm-bindgen = "0.2.100"
47-
wasm-bindgen-futures = "0.4.45"
48-
web-sys = { version = "0.3.77", features = [ "Document", "HtmlDocument", "Window" ] }
4963

5064
[dev-dependencies]
5165
# for quickstart-chat and cursive-chat examples

crates/sdk/src/credentials.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
//! }
99
//! ```
1010
11-
#[cfg(not(target_arch = "wasm32"))]
11+
#[cfg(not(feature = "web"))]
1212
mod native_mod {
1313
use home::home_dir;
1414
use spacetimedb_lib::{bsatn, de::Deserialize, ser::Serialize};
@@ -153,7 +153,7 @@ mod native_mod {
153153
}
154154
}
155155

156-
#[cfg(target_arch = "wasm32")]
156+
#[cfg(feature = "web")]
157157
mod web_mod {
158158
pub use gloo_storage::{LocalStorage, SessionStorage, Storage};
159159

@@ -319,8 +319,8 @@ mod web_mod {
319319
}
320320
}
321321

322-
#[cfg(not(target_arch = "wasm32"))]
322+
#[cfg(not(feature = "web"))]
323323
pub use native_mod::*;
324324

325-
#[cfg(target_arch = "wasm32")]
325+
#[cfg(feature = "web")]
326326
pub use web_mod::*;

crates/sdk/src/db_connection.rs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ use std::{
4141
sync::{atomic::AtomicU32, Arc, Mutex as StdMutex, OnceLock},
4242
};
4343
use tokio::runtime::{self, Runtime};
44-
#[cfg(not(target_arch = "wasm32"))]
44+
#[cfg(not(feature = "web"))]
4545
use tokio::sync::Mutex as TokioMutex;
4646

4747
pub(crate) type SharedCell<T> = Arc<StdMutex<T>>;
@@ -65,9 +65,9 @@ pub struct DbContextImpl<M: SpacetimeModule> {
6565

6666
/// Receiver channel for WebSocket messages,
6767
/// which are pre-parsed in the background by [`parse_loop`].
68-
#[cfg(not(target_arch = "wasm32"))]
68+
#[cfg(not(feature = "web"))]
6969
recv: Arc<TokioMutex<mpsc::UnboundedReceiver<ParsedMessage<M>>>>,
70-
#[cfg(target_arch = "wasm32")]
70+
#[cfg(feature = "web")]
7171
recv: SharedCell<mpsc::UnboundedReceiver<ParsedMessage<M>>>,
7272

7373
/// Channel into which operations which apparently mutate SDK state,
@@ -78,9 +78,9 @@ pub struct DbContextImpl<M: SpacetimeModule> {
7878

7979
/// Receive end of `pending_mutations_send`,
8080
/// from which [Self::apply_pending_mutations] and friends read mutations.
81-
#[cfg(not(target_arch = "wasm32"))]
81+
#[cfg(not(feature = "web"))]
8282
pending_mutations_recv: Arc<TokioMutex<mpsc::UnboundedReceiver<PendingMutation<M>>>>,
83-
#[cfg(target_arch = "wasm32")]
83+
#[cfg(feature = "web")]
8484
pending_mutations_recv: SharedCell<mpsc::UnboundedReceiver<PendingMutation<M>>>,
8585

8686
/// This connection's `Identity`.
@@ -264,12 +264,12 @@ impl<M: SpacetimeModule> DbContextImpl<M> {
264264

265265
/// Apply all queued [`PendingMutation`]s.
266266
fn apply_pending_mutations(&self) -> crate::Result<()> {
267-
#[cfg(not(target_arch = "wasm32"))]
267+
#[cfg(not(feature = "web"))]
268268
while let Ok(Some(pending_mutation)) = self.pending_mutations_recv.blocking_lock().try_next() {
269269
self.apply_mutation(pending_mutation)?;
270270
}
271271

272-
#[cfg(target_arch = "wasm32")]
272+
#[cfg(feature = "web")]
273273
while let Ok(Some(pending_mutation)) = self.pending_mutations_recv.lock().unwrap().try_next() {
274274
self.apply_mutation(pending_mutation)?;
275275
}
@@ -489,10 +489,10 @@ impl<M: SpacetimeModule> DbContextImpl<M> {
489489
// model or not.
490490

491491
let res = {
492-
#[cfg(not(target_arch = "wasm32"))]
492+
#[cfg(not(feature = "web"))]
493493
let mut recv = self.recv.blocking_lock();
494494

495-
#[cfg(target_arch = "wasm32")]
495+
#[cfg(feature = "web")]
496496
let mut recv = self.recv.lock().unwrap();
497497

498498
match recv.try_next() {
@@ -519,14 +519,14 @@ impl<M: SpacetimeModule> DbContextImpl<M> {
519519
// We call this out as an incorrect and unsupported thing to do.
520520
#![allow(clippy::await_holding_lock)]
521521

522-
#[cfg(not(target_arch = "wasm32"))]
522+
#[cfg(not(feature = "web"))]
523523
let mut pending_mutations = self.pending_mutations_recv.lock().await;
524-
#[cfg(target_arch = "wasm32")]
524+
#[cfg(feature = "web")]
525525
let mut pending_mutations = self.pending_mutations_recv.lock().unwrap();
526526

527-
#[cfg(not(target_arch = "wasm32"))]
527+
#[cfg(not(feature = "web"))]
528528
let mut recv = self.recv.lock().await;
529-
#[cfg(target_arch = "wasm32")]
529+
#[cfg(feature = "web")]
530530
let mut recv = self.recv.lock().unwrap();
531531

532532
// Always process pending mutations before WS messages, if they're available,
@@ -585,7 +585,7 @@ impl<M: SpacetimeModule> DbContextImpl<M> {
585585
/// Spawn a thread which does [`Self::advance_one_message_blocking`] in a loop.
586586
///
587587
/// Called by the autogenerated `DbConnection` method of the same name.
588-
#[cfg(not(target_arch = "wasm32"))]
588+
#[cfg(not(feature = "web"))]
589589
pub fn run_threaded(&self) -> std::thread::JoinHandle<()> {
590590
let this = self.clone();
591591
std::thread::spawn(move || loop {
@@ -597,7 +597,7 @@ impl<M: SpacetimeModule> DbContextImpl<M> {
597597
})
598598
}
599599

600-
#[cfg(target_arch = "wasm32")]
600+
#[cfg(feature = "web")]
601601
pub fn run_threaded(&self) {
602602
let this = self.clone();
603603
wasm_bindgen_futures::spawn_local(async move {
@@ -865,21 +865,21 @@ You must explicitly advance the connection by calling any one of:
865865
Which of these methods you should call depends on the specific needs of your application,
866866
but you must call one of them, or else the connection will never progress.
867867
"]
868-
#[cfg(not(target_arch = "wasm32"))]
868+
#[cfg(not(feature = "web"))]
869869
pub fn build(self) -> crate::Result<M::DbConnection> {
870870
let imp = self.build_impl()?;
871871
Ok(<M::DbConnection as DbConnection>::new(imp))
872872
}
873873

874-
#[cfg(target_arch = "wasm32")]
874+
#[cfg(feature = "web")]
875875
pub async fn build(self) -> crate::Result<M::DbConnection> {
876876
let imp = self.build_impl().await?;
877877
Ok(<M::DbConnection as DbConnection>::new(imp))
878878
}
879879

880880
/// Open a WebSocket connection, build an empty client cache, &c,
881881
/// to construct a [`DbContextImpl`].
882-
#[cfg(not(target_arch = "wasm32"))]
882+
#[cfg(not(feature = "web"))]
883883
fn build_impl(self) -> crate::Result<DbContextImpl<M>> {
884884
let (runtime, handle) = enter_or_create_runtime()?;
885885
let db_callbacks = DbCallbacks::default();
@@ -934,7 +934,7 @@ but you must call one of them, or else the connection will never progress.
934934
Ok(ctx_imp)
935935
}
936936

937-
#[cfg(target_arch = "wasm32")]
937+
#[cfg(feature = "web")]
938938
pub async fn build_impl(self) -> crate::Result<DbContextImpl<M>> {
939939
let (runtime, handle) = enter_or_create_runtime()?;
940940
let db_callbacks = DbCallbacks::default();
@@ -1101,9 +1101,9 @@ Instead of registering multiple `on_disconnect` callbacks, register a single cal
11011101
fn enter_or_create_runtime() -> crate::Result<(Option<Runtime>, runtime::Handle)> {
11021102
match runtime::Handle::try_current() {
11031103
Err(e) if e.is_missing_context() => {
1104-
#[cfg(not(target_arch = "wasm32"))]
1104+
#[cfg(not(feature = "web"))]
11051105
let mut rt = tokio::runtime::Builder::new_multi_thread();
1106-
#[cfg(target_arch = "wasm32")]
1106+
#[cfg(feature = "web")]
11071107
let mut rt = tokio::runtime::Builder::new_current_thread();
11081108

11091109
let rt = rt
@@ -1135,7 +1135,7 @@ enum ParsedMessage<M: SpacetimeModule> {
11351135
Error(crate::Error),
11361136
}
11371137

1138-
#[cfg(not(target_arch = "wasm32"))]
1138+
#[cfg(not(feature = "web"))]
11391139
fn spawn_parse_loop<M: SpacetimeModule>(
11401140
raw_message_recv: mpsc::UnboundedReceiver<ws::ServerMessage<BsatnFormat>>,
11411141
handle: &runtime::Handle,
@@ -1145,7 +1145,7 @@ fn spawn_parse_loop<M: SpacetimeModule>(
11451145
(handle, parsed_message_recv)
11461146
}
11471147

1148-
#[cfg(target_arch = "wasm32")]
1148+
#[cfg(feature = "web")]
11491149
fn spawn_parse_loop<M: SpacetimeModule>(
11501150
raw_message_recv: mpsc::UnboundedReceiver<ws::ServerMessage<BsatnFormat>>,
11511151
) -> mpsc::UnboundedReceiver<ParsedMessage<M>> {

crates/sdk/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,9 @@ pub mod unstable {
7272
pub use crate::metrics::{ClientMetrics, CLIENT_METRICS};
7373
pub use spacetimedb_client_api_messages::websocket::CallReducerFlags;
7474
}
75+
76+
#[cfg(all(not(target_arch = "wasm32"), feature = "web"))]
77+
compile_error!(
78+
"The `web` feature can only be enabled when targeting `wasm32`. \
79+
Remove `--features web` or switch your target to a wasm32 architecture."
80+
);

0 commit comments

Comments
 (0)