Skip to content

Commit 3905577

Browse files
committed
fix: wip json serial
1 parent fcbfc84 commit 3905577

File tree

5 files changed

+156
-7
lines changed

5 files changed

+156
-7
lines changed

gleam.toml

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ gleam = ">= 0.32.0"
1212

1313
[dependencies]
1414
gleam_stdlib = "~> 0.38"
15+
gleam_http = ">= 3.6.0 and < 4.0.0"
16+
gleam_json = ">= 2.0.0 and < 3.0.0"
1517

1618
[dev-dependencies]
1719
gleeunit = "~> 1.0.2"

manifest.toml

+4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
# You typically do not need to edit this file
33

44
packages = [
5+
{ name = "gleam_http", version = "3.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8C07DF9DF8CC7F054C650839A51C30A7D3C26482AC241C899C1CEA86B22DBE51" },
6+
{ name = "gleam_json", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "CB10B0E7BF44282FB25162F1A24C1A025F6B93E777CCF238C4017E4EEF2CDE97" },
57
{ name = "gleam_stdlib", version = "0.38.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "663CF11861179AF415A625307447775C09404E752FF99A24E2057C835319F1BE" },
68
{ name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" },
79
]
810

911
[requirements]
12+
gleam_http = { version = ">= 3.6.0 and < 4.0.0" }
13+
gleam_json = { version = ">= 2.0.0 and < 3.0.0"}
1014
gleam_stdlib = { version = "~> 0.38" }
1115
gleeunit = { version = "~> 1.0.2" }
+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// ======================================================
2+
// This file contains the JSON API interface to the PlaceOrder workflow
3+
//
4+
// 1) The HttpRequest is turned into a DTO, which is then turned into a Domain object
5+
// 2) The main workflow function is called
6+
// 3) The output is turned into a DTO which is turned into a HttpResponse
7+
// ======================================================
8+
9+
import gleam/http/request
10+
import gleam/http/response
11+
import gleam/json
12+
import gleam/list
13+
import gleam/result
14+
import order_taking/common/public_types
15+
import order_taking/common/simple_types/price
16+
import order_taking/place_order/dto/place_order_event_dto
17+
import order_taking/place_order/implementation
18+
19+
pub type JsonString =
20+
String
21+
22+
// pub type PlaceOrderApi =
23+
// fn(request.Request) -> response.Response
24+
25+
// =============================
26+
// Implementation
27+
// =============================
28+
29+
/// Very simplified version!
30+
/// An API takes a HttpRequest as input and returns a async response
31+
/// setup dummy dependencies
32+
pub fn check_product_exists(_product_code) {
33+
True
34+
}
35+
36+
/// dummy implementation
37+
pub fn check_address_exists(unvalidated_address) {
38+
let checked_address = implementation.CheckedAddress(unvalidated_address)
39+
40+
checked_address
41+
}
42+
43+
/// dummy implementation
44+
pub fn get_product_price(_product_code) {
45+
price.from_int(1)
46+
}
47+
48+
/// dummy implementation
49+
pub fn create_order_acknowledgment_letter(_priced_order) {
50+
let letter_test = implementation.HtmlString("some text")
51+
letter_test
52+
}
53+
54+
/// dummy implementation
55+
pub fn send_order_acknowledgment(_order_acknowledgement) {
56+
implementation.Sent
57+
}
58+
59+
// // -------------------------------
60+
// // workflow
61+
// // -------------------------------
62+
63+
/// This function converts the workflow output into a HttpResponse
64+
pub fn workflow_result_to_http_reponse(result) -> response.Response(String) {
65+
case result {
66+
Ok(events) -> {
67+
// turn domain events into dtos
68+
let dtos =
69+
events
70+
|> list.map(place_order_event_dto.from_domain)
71+
72+
// and serialize to JSON
73+
let json =
74+
dtos
75+
|> list.map(fn(event) { todo })
76+
77+
let response = response.Response()
78+
response
79+
}
80+
Error(err) ->
81+
// // turn domain errors into a dto
82+
// let dto = err |> PlaceOrderErrorDto.fromDomain
83+
// // and serialize to JSON
84+
// let json = serializeJson(dto )
85+
// let response =
86+
// {
87+
// HttpStatusCode = 401
88+
// Body = json
89+
// }
90+
// response
91+
todo
92+
}
93+
}
94+
// let placeOrderApi : PlaceOrderApi =
95+
// fun request ->
96+
// // following the approach in "A Complete Serialization Pipeline" in chapter 11
97+
98+
// // start with a string
99+
// let orderFormJson = request.Body
100+
// let orderForm = deserializeJson<OrderFormDto>(orderFormJson)
101+
// // convert to domain object
102+
// let unvalidatedOrder = orderForm |> OrderFormDto.toUnvalidatedOrder
103+
104+
// // setup the dependencies. See "Injecting Dependencies" in chapter 9
105+
// let workflow =
106+
// Implementation.placeOrder
107+
// checkProductExists // dependency
108+
// checkAddressExists // dependency
109+
// getProductPrice // dependency
110+
// createOrderAcknowledgmentLetter // dependency
111+
// sendOrderAcknowledgment // dependency
112+
113+
// // now we are in the pure domain
114+
// let asyncResult = workflow unvalidatedOrder
115+
116+
// // now convert from the pure domain back to a HttpResponse
117+
// asyncResult
118+
// |> Async.map (workflowResultToHttpReponse)

src/order_taking/place_order/dto/address_dto.gleam

+32-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import gleam/option.{type Option, None}
1+
import gleam/json
2+
import gleam/option
23
import gleam/result.{try}
34
import order_taking/common/compound_types
45
import order_taking/common/public_types
@@ -8,14 +9,38 @@ import order_taking/common/simple_types/zip_code
89
pub type AddressDto {
910
AddressDto(
1011
address_line_1: String,
11-
address_line_2: Option(String),
12-
address_line_3: Option(String),
13-
address_line_4: Option(String),
12+
address_line_2: option.Option(String),
13+
address_line_3: option.Option(String),
14+
address_line_4: option.Option(String),
1415
city: String,
1516
zip_code: String,
1617
)
1718
}
1819

20+
pub fn to_json(dto: AddressDto) {
21+
json.object([
22+
#("address_line_1", json.string(dto.address_line_1)),
23+
#(
24+
"address_line_2",
25+
dto.address_line_2
26+
|> option.map(json.string)
27+
|> option.unwrap(json.null()),
28+
),
29+
#(
30+
"address_line_3",
31+
dto.address_line_3
32+
|> option.map(json.string)
33+
|> option.unwrap(json.null()),
34+
),
35+
#(
36+
"address_line_4",
37+
dto.address_line_4
38+
|> option.map(json.string)
39+
|> option.unwrap(json.null()),
40+
),
41+
])
42+
}
43+
1944
/// This always succeeds because there is no validation.
2045
/// Used when importing an OrderForm from the outside world into the domain.
2146
pub fn to_unvalidated_address(
@@ -43,17 +68,17 @@ pub fn to_address(dto: AddressDto) -> Result(compound_types.Address, String) {
4368
use address_line_2 <- try(
4469
dto.address_line_2
4570
|> option.map(fn(addr) { string50.create_option(addr, "address_line_2") })
46-
|> option.unwrap(Ok(None)),
71+
|> option.unwrap(Ok(option.None)),
4772
)
4873
use address_line_3 <- try(
4974
dto.address_line_3
5075
|> option.map(fn(addr) { string50.create_option(addr, "address_line_3") })
51-
|> option.unwrap(Ok(None)),
76+
|> option.unwrap(Ok(option.None)),
5277
)
5378
use address_line_4 <- try(
5479
dto.address_line_4
5580
|> option.map(fn(addr) { string50.create_option(addr, "address_line_4") })
56-
|> option.unwrap(Ok(None)),
81+
|> option.unwrap(Ok(option.None)),
5782
)
5883
use city <- try(dto.city |> string50.create("city"))
5984
use zip_code <- try(dto.zip_code |> zip_code.create("zip_code"))

0 commit comments

Comments
 (0)