diff --git a/examples~/quickstart/server/.gitignore b/examples~/quickstart/server/.gitignore index 91ad2584..31b13f05 100644 --- a/examples~/quickstart/server/.gitignore +++ b/examples~/quickstart/server/.gitignore @@ -3,6 +3,10 @@ debug/ target/ +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + # These are backup files generated by rustfmt **/*.rs.bk @@ -10,4 +14,4 @@ target/ *.pdb # Spacetime ignore -/.spacetime +/.spacetime \ No newline at end of file diff --git a/examples~/quickstart/server/Cargo.lock b/examples~/quickstart/server/Cargo.lock index 372fb071..e0f96b7c 100644 --- a/examples~/quickstart/server/Cargo.lock +++ b/examples~/quickstart/server/Cargo.lock @@ -62,6 +62,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bytemuck" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" + +[[package]] +name = "bytes" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" + [[package]] name = "cfg-if" version = "1.0.0" @@ -144,6 +156,15 @@ dependencies = [ "syn 2.0.32", ] +[[package]] +name = "ethnum" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b90ca2580b73ab6a1f724b76ca11ab632df820fd6040c336200d2c1df7b3c82c" +dependencies = [ + "serde", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -259,6 +280,14 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quickstart-chat-module" +version = "0.1.0" +dependencies = [ + "log", + "spacetimedb", +] + [[package]] name = "quote" version = "1.0.29" @@ -325,6 +354,26 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +[[package]] +name = "serde" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.193" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.32", +] + [[package]] name = "sha3" version = "0.10.8" @@ -341,21 +390,13 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" -[[package]] -name = "spacetime-module" -version = "0.1.0" -dependencies = [ - "anyhow", - "log", - "spacetimedb", -] - [[package]] name = "spacetimedb" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec3fbc884bd532f1f9cddcde961686284091dfa3facd49b71c553df28d30a5f" +checksum = "6b083dadcc676ec1f2bdbd862776ac2fb295c7cd1cd63a671f3e4660c22ce4c7" dependencies = [ + "bytemuck", "derive_more", "getrandom", "log", @@ -369,11 +410,12 @@ dependencies = [ [[package]] name = "spacetimedb-bindings-macro" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a5a6d8be2a892ae1d1175b228f12deffb685947cc30d60449dba98219cc3bc2" +checksum = "f2216aa0e94ee5eff29322f7a80b847674a6415bdedca36267d4f9827838ef17" dependencies = [ "bitflags", + "heck", "humantime", "proc-macro2", "quote", @@ -383,29 +425,30 @@ dependencies = [ [[package]] name = "spacetimedb-bindings-sys" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a450cdc41a3d6a6a33ba113255c2a1d73dbf32bcf7aa2d272beb58cc6efe9655" +checksum = "bd06c9176160de7138fdd579fcac3fb5735441bdf82896ce9bcadc7000892362" dependencies = [ "spacetimedb-primitives", ] [[package]] name = "spacetimedb-data-structures" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d866aa0c287936e13f03206f32c15ce46893076918b7d1d9e1a1421ddca2e6a" +checksum = "0293e7ff788f4d36e85f4029e946145b3ca884d3702b046b1f05497931e2c117" dependencies = [ "hashbrown", "nohash-hasher", + "smallvec", "thiserror", ] [[package]] name = "spacetimedb-lib" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c1d4c3106bdfe395c8f266df1daff9e6259322bd70d05e3f78c7fa67efd14f" +checksum = "e9e92b11f138722de120c6bba2cdc46d0aed348fbeb673bd60d8758a5199e6ac" dependencies = [ "anyhow", "bitflags", @@ -414,6 +457,7 @@ dependencies = [ "hex", "itertools", "spacetimedb-bindings-macro", + "spacetimedb-data-structures", "spacetimedb-primitives", "spacetimedb-sats", "thiserror", @@ -421,33 +465,36 @@ dependencies = [ [[package]] name = "spacetimedb-primitives" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f80f43ce78747ae4deb061130fcbedf9c57cbe9d3db8269e2ce403d6cf3a0c" +checksum = "02c6c81cb1df7d6bd77923121d1663f8bbe8e28e669d29d25b335fc81a2a3ccd" dependencies = [ "bitflags", "either", + "itertools", "nohash-hasher", ] [[package]] name = "spacetimedb-sats" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab8da7807277abaef5452d25c3cbc01978297a37d0f00071e52621e655b3a84" +checksum = "b6e07d8e872575b4825eb62c1bbb6f0a50081858664bbe9ee135f977ee7263d2" dependencies = [ "arrayvec", "bitflags", + "bytemuck", + "bytes", "decorum", "derive_more", "enum-as-inner", + "ethnum", "hex", "itertools", "second-stack", "sha3", "smallvec", "spacetimedb-bindings-macro", - "spacetimedb-data-structures", "spacetimedb-primitives", "thiserror", ] diff --git a/examples~/quickstart/server/Cargo.toml b/examples~/quickstart/server/Cargo.toml index 735a5ad6..4775c4e1 100644 --- a/examples~/quickstart/server/Cargo.toml +++ b/examples~/quickstart/server/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "spacetime-module" +name = "quickstart-chat-module" version = "0.1.0" edition = "2021" @@ -9,6 +9,5 @@ edition = "2021" crate-type = ["cdylib"] [dependencies] -spacetimedb = "0.10" +spacetimedb = "0.12.0" log = "0.4" -anyhow = "1.0" diff --git a/examples~/quickstart/server/src/lib.rs b/examples~/quickstart/server/src/lib.rs index 015aaefe..cf986470 100644 --- a/examples~/quickstart/server/src/lib.rs +++ b/examples~/quickstart/server/src/lib.rs @@ -1,5 +1,4 @@ -use spacetimedb::{ReducerContext, Identity, Table, Timestamp}; -use anyhow::{Result, anyhow}; +use spacetimedb::{Identity, ReducerContext, Table, Timestamp}; #[spacetimedb::table(name = user, public)] pub struct User { @@ -16,71 +15,41 @@ pub struct Message { text: String, } -#[spacetimedb::reducer(init)] -pub fn init(_ctx: &ReducerContext) { - -} - -#[spacetimedb::reducer(client_connected)] -pub fn identity_connected(ctx: &ReducerContext) { - if let Some(user) = ctx.db.user().identity().find(&ctx.sender) { - // If this is a returning user, i.e. we already have a `User` with this `Identity`, - // set `online: true`, but leave `name` and `identity` unchanged. - ctx.db.user().identity().update(User { online: true, ..user }); - } else { - // If this is a new user, create a `User` row for the `Identity`, - // which is online, but hasn't set a name. - ctx.db.user().try_insert(User { - name: None, - identity: ctx.sender, - online: true, - }).unwrap(); - } -} - -#[spacetimedb::reducer(client_disconnected)] -pub fn identity_disconnected(ctx: &ReducerContext) { - if let Some(user) = ctx.db.user().identity().find(&ctx.sender) { - ctx.db.user().identity().update(User { online: false, ..user }); - } else { - // This branch should be unreachable, - // as it doesn't make sense for a client to disconnect without connecting first. - log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender); - } -} - -fn validate_name(name: String) -> Result { +fn validate_name(name: String) -> Result { if name.is_empty() { - Err(anyhow!("Names must not be empty")) + Err("Names must not be empty".to_string()) } else { Ok(name) } } #[spacetimedb::reducer] -pub fn set_name(ctx: &ReducerContext, name: String) -> Result<()> { +pub fn set_name(ctx: &ReducerContext, name: String) -> Result<(), String> { let name = validate_name(name)?; - if let Some(user) = ctx.db.user().identity().find(&ctx.sender) { - ctx.db.user().identity().update(User { name: Some(name), ..user }); + if let Some(user) = ctx.db.user().identity().find(ctx.sender) { + ctx.db.user().identity().update(User { + name: Some(name), + ..user + }); Ok(()) } else { - Err(anyhow!("Cannot set name for unknown user")) + Err("Cannot set name for unknown user".to_string()) } } -fn validate_message(text: String) -> Result { +fn validate_message(text: String) -> Result { if text.is_empty() { - Err(anyhow!("Messages must not be empty")) + Err("Messages must not be empty".to_string()) } else { Ok(text) } } #[spacetimedb::reducer] -pub fn send_message(ctx: &ReducerContext, text: String) -> Result<()> { +pub fn send_message(ctx: &ReducerContext, text: String) -> Result<(), String> { // Things to consider: // - Rate-limit messages per-user. - // - Reject messages from unnamed users. + // - Reject messages from unnamed user. let text = validate_message(text)?; ctx.db.message().insert(Message { sender: ctx.sender, @@ -89,3 +58,35 @@ pub fn send_message(ctx: &ReducerContext, text: String) -> Result<()> { }); Ok(()) } + +#[spacetimedb::reducer(init)] +// Called when the module is initially published +pub fn init(_ctx: &ReducerContext) {} + +#[spacetimedb::reducer(client_connected)] +pub fn identity_connected(ctx: &ReducerContext) { + if let Some(user) = ctx.db.user().identity().find(ctx.sender) { + // If this is a returning user, i.e. we already have a `User` with this `Identity`, + // set `online: true`, but leave `name` and `identity` unchanged. + ctx.db.user().identity().update(User { online: true, ..user }); + } else { + // If this is a new user, create a `User` row for the `Identity`, + // which is online, but hasn't set a name. + ctx.db.user().insert(User { + name: None, + identity: ctx.sender, + online: true, + }); + } +} + +#[spacetimedb::reducer(client_disconnected)] +pub fn identity_disconnected(ctx: &ReducerContext) { + if let Some(user) = ctx.db.user().identity().find(ctx.sender) { + ctx.db.user().identity().update(User { online: false, ..user }); + } else { + // This branch should be unreachable, + // as it doesn't make sense for a client to disconnect without connecting first. + log::warn!("Disconnect event for unknown user with identity {:?}", ctx.sender); + } +}