diff --git a/Cargo.lock b/Cargo.lock index aa7668c..8473287 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -619,7 +619,7 @@ dependencies = [ [[package]] name = "bookshelf-api" -version = "1.0.0" +version = "1.0.1" dependencies = [ "actix-cors", "actix-web", diff --git a/src/bin/import_from_v1_backup.rs b/src/bin/import_from_v1_backup.rs index d0a70dc..fe97763 100644 --- a/src/bin/import_from_v1_backup.rs +++ b/src/bin/import_from_v1_backup.rs @@ -1,9 +1,8 @@ use bookshelf_api::{ + common::types::{BookFormat, BookStore}, domain::entity::{ author::{Author, AuthorId, AuthorName}, - book::{ - Book, BookFormat, BookId, BookStore, BookTitle, Isbn, OwnedFlag, Priority, ReadFlag, - }, + book::{Book, BookId, BookTitle, Isbn, OwnedFlag, Priority, ReadFlag}, user::UserId, }, infrastructure::{ diff --git a/src/common.rs b/src/common.rs new file mode 100644 index 0000000..cd40856 --- /dev/null +++ b/src/common.rs @@ -0,0 +1 @@ +pub mod types; diff --git a/src/common/types.rs b/src/common/types.rs new file mode 100644 index 0000000..fe7c5d5 --- /dev/null +++ b/src/common/types.rs @@ -0,0 +1,82 @@ +use derive_more::Display; +use thiserror::Error; + +#[derive(Debug, Clone, PartialEq, Eq, Display)] +pub enum BookFormat { + #[display(fmt = "eBook")] + EBook, + Printed, + Unknown, +} + +impl TryFrom<&str> for BookFormat { + type Error = ParseBookFormatError; + + fn try_from(value: &str) -> Result { + match value { + "eBook" => Ok(BookFormat::EBook), + "Printed" => Ok(BookFormat::Printed), + "Unknown" => Ok(BookFormat::Unknown), + _ => Err(ParseBookFormatError(format!( + "{} is not valid format", + value + ))), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Display)] +pub enum BookStore { + Kindle, + Unknown, +} + +impl TryFrom<&str> for BookStore { + type Error = ParseBookStoreError; + + fn try_from(value: &str) -> Result { + match value { + "Kindle" => Ok(BookStore::Kindle), + "Unknown" => Ok(BookStore::Unknown), + _ => Err(ParseBookStoreError(format!("{} is not valid store", value))), + } + } +} + +#[derive(Debug, Error)] +#[error("{0}")] +pub struct ParseBookFormatError(String); + +#[derive(Debug, Error)] +#[error("{0}")] +pub struct ParseBookStoreError(String); + +#[cfg(test)] +mod test { + use crate::common::types::{BookFormat, BookStore}; + + #[test] + fn book_format_ebook_to_string() { + assert_eq!(BookFormat::EBook.to_string(), "eBook"); + } + + #[test] + fn book_format_printed_to_string() { + assert_eq!(BookFormat::Printed.to_string(), "Printed"); + } + + #[test] + fn book_format_unknown_to_string() { + assert_eq!(BookFormat::Unknown.to_string(), "Unknown"); + } + + #[test] + fn book_store_kindle_to_string() { + assert_eq!(BookStore::Kindle.to_string(), "Kindle"); + } + + #[test] + fn book_store_unknown_to_string() { + assert_eq!(BookStore::Unknown.to_string(), "Unknown"); + } +} diff --git a/src/domain/entity/book.rs b/src/domain/entity/book.rs index cdc2cda..5a09eb2 100644 --- a/src/domain/entity/book.rs +++ b/src/domain/entity/book.rs @@ -1,4 +1,3 @@ -use derive_more::Display; use getset::{Getters, Setters}; use once_cell::sync::Lazy; use regex::Regex; @@ -6,7 +5,11 @@ use time::OffsetDateTime; use uuid::Uuid; use validator::Validate; -use crate::{domain::error::DomainError, impl_string_value_object}; +use crate::{ + common::types::{BookFormat, BookStore}, + domain::error::DomainError, + impl_string_value_object, +}; use super::author::AuthorId; @@ -112,51 +115,6 @@ impl Priority { } } -#[derive(Debug, Clone, PartialEq, Eq, Display)] -pub enum BookFormat { - #[display(fmt = "eBook")] - EBook, - Printed, - Unknown, -} - -impl TryFrom<&str> for BookFormat { - type Error = DomainError; - - fn try_from(value: &str) -> Result { - match value { - "eBook" => Ok(BookFormat::EBook), - "Printed" => Ok(BookFormat::Printed), - "Unknown" => Ok(BookFormat::Unknown), - _ => Err(DomainError::Validation(format!( - "{} is not valid format", - value - ))), - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Display)] -pub enum BookStore { - Kindle, - Unknown, -} - -impl TryFrom<&str> for BookStore { - type Error = DomainError; - - fn try_from(value: &str) -> Result { - match value { - "Kindle" => Ok(BookStore::Kindle), - "Unknown" => Ok(BookStore::Unknown), - _ => Err(DomainError::Validation(format!( - "{} is not valid store", - value - ))), - } - } -} - #[derive(Debug, Clone, PartialEq, Eq, Getters, Setters)] pub struct Book { #[getset(get = "pub")] @@ -247,8 +205,6 @@ impl Book { #[cfg(test)] mod test { - use crate::domain::entity::book::{BookFormat, BookStore}; - use super::{Isbn, Priority}; #[test] @@ -298,29 +254,4 @@ mod test { let priority = Priority::new(101); assert!(matches!(priority, Err(_))); } - - #[test] - fn book_format_ebook_to_string() { - assert_eq!(BookFormat::EBook.to_string(), "eBook"); - } - - #[test] - fn book_format_printed_to_string() { - assert_eq!(BookFormat::Printed.to_string(), "Printed"); - } - - #[test] - fn book_format_unknown_to_string() { - assert_eq!(BookFormat::Unknown.to_string(), "Unknown"); - } - - #[test] - fn book_store_kindle_to_string() { - assert_eq!(BookStore::Kindle.to_string(), "Kindle"); - } - - #[test] - fn book_store_unknown_to_string() { - assert_eq!(BookStore::Unknown.to_string(), "Unknown"); - } } diff --git a/src/domain/error.rs b/src/domain/error.rs index cadfa3d..6eeeea9 100644 --- a/src/domain/error.rs +++ b/src/domain/error.rs @@ -1,6 +1,8 @@ use thiserror::Error; use validator::ValidationErrors; +use crate::common::types::{ParseBookFormatError, ParseBookStoreError}; + #[derive(Debug, Error)] pub enum DomainError { #[error("{0}")] @@ -22,3 +24,15 @@ impl From for DomainError { DomainError::Validation(err.to_string()) } } + +impl From for DomainError { + fn from(err: ParseBookStoreError) -> Self { + DomainError::Validation(err.to_string()) + } +} + +impl From for DomainError { + fn from(err: ParseBookFormatError) -> Self { + DomainError::Validation(err.to_string()) + } +} diff --git a/src/infrastructure/book_repository.rs b/src/infrastructure/book_repository.rs index 594aae9..3e9d2d2 100644 --- a/src/infrastructure/book_repository.rs +++ b/src/infrastructure/book_repository.rs @@ -4,16 +4,17 @@ use sqlx::{PgConnection, PgPool}; use time::OffsetDateTime; use uuid::Uuid; -use crate::domain::{ - entity::{ - author::AuthorId, - book::{ - Book, BookFormat, BookId, BookStore, BookTitle, Isbn, OwnedFlag, Priority, ReadFlag, +use crate::{ + common::types::{BookFormat, BookStore}, + domain::{ + entity::{ + author::AuthorId, + book::{Book, BookId, BookTitle, Isbn, OwnedFlag, Priority, ReadFlag}, + user::UserId, }, - user::UserId, + error::DomainError, + repository::book_repository::BookRepository, }, - error::DomainError, - repository::book_repository::BookRepository, }; #[derive(sqlx::FromRow)] diff --git a/src/lib.rs b/src/lib.rs index f973747..8b8cb51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +pub mod common; pub mod dependency_injection; pub mod domain; pub mod extractors; diff --git a/src/presentational/graphql/object.rs b/src/presentational/graphql/object.rs index 940f203..f69b0f2 100644 --- a/src/presentational/graphql/object.rs +++ b/src/presentational/graphql/object.rs @@ -2,12 +2,11 @@ use async_graphql::dataloader::DataLoader; use async_graphql::{ComplexObject, Context, Enum, Result}; use async_graphql::{InputObject, SimpleObject, ID}; +use crate::common::types::{BookFormat as CommonBookFormat, BookStore as CommonBookStore}; use crate::dependency_injection::QI; -use crate::domain; use crate::use_case::dto::author::AuthorDto; use crate::use_case::dto::author::CreateAuthorDto; use crate::use_case::dto::book::{BookDto, CreateBookDto, UpdateBookDto}; -use domain::entity::book::{BookFormat as DomainBookFormat, BookStore as DomainBookStore}; use super::loader::AuthorLoader; @@ -29,22 +28,22 @@ pub enum BookFormat { Unknown, } -impl From for BookFormat { - fn from(book_format: DomainBookFormat) -> Self { +impl From for BookFormat { + fn from(book_format: CommonBookFormat) -> Self { match book_format { - DomainBookFormat::EBook => BookFormat::EBook, - DomainBookFormat::Printed => BookFormat::Printed, - DomainBookFormat::Unknown => BookFormat::Unknown, + CommonBookFormat::EBook => BookFormat::EBook, + CommonBookFormat::Printed => BookFormat::Printed, + CommonBookFormat::Unknown => BookFormat::Unknown, } } } -impl From for DomainBookFormat { +impl From for CommonBookFormat { fn from(book_format: BookFormat) -> Self { match book_format { - BookFormat::EBook => DomainBookFormat::EBook, - BookFormat::Printed => DomainBookFormat::Printed, - BookFormat::Unknown => DomainBookFormat::Unknown, + BookFormat::EBook => CommonBookFormat::EBook, + BookFormat::Printed => CommonBookFormat::Printed, + BookFormat::Unknown => CommonBookFormat::Unknown, } } } @@ -55,20 +54,20 @@ pub enum BookStore { Unknown, } -impl From for BookStore { - fn from(book_format: DomainBookStore) -> Self { +impl From for BookStore { + fn from(book_format: CommonBookStore) -> Self { match book_format { - DomainBookStore::Kindle => BookStore::Kindle, - DomainBookStore::Unknown => BookStore::Unknown, + CommonBookStore::Kindle => BookStore::Kindle, + CommonBookStore::Unknown => BookStore::Unknown, } } } -impl From for DomainBookStore { +impl From for CommonBookStore { fn from(book_format: BookStore) -> Self { match book_format { - BookStore::Kindle => DomainBookStore::Kindle, - BookStore::Unknown => DomainBookStore::Unknown, + BookStore::Kindle => CommonBookStore::Kindle, + BookStore::Unknown => CommonBookStore::Unknown, } } } diff --git a/src/use_case/dto/book.rs b/src/use_case/dto/book.rs index bd3ea2a..99c33f4 100644 --- a/src/use_case/dto/book.rs +++ b/src/use_case/dto/book.rs @@ -2,13 +2,11 @@ use time::OffsetDateTime; use uuid::Uuid; use crate::{ + common::types::{BookFormat, BookStore}, domain::{ entity::{ author::AuthorId, - book::{ - Book, BookFormat, BookId, BookStore, BookTitle, DestructureBook, Isbn, OwnedFlag, - Priority, ReadFlag, - }, + book::{Book, BookId, BookTitle, DestructureBook, Isbn, OwnedFlag, Priority, ReadFlag}, }, error::DomainError, },