Skip to content

Commit 5e8542c

Browse files
committed
fix: working server
1 parent 7b4bb38 commit 5e8542c

File tree

6 files changed

+124
-65
lines changed

6 files changed

+124
-65
lines changed

gleam.toml

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "fddd_library"
22
version = "0.1.0"
3-
gleam = ">= 0.32.0"
3+
gleam = ">= 1.0.0"
44

55
# Fill out these fields if you intend to generate HTML documentation or publish
66
# your project to the Hex package manager.
@@ -13,7 +13,10 @@ gleam = ">= 0.32.0"
1313
[dependencies]
1414
gleam_stdlib = "~> 0.38"
1515
gleam_http = ">= 3.6.0 and < 4.0.0"
16-
gleam_json = ">= 2.0.0 and < 3.0.0"
16+
gleam_json = "1.0.1"
17+
mist = ">= 1.2.0 and < 2.0.0"
18+
gleam_erlang = ">= 0.25.0 and < 1.0.0"
19+
logging = ">= 1.1.0 and < 2.0.0"
1720

1821
[dev-dependencies]
1922
gleeunit = "~> 1.0.2"

manifest.toml

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

44
packages = [
5+
{ name = "birl", version = "1.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "B1FA529E7BE3FF12CADF32814AB8EC7294E74CEDEE8CC734505707B929A98985" },
6+
{ name = "gleam_crypto", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "ADD058DEDE8F0341F1ADE3AAC492A224F15700829D9A3A3F9ADF370F875C51B7" },
7+
{ name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" },
58
{ 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" },
9+
{ name = "gleam_json", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "9063D14D25406326C0255BDA0021541E797D8A7A12573D849462CAFED459F6EB" },
10+
{ name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" },
711
{ name = "gleam_stdlib", version = "0.38.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "663CF11861179AF415A625307447775C09404E752FF99A24E2057C835319F1BE" },
812
{ name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" },
13+
{ name = "glisten", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "glisten", source = "hex", outer_checksum = "CF3A9383E9BA4A8CBAF2F7B799716290D02F2AC34E7A77556B49376B662B9314" },
14+
{ name = "gramps", version = "2.0.3", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "3CCAA6E081225180D95C79679D383BBF51C8D1FDC1B84DA1DA444F628C373793" },
15+
{ name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
16+
{ name = "logging", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "A996064F04EF6E67F0668FD0ACFB309830B05D0EE3A0C11BBBD2D4464334F792" },
17+
{ name = "mist", version = "1.2.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "109B4D64E68C104CC23BB3CC5441ECD479DD7444889DA01113B75C6AF0F0E17B" },
18+
{ name = "ranger", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "1566C272B1D141B3BBA38B25CB761EF56E312E79EC0E2DFD4D3C19FB0CC1F98C" },
19+
{ name = "thoas", version = "1.2.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "E38697EDFFD6E91BD12CEA41B155115282630075C2A727E7A6B2947F5408B86A" },
920
]
1021

1122
[requirements]
23+
gleam_erlang = { version = ">= 0.25.0 and < 1.0.0" }
1224
gleam_http = { version = ">= 3.6.0 and < 4.0.0" }
13-
gleam_json = { version = ">= 2.0.0 and < 3.0.0"}
25+
gleam_json = { version = "1.0.1" }
1426
gleam_stdlib = { version = "~> 0.38" }
1527
gleeunit = { version = "~> 1.0.2" }
28+
logging = { version = ">= 1.1.0 and < 2.0.0" }
29+
mist = { version = ">= 1.2.0 and < 2.0.0" }

src/fddd_library.gleam

+45-39
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,49 @@
1-
import gleam/io
1+
import gleam/bytes_builder
2+
import gleam/dict
3+
import gleam/erlang/atom
4+
import gleam/erlang/process
5+
import gleam/http/request
6+
import gleam/http/response
7+
import logging
8+
import mist
9+
import order_taking/place_order/api.{place_order_api}
10+
11+
@external(erlang, "logger", "update_primary_config")
12+
fn logger_update_primary_config(
13+
config: dict.Dict(atom.Atom, atom.Atom),
14+
) -> Result(Nil, any)
215

3-
pub type OrderEvents {
4-
OrderPlaced
5-
}
6-
7-
pub type UnvalidatedOrder {
8-
UnvalidatedOrder(id: String)
9-
}
10-
11-
pub type ValidatedOrder {
12-
ValidatedOrder(id: String)
13-
}
14-
15-
pub type PlacedOrder {
16-
PlacedOrder(id: String)
17-
}
18-
19-
pub type Validate =
20-
fn(UnvalidatedOrder) -> ValidatedOrder
21-
22-
pub type SendOrder =
23-
fn(ValidatedOrder) -> PlacedOrder
24-
25-
pub type ExtractEvents =
26-
fn(PlacedOrder) -> List(OrderEvents)
27-
28-
pub fn create_place_order(
29-
validate: Validate,
30-
send_order: SendOrder,
31-
extract_events: ExtractEvents,
32-
) -> fn(UnvalidatedOrder) -> List(OrderEvents) {
33-
fn(order) {
34-
order
35-
|> validate
36-
|> send_order
37-
|> extract_events
38-
}
16+
pub fn main() {
17+
logging.configure()
18+
let _ =
19+
logger_update_primary_config(
20+
dict.from_list([
21+
#(atom.create_from_string("level"), atom.create_from_string("debug")),
22+
]),
23+
)
24+
25+
let not_found =
26+
response.new(404)
27+
|> response.set_body(mist.Bytes(bytes_builder.new()))
28+
29+
let assert Ok(_) =
30+
fn(req: request.Request(mist.Connection)) -> response.Response(
31+
mist.ResponseData,
32+
) {
33+
case request.path_segments(req) {
34+
["order"] -> submit_order(req)
35+
_ -> not_found
36+
}
37+
}
38+
|> mist.new
39+
|> mist.port(8000)
40+
|> mist.start_http
41+
42+
process.sleep_forever()
3943
}
4044

41-
pub fn main() {
42-
io.println("Hello from fddd_library! ")
45+
fn submit_order(
46+
request: request.Request(mist.Connection),
47+
) -> response.Response(mist.ResponseData) {
48+
place_order_api(request)
4349
}

src/order_taking/place_order/api.gleam

+54-18
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@
66
// 3) The output is turned into a DTO which is turned into a HttpResponse
77
// ======================================================
88

9+
import gleam/bit_array
10+
import gleam/bytes_builder
11+
import gleam/dynamic
912
import gleam/http/request
1013
import gleam/http/response
14+
import gleam/io
1115
import gleam/json
1216
import gleam/list
1317
import gleam/result
18+
import gleam/string
19+
import mist
1420
import order_taking/common/simple_types/price
1521
import order_taking/place_order/dto/order_form_dto
1622
import order_taking/place_order/dto/place_order_error_dto
@@ -62,7 +68,9 @@ pub fn send_order_acknowledgment(_order_acknowledgement) {
6268
// // -------------------------------
6369

6470
/// This function converts the workflow output into a HttpResponse
65-
pub fn workflow_result_to_http_reponse(result) -> response.Response(String) {
71+
pub fn workflow_result_to_http_reponse(
72+
result,
73+
) -> response.Response(mist.ResponseData) {
6674
case result {
6775
Ok(events) -> {
6876
// turn domain events into dtos
@@ -81,30 +89,40 @@ pub fn workflow_result_to_http_reponse(result) -> response.Response(String) {
8189
|> json.to_string
8290
}
8391

84-
let response =
85-
response.Response(body: json, status: 200, headers: [
86-
#("Content-Type", "application/json"),
87-
])
88-
response
92+
// let response =
93+
// response.Response(body: json, status: 200, headers: [
94+
// #("Content-Type", "application/json"),
95+
// ])
96+
// response
97+
response.new(200)
98+
|> response.prepend_header("content-type", "application/json")
99+
|> response.set_body(mist.Bytes(bytes_builder.from_string(json)))
89100
}
90101
Error(err) -> {
91102
// turn domain errors into a dto
92103
let dto = place_order_error_dto.from_domain(err)
93104
// and serialize to JSON
94105
let json = dto |> place_order_error_dto.to_json |> json.to_string
95-
let response = response.Response(status: 401, body: json, headers: [])
96-
response
106+
response.new(401)
107+
|> response.prepend_header("content-type", "application/json")
108+
|> response.set_body(mist.Bytes(bytes_builder.from_string(json)))
97109
}
98110
}
99111
}
100112

101113
pub fn place_order_api(
102-
request: request.Request(String),
103-
) -> response.Response(String) {
114+
request: request.Request(mist.Connection),
115+
) -> response.Response(mist.ResponseData) {
104116
// following the approach in "A Complete Serialization Pipeline" in chapter 11
105117

106118
// start with a string
107-
let order_form_json = request.body
119+
let order_form_json =
120+
mist.read_body(request, 300_000)
121+
|> result.map(fn(req) { req.body })
122+
|> result.map(bit_array.to_string)
123+
|> result.unwrap(Ok(""))
124+
|> result.unwrap("")
125+
108126
let order_form =
109127
json.decode(from: order_form_json, using: order_form_dto.decoder())
110128

@@ -135,14 +153,32 @@ pub fn place_order_api(
135153
result
136154
|> workflow_result_to_http_reponse
137155
}
138-
Error(_json_error) -> {
139-
let response =
140-
response.Response(
141-
status: 403,
142-
body: "JSON deserialisation error",
143-
headers: [],
156+
Error(json_error) -> {
157+
io.debug(json_error)
158+
let message = case json_error {
159+
json.UnexpectedFormat(decode_errors) -> {
160+
decode_errors
161+
|> list.map(fn(err) {
162+
let dynamic.DecodeError(_, _, err_path) = err
163+
string.join(err_path, ".")
164+
})
165+
|> string.join(", ")
166+
}
167+
_ -> "Json deser error"
168+
}
169+
170+
// response.new(401)
171+
// |> response.set_body(mist.Bytes(bytes_builder.from_string(message)))
172+
let json =
173+
place_order_error_dto.PlaceOrderErrorDto(
174+
code: "DeserialisationError",
175+
message: message,
144176
)
145-
response
177+
|> place_order_error_dto.to_json
178+
|> json.to_string
179+
response.new(401)
180+
|> response.prepend_header("content-type", "application/json")
181+
|> response.set_body(mist.Bytes(bytes_builder.from_string(json)))
146182
}
147183
}
148184
}

src/order_taking/place_order/dto/address_dto.gleam

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ pub fn decoder() {
2424
dynamic.decode6(
2525
AddressDto,
2626
dynamic.field("address_line_1", of: dynamic.string),
27-
dynamic.field("address_line_2", of: dynamic.optional(dynamic.string)),
28-
dynamic.field("address_line_3", of: dynamic.optional(dynamic.string)),
29-
dynamic.field("address_line_4", of: dynamic.optional(dynamic.string)),
27+
dynamic.optional_field("address_line_2", of: dynamic.string),
28+
dynamic.optional_field("address_line_3", of: dynamic.string),
29+
dynamic.optional_field("address_line_4", of: dynamic.string),
3030
dynamic.field("city", of: dynamic.string),
3131
dynamic.field("zip_code", of: dynamic.string),
3232
)

src/order_taking/place_order/dto/customer_info_dto.gleam

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub type CustomerInfoDto {
1515
}
1616

1717
/// For deserialising
18-
pub fn decoder(json_string: String) {
18+
pub fn decoder() {
1919
let decoder =
2020
dynamic.decode3(
2121
CustomerInfoDto,

0 commit comments

Comments
 (0)