diff --git a/Cargo.lock b/Cargo.lock index 3dee1c1..7a1fa0f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,6 +28,17 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "async-trait" +version = "0.1.51" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "atoi" version = "0.4.0" @@ -455,6 +466,7 @@ dependencies = [ name = "lib" version = "0.1.0" dependencies = [ + "async-trait", "directories", "sqlx", "tokio", diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 756a4f2..1234e51 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -7,3 +7,4 @@ edition = "2018" directories = "3.0" sqlx = { version = "0.5", default-features = false, features = [ "sqlite", "chrono", "macros", "migrate", "runtime-tokio-rustls"] } tokio = { version = "1.6", features = [ "rt", "macros" ] } +async-trait = "0.1" diff --git a/lib/src/database.rs b/lib/src/database.rs index 0fca8bb..ba02071 100644 --- a/lib/src/database.rs +++ b/lib/src/database.rs @@ -25,11 +25,11 @@ use sqlx::sqlite::SqliteConnectOptions; use sqlx::sqlite::SqlitePoolOptions; use sqlx::Pool; -async fn connect() -> Result, sqlx::Error> { +pub async fn connect() -> Result, sqlx::Error> { connect_with(&default_filename()).await } -async fn connect_with(filename: &Path) -> Result, sqlx::Error> { +pub async fn connect_with(filename: &Path) -> Result, sqlx::Error> { let pool = SqlitePoolOptions::new() .connect_with( SqliteConnectOptions::new() diff --git a/lib/src/domain/command.rs b/lib/src/domain/command.rs index 28911e4..00f0143 100644 --- a/lib/src/domain/command.rs +++ b/lib/src/domain/command.rs @@ -16,16 +16,27 @@ along with this program. If not, see . */ +use async_trait::async_trait; + /// Trait/tag for DTOs pub trait Dto {} /// Trait that all commands must implement. +#[async_trait] pub trait Command { - async fn execute(self) -> Result; + async fn execute(&self) -> Result<&T, CommandError>; } /// Errors produced by invalid commands pub enum CommandError { /// The request identified used in the command is already used. IdentifierAlreadyUsed(String), + /// Erro with the database + DatabaseError, +} + +impl From for CommandError { + fn from(_error: sqlx::Error) -> Self { + Self::DatabaseError + } } diff --git a/lib/src/domain/project/create.rs b/lib/src/domain/project/create.rs index 120c5cd..513e6af 100644 --- a/lib/src/domain/project/create.rs +++ b/lib/src/domain/project/create.rs @@ -16,6 +16,8 @@ along with this program. If not, see . */ +use async_trait::async_trait; + use super::dto::Project; use super::repository::Repository; use crate::database; @@ -30,11 +32,13 @@ impl Create { } } +#[async_trait] impl Command for Create { - async fn execute(self) -> Result { + async fn execute(&self) -> Result<&Project, CommandError> { let pool = database::connect().await?; let repo = Repository::new(&pool); - Ok(self.0) + repo.save(&self.0).await?; + Ok(&self.0) } } diff --git a/lib/src/domain/project/repository.rs b/lib/src/domain/project/repository.rs index ccee4ce..0d64e15 100644 --- a/lib/src/domain/project/repository.rs +++ b/lib/src/domain/project/repository.rs @@ -21,21 +21,21 @@ use sqlx::Pool; use super::dto::Project; -struct Repository<'a> { +pub struct Repository<'a> { pool: &'a Pool, } impl<'a> Repository<'a> { - fn new(pool: &'a Pool) -> Self { + pub fn new(pool: &'a Pool) -> Self { Self { pool } } - async fn save(&self, project: Project) -> Result { + pub async fn save(&self, project: &Project) -> Result<(), sqlx::Error> { sqlx::query(r#"INSERT INTO project (code, name) VALUES (?, ?)"#) .bind(&project.code()) .bind(&project.name()) .execute(self.pool) .await?; - Ok(project) + Ok(()) } }