From 44931afbe7ff5715acae1929f5e0d8a90d581f0a Mon Sep 17 00:00:00 2001 From: Peter Schiwy Date: Thu, 20 Jun 2024 14:50:36 +0200 Subject: [PATCH] test with kerkour architecture (https://kerkour.com/rust-web-application-clean-architecture) --- Cargo.lock | 189 ++++++++++++++++-- Cargo.toml | 22 +- src/config.rs | 53 +++++ src/database.rs | 23 +++ src/domain.rs | 1 + src/domain/rolle.rs | 5 + src/domain/rolle/entity.rs | 2 + src/domain/rolle/entity/rolle.rs | 9 + src/domain/rolle/model.rs | 5 + src/domain/rolle/model/create_rolle_input.rs | 7 + src/domain/rolle/model/rolle.rs | 15 ++ src/domain/rolle/model/update_rolle_input.rs | 12 ++ src/domain/rolle/repository.rs | 20 ++ src/domain/rolle/repository/create_rolle.rs | 30 +++ src/domain/rolle/repository/delete_rolle.rs | 0 src/domain/rolle/repository/find_all_rolle.rs | 0 src/domain/rolle/repository/find_rolle.rs | 0 src/domain/rolle/repository/update_rolle.rs | 0 src/domain/rolle/service.rs | 17 ++ src/domain/rolle/service/create_user.rs | 26 +++ src/main.rs | 7 + src/models/typ.rs | 3 +- src/scalar.rs | 10 + 23 files changed, 431 insertions(+), 25 deletions(-) create mode 100644 src/config.rs create mode 100644 src/database.rs create mode 100644 src/domain.rs create mode 100644 src/domain/rolle.rs create mode 100644 src/domain/rolle/entity.rs create mode 100644 src/domain/rolle/entity/rolle.rs create mode 100644 src/domain/rolle/model.rs create mode 100644 src/domain/rolle/model/create_rolle_input.rs create mode 100644 src/domain/rolle/model/rolle.rs create mode 100644 src/domain/rolle/model/update_rolle_input.rs create mode 100644 src/domain/rolle/repository.rs create mode 100644 src/domain/rolle/repository/create_rolle.rs create mode 100644 src/domain/rolle/repository/delete_rolle.rs create mode 100644 src/domain/rolle/repository/find_all_rolle.rs create mode 100644 src/domain/rolle/repository/find_rolle.rs create mode 100644 src/domain/rolle/repository/update_rolle.rs create mode 100644 src/domain/rolle/service.rs create mode 100644 src/domain/rolle/service/create_user.rs create mode 100644 src/scalar.rs diff --git a/Cargo.lock b/Cargo.lock index 2e2635e..1ec14a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,9 +127,9 @@ checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "async-graphql" -version = "7.0.5" +version = "7.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0808e3dc8be9cee801000b9261081cd7caae9935658be7e52d4df3d5c22bdce" +checksum = "bf338d20ba5bab309f55ce8df95d65ee19446f7737f06f4a64593ab2c6b546ad" dependencies = [ "async-graphql-derive", "async-graphql-parser", @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "async-graphql-axum" -version = "7.0.5" +version = "7.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d94b2673899046dbbb803dff9c400330f7908727f5edb99979c3d841136ee754" +checksum = "28f874ad4bc10519f3fa500e36814452033a5ce9ea681ab0a2e0d3b1f18bae44" dependencies = [ "async-graphql", "async-trait", @@ -181,9 +181,9 @@ dependencies = [ [[package]] name = "async-graphql-derive" -version = "7.0.5" +version = "7.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae80fb7b67deeae84441a9eb156359b99be7902d2d706f43836156eec69a8226" +checksum = "fc51fd6b7102acda72bc94e8ae1543844d5688ff394a6cf7c21f2a07fe2d64e4" dependencies = [ "Inflector", "async-graphql-parser", @@ -198,9 +198,9 @@ dependencies = [ [[package]] name = "async-graphql-parser" -version = "7.0.5" +version = "7.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f0fffb19cd96eb084428289f4568b5ad48df32f782f891f709db96384fbdeb2" +checksum = "75361eefd64e39f89bead4cb45fddbaf60ddb0e7b15fb7c852b6088bcd63071f" dependencies = [ "async-graphql-value", "pest", @@ -210,9 +210,9 @@ dependencies = [ [[package]] name = "async-graphql-value" -version = "7.0.5" +version = "7.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c224c93047a7197fe0f1d6eee98245ba6049706c6c04a372864557fb61495e94" +checksum = "c1f665d2d52b41c4ed1f01c43f3ef27a2fe0af2452ed5c8bc7ac9b1a8719afaa" dependencies = [ "bytes", "indexmap", @@ -317,10 +317,14 @@ dependencies = [ "chrono", "dotenv", "env_logger", + "envy", "log", "serde", "sqlx", "tokio", + "tracing", + "tracing-subscriber", + "ulid", "uuid", ] @@ -656,6 +660,15 @@ dependencies = [ "log", ] +[[package]] +name = "envy" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f47e0157f2cb54f5ae1bd371b30a2ae4311e1c028f575cd4e81de7353215965" +dependencies = [ + "serde", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -843,8 +856,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1163,6 +1178,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "matchit" version = "0.7.3" @@ -1262,6 +1286,16 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -1378,6 +1412,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "parking_lot" version = "0.12.3" @@ -1615,8 +1655,17 @@ checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", ] [[package]] @@ -1627,9 +1676,15 @@ checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.3", ] +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + [[package]] name = "regex-syntax" version = "0.8.3" @@ -1800,6 +1855,15 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "signature" version = "2.2.0" @@ -2191,6 +2255,16 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -2208,9 +2282,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -2225,9 +2299,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", @@ -2346,6 +2420,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "chrono", + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", ] [[package]] @@ -2379,6 +2484,18 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" +[[package]] +name = "ulid" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34778c17965aa2a08913b57e1f34db9b4a63f5de31768b55bf20d2795f921259" +dependencies = [ + "getrandom", + "rand", + "uuid", + "web-time", +] + [[package]] name = "unicode-bidi" version = "0.3.15" @@ -2457,6 +2574,12 @@ dependencies = [ "serde", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" @@ -2535,6 +2658,16 @@ version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "whoami" version = "1.5.1" @@ -2545,6 +2678,28 @@ dependencies = [ "wasite", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 49d48c8..ba34659 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,6 @@ async-graphql = { version = "7.0.5", default-features = false, features = [ 'graphiql', 'playground', ] } -uuid = { version = "1.8.0", features = ["serde", "v4"] } axum = { version = "0.7.5", features = ["macros"] } sqlx = { version = "0.7.4", features = [ "runtime-tokio-native-tls", @@ -21,11 +20,20 @@ sqlx = { version = "0.7.4", features = [ "chrono", "macros", ] } -anyhow = "1.0.53" -async-graphql-axum = "7.0.5" -chrono = { version = "0.4.19", features = ["serde"] } +anyhow = "1.0.86" +async-graphql-axum = "7.0.6" +chrono = { version = "0.4.38", features = ["serde"] } dotenv = "0.15.0" +envy = "0.4.2" env_logger = "0.11.3" -log = "0.4.14" -serde = "1.0.136" -tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"] } +log = "0.4.21" +serde = "1.0.203" +tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] } + +# UUID +uuid = { version = "1.8.0", features = ["serde", "v4"] } +ulid = { version = "1.1.2", features = ["uuid"] } + +# Logging +tracing = "0.1.40" +tracing-subscriber = { version = "0.3.18", features = ["env-filter", "chrono"] } diff --git a/src/config.rs b/src/config.rs new file mode 100644 index 0000000..41e1595 --- /dev/null +++ b/src/config.rs @@ -0,0 +1,53 @@ +use anyhow::Error; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Config { + pub http: Http, + pub database: Database, + pub graphql: Grapthql, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Http { + pub host: String, + pub port: u16, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Database { + pub url: String, + pub pool_size: u32, + pub max_lifetime: u64, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Grapthql { + pub schema_location: String, +} + +impl Config { + pub fn load() -> Result { + dotenv::dotenv().ok(); + + let http = envy::prefixed("HTTP_") + .from_env::() + .expect("Failed to load http config"); + + let database = envy::prefixed("DATABASE_") + .from_env::() + .expect("Failed to load database config"); + + let graphql = envy::prefixed("GRAPHQL_") + .from_env::() + .expect("Failed to load graphql config"); + + let config = Self { + http, + database, + graphql, + }; + + Ok(config) + } +} diff --git a/src/database.rs b/src/database.rs new file mode 100644 index 0000000..79ca7c8 --- /dev/null +++ b/src/database.rs @@ -0,0 +1,23 @@ +use std::time::Duration; + +use anyhow::Error; +use sqlx::{self, postgres::PgPoolOptions, Executor, Pool, Postgres}; + +use crate::config; + +pub type DB = Pool; +pub trait Queryer<'c>: Executor<'c, Database = sqlx::Postgres> {} + +impl<'c> Queryer<'c> for &Pool {} + +pub async fn connect(database: &config::Database) -> Result { + PgPoolOptions::new() + .max_connections(database.pool_size) + .max_lifetime(Duration::from_secs(database.max_lifetime)) + .connect(&database.url) + .await + .map_err(|err| { + tracing::error!("{}", err); + err.into() + }) +} diff --git a/src/domain.rs b/src/domain.rs new file mode 100644 index 0000000..6c5482c --- /dev/null +++ b/src/domain.rs @@ -0,0 +1 @@ +pub mod rolle; diff --git a/src/domain/rolle.rs b/src/domain/rolle.rs new file mode 100644 index 0000000..e8cc49b --- /dev/null +++ b/src/domain/rolle.rs @@ -0,0 +1,5 @@ +pub mod entity; +pub mod model; +pub mod repository; +pub mod service; + diff --git a/src/domain/rolle/entity.rs b/src/domain/rolle/entity.rs new file mode 100644 index 0000000..85a549e --- /dev/null +++ b/src/domain/rolle/entity.rs @@ -0,0 +1,2 @@ +pub mod rolle; +pub use rolle::Rolle; diff --git a/src/domain/rolle/entity/rolle.rs b/src/domain/rolle/entity/rolle.rs new file mode 100644 index 0000000..5e6217e --- /dev/null +++ b/src/domain/rolle/entity/rolle.rs @@ -0,0 +1,9 @@ +use crate::scalar::{Id, Time}; + +#[derive(sqlx::FromRow)] +pub struct Rolle { + pub id: Id, + pub created_at: Time, + pub updated_at: Time, + pub name: String, +} diff --git a/src/domain/rolle/model.rs b/src/domain/rolle/model.rs new file mode 100644 index 0000000..e9e6de2 --- /dev/null +++ b/src/domain/rolle/model.rs @@ -0,0 +1,5 @@ +mod create_rolle_input; +mod rolle; +mod update_rolle_input; + +pub use create_rolle_input::CreateRolleInput; diff --git a/src/domain/rolle/model/create_rolle_input.rs b/src/domain/rolle/model/create_rolle_input.rs new file mode 100644 index 0000000..6b7eeb9 --- /dev/null +++ b/src/domain/rolle/model/create_rolle_input.rs @@ -0,0 +1,7 @@ +use async_graphql::InputObject; + +#[derive(InputObject)] +pub struct CreateRolleInput { + /// Der Name einer Rolle + pub name: String, +} diff --git a/src/domain/rolle/model/rolle.rs b/src/domain/rolle/model/rolle.rs new file mode 100644 index 0000000..c954d57 --- /dev/null +++ b/src/domain/rolle/model/rolle.rs @@ -0,0 +1,15 @@ +use async_graphql::SimpleObject; + +use crate::scalar::{Id, Time}; + +#[derive(Debug, SimpleObject)] +pub struct Rolle { + /// Die ID einer Rolle + pub id: Id, + + /// Wann die Rolle erstellt wurde + pub created_at: Time, + + /// Der Name einer Rolle + pub name: String, +} diff --git a/src/domain/rolle/model/update_rolle_input.rs b/src/domain/rolle/model/update_rolle_input.rs new file mode 100644 index 0000000..8dbc231 --- /dev/null +++ b/src/domain/rolle/model/update_rolle_input.rs @@ -0,0 +1,12 @@ +use async_graphql::InputObject; + +use crate::scalar::Id; + +#[derive(InputObject)] +pub struct UpdateRolleInput { + /// Die ID einer Rolle + pub id: Id, + + /// Der Name einer Rolle + pub name: String, +} diff --git a/src/domain/rolle/repository.rs b/src/domain/rolle/repository.rs new file mode 100644 index 0000000..846849e --- /dev/null +++ b/src/domain/rolle/repository.rs @@ -0,0 +1,20 @@ +mod create_rolle; +mod delete_rolle; +mod find_all_rolle; +mod find_rolle; +mod update_rolle; + +#[derive(Debug, Clone)] +pub struct Repository {} + +impl Repository { + pub fn new() -> Repository { + Repository {} + } +} + +impl Default for Repository { + fn default() -> Self { + Self::new() + } +} diff --git a/src/domain/rolle/repository/create_rolle.rs b/src/domain/rolle/repository/create_rolle.rs new file mode 100644 index 0000000..1e90476 --- /dev/null +++ b/src/domain/rolle/repository/create_rolle.rs @@ -0,0 +1,30 @@ +use anyhow::Error; + +use super::Repository; +use crate::{database::Queryer, domain::rolle::entity}; + +impl Repository { + pub async fn create_rolle<'c, C: Queryer<'c>>( + &self, + db: C, + rolle: &entity::Rolle, + ) -> Result { + const QUERY: &str = "insert into rolle (id, created_at, updated_at, + name) values ($1, $2, $3, $4) returning *"; + + match sqlx::query_as::<_, entity::Rolle>(QUERY) + .bind(rolle.id) + .bind(rolle.created_at) + .bind(rolle.updated_at) + .bind(&rolle.name) + .fetch_one(db) + .await + { + Err(err) => { + tracing::error!("{}", &err); + Err(err.into()) + } + Ok(user) => Ok(user), + } + } +} diff --git a/src/domain/rolle/repository/delete_rolle.rs b/src/domain/rolle/repository/delete_rolle.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/domain/rolle/repository/find_all_rolle.rs b/src/domain/rolle/repository/find_all_rolle.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/domain/rolle/repository/find_rolle.rs b/src/domain/rolle/repository/find_rolle.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/domain/rolle/repository/update_rolle.rs b/src/domain/rolle/repository/update_rolle.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/domain/rolle/service.rs b/src/domain/rolle/service.rs new file mode 100644 index 0000000..1b55aea --- /dev/null +++ b/src/domain/rolle/service.rs @@ -0,0 +1,17 @@ +mod create_user; + +use super::repository::Repository; +use crate::database::DB; + +#[derive(Debug)] +pub struct Service { + repo: Repository, + pub db: DB, +} + +impl Service { + pub fn new(db: DB) -> Self { + let repo = Repository::new(); + Self { repo, db } + } +} diff --git a/src/domain/rolle/service/create_user.rs b/src/domain/rolle/service/create_user.rs new file mode 100644 index 0000000..7f17cad --- /dev/null +++ b/src/domain/rolle/service/create_user.rs @@ -0,0 +1,26 @@ +use anyhow::Error; +use chrono::Utc; +use ulid::Ulid; + +use super::Service; +use crate::domain::rolle::entity; +use crate::domain::rolle::model::CreateRolleInput; + +impl Service { + pub async fn create_rolle(&self, input: CreateRolleInput) -> Result { + // let username_exists = self.check_username_exists(&self.db, &input.name).await?; + // if username_exists { + // return Err(Error::UsernameAlreadyExists.into()); + // } + + let rolle_input = entity::Rolle { + id: Ulid::new().into(), + name: input.name, + created_at: Utc::now(), + updated_at: Utc::now(), + }; + + let rolle = self.repo.create_rolle(&self.db, &rolle_input).await?; + Ok(rolle) + } +} diff --git a/src/main.rs b/src/main.rs index 87684bb..c61347d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ use axum::{ routing::get, Router, }; +use config::Config; use dotenv::dotenv; use mutations::Mutation; use queries::Query; @@ -15,9 +16,13 @@ use sqlx::postgres::PgPool; use std::env; use tokio::net::TcpListener; +mod config; +mod database; +mod domain; mod models; mod mutations; mod queries; +mod scalar; async fn ping() -> String { format!( @@ -36,6 +41,8 @@ async fn main() -> Result<()> { dotenv().ok(); env_logger::init(); + Config::load(); + let database_url = env::var("DATABASE_URL").expect("DATABASE_URL is not set"); let db_pool = PgPool::connect(&database_url).await?; diff --git a/src/models/typ.rs b/src/models/typ.rs index 8ebecfd..e81008d 100644 --- a/src/models/typ.rs +++ b/src/models/typ.rs @@ -5,9 +5,10 @@ use sqlx::{FromRow, PgPool, Type}; #[derive(SimpleObject, Debug, FromRow, Deserialize, Serialize, Type)] pub struct Typ { + /// Die ID eines Geräte-Typs pub id: i32, - /// Name eines Typs + /// Der Name eines Geräte-Typs pub name: String, } diff --git a/src/scalar.rs b/src/scalar.rs new file mode 100644 index 0000000..fe5815d --- /dev/null +++ b/src/scalar.rs @@ -0,0 +1,10 @@ +/// It is easier to track each type alias if this file is located on the top-level directory (here) +/// than in each domain. Also, separating them will create a lot of duplicate code. +use uuid::Uuid; + +pub type Time = chrono::DateTime; + +/// The ID scalar type represents a unique identifier, often used to refetch an object or as key for a cache. +/// The ID type appears in a JSON response as a String; however, it is not intended to be human-readable. +/// When expected as an input type, any string (such as "4") or integer (such as 4) input value will be accepted as an ID. +pub type Id = Uuid;