commit 7a75a523f009ec596e3ed84f15d36c39602df425 Author: Jan-Peter von Hunnius Date: Sun Aug 2 12:48:08 2026 +0200 Initial scaffold: Rust server workspace (sb-api, sb-core, sb-db, sb-auth, sb-shared) + sb-common dependency + systemd diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..edd13b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +target/ +Cargo.lock +.env diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..65601b1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[workspace] +resolver = "2" +members = [ + "crates/sb-api", + "crates/sb-core", + "crates/sb-db", + "crates/sb-auth", + "crates/sb-shared", +] + +[patch.crates-io] +sb-common = { path = "/home/jan/Development/skara-brae/skara-brae-common/rust" } diff --git a/crates/sb-api/Cargo.toml b/crates/sb-api/Cargo.toml new file mode 100644 index 0000000..0a94120 --- /dev/null +++ b/crates/sb-api/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "sb-api" +version = "0.1.0" +edition = "2024" + +[dependencies] +axum = { version = "0.8", features = ["ws", "macros"] } +tokio = { version = "1", features = ["full"] } +tower = "0.5" +tower-http = { version = "0.6", features = ["cors", "trace", "compression-gzip"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } +sb-core = { path = "../sb-core" } +sb-db = { path = "../sb-db" } +sb-auth = { path = "../sb-auth" } +sb-shared = { path = "../sb-shared" } +sb-common = { path = "/home/jan/Development/skara-brae/skara-brae-common/rust" } diff --git a/crates/sb-api/src/main.rs b/crates/sb-api/src/main.rs new file mode 100644 index 0000000..25cc881 --- /dev/null +++ b/crates/sb-api/src/main.rs @@ -0,0 +1,34 @@ +#![allow(dead_code)] + +use axum::routing::get; +use axum::Router; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; + +pub mod routes; +pub mod ws; + +#[tokio::main] +async fn main() { + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer().pretty()) + .with(tracing_subscriber::EnvFilter::new( + std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into()), + )) + .init(); + + let app = Router::new() + .route("/health", get(health)) + .merge(routes::build()); + + let listener = tokio::net::TcpListener::bind("0.0.0.0:8080") + .await + .expect("failed to bind"); + + tracing::info!("listening on {:?}", listener.local_addr()); + axum::serve(listener, app).await.expect("server error"); +} + +async fn health() -> &'static str { + "ok" +} diff --git a/crates/sb-api/src/middleware/auth.rs b/crates/sb-api/src/middleware/auth.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/sb-api/src/middleware/mod.rs b/crates/sb-api/src/middleware/mod.rs new file mode 100644 index 0000000..549a9c6 --- /dev/null +++ b/crates/sb-api/src/middleware/mod.rs @@ -0,0 +1,2 @@ +pub mod auth; +pub mod rate_limit; diff --git a/crates/sb-api/src/middleware/rate_limit.rs b/crates/sb-api/src/middleware/rate_limit.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/sb-api/src/routes/mod.rs b/crates/sb-api/src/routes/mod.rs new file mode 100644 index 0000000..b98e5f6 --- /dev/null +++ b/crates/sb-api/src/routes/mod.rs @@ -0,0 +1,5 @@ +use axum::{routing::get, Router}; + +pub fn build() -> Router { + Router::new().route("/", get(|| async { "skara-brae api" })) +} diff --git a/crates/sb-api/src/ws/channels.rs b/crates/sb-api/src/ws/channels.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/sb-api/src/ws/handler.rs b/crates/sb-api/src/ws/handler.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/sb-api/src/ws/mod.rs b/crates/sb-api/src/ws/mod.rs new file mode 100644 index 0000000..42432de --- /dev/null +++ b/crates/sb-api/src/ws/mod.rs @@ -0,0 +1,2 @@ +pub mod handler; +pub mod channels; diff --git a/crates/sb-auth/Cargo.toml b/crates/sb-auth/Cargo.toml new file mode 100644 index 0000000..9493713 --- /dev/null +++ b/crates/sb-auth/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "sb-auth" +version = "0.1.0" +edition = "2024" + +[dependencies] +jsonwebtoken = "9" +argon2 = "0.5" +serde = { version = "1", features = ["derive"] } +chrono = { version = "0.4", features = ["serde"] } +sb-shared = { path = "../sb-shared" } diff --git a/crates/sb-auth/src/hash.rs b/crates/sb-auth/src/hash.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/sb-auth/src/jwt.rs b/crates/sb-auth/src/jwt.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/sb-auth/src/lib.rs b/crates/sb-auth/src/lib.rs new file mode 100644 index 0000000..1e7a355 --- /dev/null +++ b/crates/sb-auth/src/lib.rs @@ -0,0 +1,3 @@ +pub mod jwt; +pub mod hash; +pub mod session; diff --git a/crates/sb-auth/src/session.rs b/crates/sb-auth/src/session.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/sb-core/Cargo.toml b/crates/sb-core/Cargo.toml new file mode 100644 index 0000000..69ea641 --- /dev/null +++ b/crates/sb-core/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "sb-core" +version = "0.1.0" +edition = "2024" + +[dependencies] +serde = { version = "1", features = ["derive"] } +serde_json = "1" +rand = "0.9" +chrono = { version = "0.4", features = ["serde"] } +thiserror = "2" +sb-shared = { path = "../sb-shared" } +sb-common = { path = "/home/jan/Development/skara-brae/skara-brae-common/rust" } diff --git a/crates/sb-core/src/adventure/mod.rs b/crates/sb-core/src/adventure/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/adventure/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/blessings/mod.rs b/crates/sb-core/src/blessings/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/blessings/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/character/mod.rs b/crates/sb-core/src/character/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/character/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/combat/mod.rs b/crates/sb-core/src/combat/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/combat/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/crafting/mod.rs b/crates/sb-core/src/crafting/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/crafting/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/economy/mod.rs b/crates/sb-core/src/economy/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/economy/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/guild/mod.rs b/crates/sb-core/src/guild/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/guild/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/items.rs b/crates/sb-core/src/items.rs new file mode 100644 index 0000000..7129d1b --- /dev/null +++ b/crates/sb-core/src/items.rs @@ -0,0 +1,13 @@ +pub mod mod; + +use sb_common::PROJECT_NAME; + +const WEAPONS: &str = include_str!("../../../../skara-brae-common/data/items/weapons.json"); + +pub fn game_name() -> &'static str { + PROJECT_NAME +} + +pub fn load_weapons() -> Vec { + serde_json::from_str(WEAPONS).expect("failed to parse weapons data") +} diff --git a/crates/sb-core/src/lib.rs b/crates/sb-core/src/lib.rs new file mode 100644 index 0000000..2b6e7e1 --- /dev/null +++ b/crates/sb-core/src/lib.rs @@ -0,0 +1,14 @@ +#![allow(dead_code)] + +pub mod character; +pub mod combat; +pub mod adventure; +pub mod economy; +pub mod guild; +pub mod crafting; +pub mod pets; +pub mod blessings; +pub mod workers; +pub mod slayer; +pub mod world; +pub mod rules; diff --git a/crates/sb-core/src/pets/mod.rs b/crates/sb-core/src/pets/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/pets/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/rules/mod.rs b/crates/sb-core/src/rules/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/rules/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/slayer/mod.rs b/crates/sb-core/src/slayer/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/slayer/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/workers/mod.rs b/crates/sb-core/src/workers/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/workers/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-core/src/world/mod.rs b/crates/sb-core/src/world/mod.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/crates/sb-core/src/world/mod.rs @@ -0,0 +1 @@ + diff --git a/crates/sb-db/Cargo.toml b/crates/sb-db/Cargo.toml new file mode 100644 index 0000000..5c5f802 --- /dev/null +++ b/crates/sb-db/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "sb-db" +version = "0.1.0" +edition = "2024" + +[dependencies] +sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "chrono", "uuid", "migrate"] } +serde = { version = "1", features = ["derive"] } +sb-shared = { path = "../sb-shared" } diff --git a/crates/sb-db/src/lib.rs b/crates/sb-db/src/lib.rs new file mode 100644 index 0000000..7a884dd --- /dev/null +++ b/crates/sb-db/src/lib.rs @@ -0,0 +1,4 @@ +#![allow(dead_code)] + +pub mod models; +pub mod queries; diff --git a/crates/sb-db/src/migrations/mod.rs b/crates/sb-db/src/migrations/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/sb-db/src/models/mod.rs b/crates/sb-db/src/models/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/sb-db/src/queries/mod.rs b/crates/sb-db/src/queries/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/crates/sb-shared/Cargo.toml b/crates/sb-shared/Cargo.toml new file mode 100644 index 0000000..0511464 --- /dev/null +++ b/crates/sb-shared/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "sb-shared" +version = "0.1.0" +edition = "2024" + +[dependencies] +serde = { version = "1", features = ["derive"] } +serde_json = "1" +thiserror = "2" diff --git a/crates/sb-shared/src/errors.rs b/crates/sb-shared/src/errors.rs new file mode 100644 index 0000000..7f90312 --- /dev/null +++ b/crates/sb-shared/src/errors.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AppError { + pub code: String, + pub message: String, +} + +impl std::fmt::Display for AppError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}: {}", self.code, self.message) + } +} + +impl std::error::Error for AppError {} diff --git a/crates/sb-shared/src/lib.rs b/crates/sb-shared/src/lib.rs new file mode 100644 index 0000000..700f149 --- /dev/null +++ b/crates/sb-shared/src/lib.rs @@ -0,0 +1,3 @@ +pub mod errors; + +pub use errors::AppError;