Skip to content

Commit

Permalink
feat: one of the dto transformations
Browse files Browse the repository at this point in the history
  • Loading branch information
jayy-lmao committed May 31, 2024
1 parent 743742d commit a20d913
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/order_taking/common/constrained_type.gleam
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import gleam/int
import gleam/option.{type Option, None, Some}
import gleam/regex
import gleam/result
import gleam/string
import order_taking/common/decimal

Expand Down Expand Up @@ -91,7 +92,10 @@ pub fn create_like_string(
error_message: String,
) -> Result(String, String) {
let options = regex.Options(case_insensitive: False, multi_line: True)
let assert Ok(re) = regex.compile(pattern, options)
use re <- result.try(
regex.compile(pattern, options)
|> result.map_error(fn(_) { "Could not compile regex" <> pattern }),
)

case string.is_empty(str), regex.check(re, str) {
False, True -> Ok(str)
Expand Down
6 changes: 6 additions & 0 deletions src/order_taking/common/simple_types/email_address.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ pub type EmailAddress {
EmailAddress(String)
}

/// Return the value inside an EmailAddress
pub fn value(addr: EmailAddress) -> String {
let EmailAddress(str) = addr
str
}

/// Create an EmailAddress from a string
/// Return Error if input is null, empty, or doesn't have an "@" in it
pub fn create(str) -> Result(EmailAddress, String) {
Expand Down
6 changes: 6 additions & 0 deletions src/order_taking/common/simple_types/string50.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ pub type String50 {
String50(String)
}

/// Return the value inside a String50
pub fn value(str50: String50) -> String {
let String50(str) = str50
str
}

/// Create an String50 from a string
/// Return Error if input is null, empty, or length > 50
pub fn create(str) -> Result(String50, String) {
Expand Down
55 changes: 55 additions & 0 deletions src/order_taking/place_order/dto/customer_info.gleam
Original file line number Diff line number Diff line change
@@ -1,7 +1,62 @@
import gleam/result
import order_taking/common/compound_types
import order_taking/common/public_types.{
type UnvalidatedCustomerInfo, UnvalidatedCustomerInfo,
}
import order_taking/common/simple_types/email_address
import order_taking/common/simple_types/string50

//===============================================
// DTO for CustomerInfo
//===============================================

pub type CustomerInfoDto {
CustomerInfoDto(first_name: String, last_name: String, email_address: String)
}

/// Convert the DTO into a UnvalidatedCustomerInfo object.
/// This always succeeds because there is no validation.
/// Used when importing an OrderForm from the outside world into the domain.
pub fn to_unvalidated_customer_info(
dto: CustomerInfoDto,
) -> UnvalidatedCustomerInfo {
// sometimes it's helpful to use an explicit type annotation
// to avoid ambiguity between records with the same field names.
let domain_obj =
UnvalidatedCustomerInfo(
// this is a simple 1:1 copy which always succeeds
first_name: dto.first_name,
last_name: dto.last_name,
email_address: dto.email_address,
)
domain_obj
}

/// Convert the DTO into a CustomerInfo object
/// Used when importing from the outside world into the domain, eg loading from a database
pub fn to_customer_info(
dto: CustomerInfoDto,
) -> Result(compound_types.CustomerInfo, String) {
// get each (validated) simple type from the DTO as a success or failure
use first <- result.try(dto.first_name |> string50.create)
use last <- result.try(dto.last_name |> string50.create)
use email <- result.try(dto.email_address |> email_address.create)

// combine the components to create the domain object
let name = compound_types.PersonalName(first_name: first, last_name: last)
let info = compound_types.CustomerInfo(name: name, email_address: email)
Ok(info)
}

/// Convert a CustomerInfo object into the corresponding DTO.
/// Used when exporting from the domain to the outside world.
pub fn from_customer_info(
domain_obj: compound_types.CustomerInfo,
) -> CustomerInfoDto {
// this is a simple 1:1 copy
CustomerInfoDto(
first_name: domain_obj.name.first_name |> string50.value,
last_name: domain_obj.name.last_name |> string50.value,
email_address: domain_obj.email_address |> email_address.value,
)
}

0 comments on commit a20d913

Please sign in to comment.