Skip to content

Commit cf09d2c

Browse files
authored
Merge pull request #2 from sisou/master
Modernize: update dependencies and `dynamic/decode` module for decoding
2 parents 41709c2 + 347466f commit cf09d2c

File tree

7 files changed

+106
-91
lines changed

7 files changed

+106
-91
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Further documentation can be found at <https://hexdocs.pm/fiber>.
2929
## Client Example
3030

3131
```gleam
32-
import gleam/dynamic
32+
import gleam/dynamic/decode
3333
import gleam/json
3434
import gleeunit/should
3535
@@ -45,7 +45,7 @@ fn start_client(fiber) {
4545
fn ping() {
4646
request.new(method: "ping")
4747
// We expect "pong" from this, so we can decode the result into a string.
48-
|> request.with_decoder(dynamic.string)
48+
|> request.with_decoder(decode.string)
4949
}
5050
5151
fn file_updated(file_name) {
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
2-
version: 1.2.3
2+
version: 1.2.6
33
title: invalid request error message
44
file: ./test/message_test.gleam
55
test_name: invalid_message_test
66
---
7-
UnexpectedFormat([DecodeError("another type", "Dict", [])])
7+
UnableToDecode([DecodeError("Message", "Dict", [])])

manifest.toml

+15-13
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,24 @@
33

44
packages = [
55
{ name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
6-
{ name = "birdie", version = "1.2.3", build_tools = ["gleam"], requirements = ["argv", "edit_distance", "filepath", "glance", "gleam_community_ansi", "gleam_erlang", "gleam_stdlib", "justin", "rank", "simplifile", "trie_again"], otp_app = "birdie", source = "hex", outer_checksum = "AE1207210E9CC8F4170BCE3FB3C23932F314C352C3FD1BCEA44CF4BF8CF60F93" },
6+
{ name = "birdie", version = "1.2.6", build_tools = ["gleam"], requirements = ["argv", "edit_distance", "filepath", "glance", "gleam_community_ansi", "gleam_erlang", "gleam_stdlib", "justin", "rank", "simplifile", "term_size", "trie_again"], otp_app = "birdie", source = "hex", outer_checksum = "1363F4C7E7433A4A8350CC682BCDDBA5BBC6F66C94EFC63BC43025F796C4F6D0" },
77
{ name = "edit_distance", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "edit_distance", source = "hex", outer_checksum = "A1E485C69A70210223E46E63985FA1008B8B2DDA9848B7897469171B29020C05" },
8-
{ name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" },
9-
{ name = "glance", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "8F3314D27773B7C3B9FB58D8C02C634290422CE531988C0394FA0DF8676B964D" },
10-
{ name = "gleam_community_ansi", version = "1.4.1", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "4CD513FC62523053E62ED7BAC2F36136EC17D6A8942728250A9A00A15E340E4B" },
11-
{ name = "gleam_community_colour", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "A49A5E3AE8B637A5ACBA80ECB9B1AFE89FD3D5351FF6410A42B84F666D40D7D5" },
12-
{ name = "gleam_crypto", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "ADD058DEDE8F0341F1ADE3AAC492A224F15700829D9A3A3F9ADF370F875C51B7" },
13-
{ name = "gleam_erlang", version = "0.26.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "3DF72F95F4716883FA51396FB0C550ED3D55195B541568CAF09745984FD37AD1" },
14-
{ name = "gleam_json", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "CB10B0E7BF44282FB25162F1A24C1A025F6B93E777CCF238C4017E4EEF2CDE97" },
15-
{ name = "gleam_otp", version = "0.12.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "CD5FC777E99673BDB390092DF85E34EAA6B8EE1882147496290AB3F45A4960B1" },
16-
{ name = "gleam_stdlib", version = "0.40.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "86606B75A600BBD05E539EB59FABC6E307EEEA7B1E5865AFB6D980A93BCB2181" },
17-
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
18-
{ name = "glexer", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glexer", source = "hex", outer_checksum = "BD477AD657C2B637FEF75F2405FAEFFA533F277A74EF1A5E17B55B1178C228FB" },
8+
{ name = "filepath", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "67A6D15FB39EEB69DD31F8C145BB5A421790581BD6AA14B33D64D5A55DBD6587" },
9+
{ name = "glance", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "106111453AE9BA959184302B7DADF2E8CF322B27A7CB68EE78F3EE43FEACCE2C" },
10+
{ name = "gleam_community_ansi", version = "1.4.2", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "479DEDC748D08B310C9FEB9C4CBEC46B95C874F7F4F2844304D6D20CA78A8BB5" },
11+
{ name = "gleam_community_colour", version = "1.4.1", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "386CB9B01B33371538672EEA8A6375A0A0ADEF41F17C86DDCB81C92AD00DA610" },
12+
{ name = "gleam_crypto", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "8AE56026B3E05EBB1F076778478A762E9EB62B31AEEB4285755452F397029D22" },
13+
{ name = "gleam_erlang", version = "0.34.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "0C38F2A128BAA0CEF17C3000BD2097EB80634E239CE31A86400C4416A5D0FDCC" },
14+
{ name = "gleam_json", version = "2.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "C55C5C2B318533A8072D221C5E06E5A75711C129E420DD1CE463342106012E5D" },
15+
{ name = "gleam_otp", version = "0.16.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "50DA1539FC8E8FA09924EB36A67A2BBB0AD6B27BCDED5A7EF627057CF69D035E" },
16+
{ name = "gleam_regexp", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "7F5E0C0BBEB3C58E57C9CB05FA9002F970C85AD4A63BA1E55CBCB35C15809179" },
17+
{ name = "gleam_stdlib", version = "0.55.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "32D8F4AE03771516950047813A9E359249BD9FBA5C33463FDB7B953D6F8E896B" },
18+
{ name = "gleeunit", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "0E6C83834BA65EDCAAF4FE4FB94AC697D9262D83E6F58A750D63C9F6C8A9D9FF" },
19+
{ name = "glexer", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glexer", source = "hex", outer_checksum = "F74FB4F78C3C1E158DF15A7226F33A662672F58EEF1DFE6593B7FCDA38B0A0EB" },
1920
{ name = "justin", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "justin", source = "hex", outer_checksum = "7FA0C6DB78640C6DC5FBFD59BF3456009F3F8B485BF6825E97E1EB44E9A1E2CD" },
2021
{ name = "rank", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "rank", source = "hex", outer_checksum = "5660E361F0E49CBB714CC57CC4C89C63415D8986F05B2DA0C719D5642FAD91C9" },
21-
{ name = "simplifile", version = "2.1.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "BDD04F5D31D6D34E2EDFAEF0B68A6297AEC939888C3BFCE61133DE13857F6DA2" },
22+
{ name = "simplifile", version = "2.2.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0DFABEF7DC7A9E2FF4BB27B108034E60C81BEBFCB7AB816B9E7E18ED4503ACD8" },
23+
{ name = "term_size", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "term_size", source = "hex", outer_checksum = "D00BD2BC8FB3EBB7E6AE076F3F1FF2AC9D5ED1805F004D0896C784D06C6645F1" },
2224
{ name = "trie_again", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "trie_again", source = "hex", outer_checksum = "5B19176F52B1BD98831B57FDC97BD1F88C8A403D6D8C63471407E78598E27184" },
2325
{ name = "youid", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_stdlib"], otp_app = "youid", source = "hex", outer_checksum = "EF0F693004E221155EE5909C6D3C945DD14F7117DBA882887CF5F45BE399B8CA" },
2426
]

src/fiber.gleam

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import gleam/dict
22
import gleam/dynamic.{type Dynamic}
3+
import gleam/dynamic/decode
34
import gleam/erlang/process
45
import gleam/list
56
import gleam/option
@@ -64,7 +65,7 @@ pub fn server_only(builder: backend.FiberBuilder) -> backend.FiberBuilder {
6465

6566
pub type RequestError(a) {
6667
ReturnedError(message.ErrorData(Dynamic))
67-
DecodeError(dynamic.DecodeErrors)
68+
DecodeError(List(decode.DecodeError))
6869
CallError(process.CallError(a))
6970
}
7071

@@ -85,7 +86,7 @@ pub fn call(
8586
|> result.map(fn(call_result) {
8687
call_result
8788
|> result.map(fn(data) {
88-
request.decoder(data)
89+
decode.run(data, request.decoder)
8990
|> result.map_error(DecodeError)
9091
})
9192
|> result.map_error(ReturnedError)

src/fiber/backend.gleam

+6
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,12 @@ pub fn handle_text(
254254
message: "Invalid Request",
255255
data: option.None,
256256
)
257+
json.UnableToDecode(_) ->
258+
message.ErrorData(
259+
code: -32_600,
260+
message: "Invalid Request",
261+
data: option.None,
262+
)
257263
json.UnexpectedByte(byte) ->
258264
message.ErrorData(
259265
code: -32_700,

src/fiber/message.gleam

+74-69
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import gleam/dynamic.{type Dynamic}
2+
import gleam/dynamic/decode
23
import gleam/json.{type Json}
34
import gleam/option.{type Option}
45
import gleam/pair
@@ -35,87 +36,91 @@ pub type Message(dyn) {
3536
BatchResponseMessage(List(Response(dyn)))
3637
}
3738

38-
fn id_decoder() {
39-
dynamic.any([
40-
fn(data) { dynamic.int(data) |> result.map(IntId) },
41-
fn(data) { dynamic.string(data) |> result.map(StringId) },
39+
fn id_decoder() -> decode.Decoder(Id) {
40+
decode.one_of(decode.int |> decode.map(IntId), [
41+
decode.string |> decode.map(StringId),
4242
])
43+
|> decode.collapse_errors("Id")
4344
}
4445

45-
fn error_data_decoder() {
46-
dynamic.any([
47-
fn(v) { dynamic.string(v) |> result.map(ErrorString) },
48-
dynamic.decode3(
49-
ErrorData,
50-
dynamic.optional_field("data", dynamic.dynamic),
51-
dynamic.field("code", dynamic.int),
52-
dynamic.field("message", dynamic.string),
53-
),
54-
])
55-
}
56-
57-
fn request_decoder() {
58-
dynamic.any([
59-
dynamic.decode3(
60-
Request,
61-
dynamic.optional_field("params", dynamic.dynamic),
62-
dynamic.field("method", dynamic.string),
63-
dynamic.field("id", id_decoder()),
64-
),
65-
dynamic.decode2(
66-
Notification,
67-
dynamic.optional_field("params", dynamic.dynamic),
68-
dynamic.field("method", dynamic.string),
69-
),
70-
])
71-
}
72-
73-
fn response_decoder() {
74-
dynamic.any([
75-
dynamic.decode2(
76-
SuccessResponse,
77-
dynamic.field("result", dynamic.dynamic),
78-
dynamic.field("id", id_decoder()),
79-
),
80-
dynamic.decode2(
81-
ErrorResponse,
82-
dynamic.field("error", error_data_decoder()),
83-
dynamic.field("id", id_decoder()),
84-
),
46+
fn error_data_decoder() -> decode.Decoder(ErrorData(Dynamic)) {
47+
decode.one_of(decode.string |> decode.map(ErrorString), [
48+
{
49+
use data <- decode.optional_field(
50+
"data",
51+
option.None,
52+
decode.optional(decode.dynamic),
53+
)
54+
use code <- decode.field("code", decode.int)
55+
use message <- decode.field("message", decode.string)
56+
decode.success(ErrorData(data, code, message))
57+
},
8558
])
59+
|> decode.collapse_errors("ErrorData")
8660
}
8761

88-
fn error_decoder() {
89-
dynamic.field("error", error_data_decoder())
90-
}
91-
92-
fn message_decoder() {
93-
dynamic.any([
94-
fn(d) {
95-
response_decoder()(d)
96-
|> result.map(ResponseMessage)
97-
},
98-
fn(d) {
99-
request_decoder()(d)
100-
|> result.map(RequestMessage)
101-
},
102-
fn(d) {
103-
error_decoder()(d)
104-
|> result.map(ErrorMessage)
105-
},
106-
fn(d) {
107-
dynamic.list(request_decoder())(d)
108-
|> result.map(BatchRequestMessage)
62+
fn request_decoder() -> decode.Decoder(Request(Dynamic)) {
63+
decode.one_of(
64+
{
65+
use params <- decode.optional_field(
66+
"params",
67+
option.None,
68+
decode.optional(decode.dynamic),
69+
)
70+
use method <- decode.field("method", decode.string)
71+
use id <- decode.field("id", id_decoder())
72+
decode.success(Request(params, method, id))
10973
},
110-
fn(d) {
111-
dynamic.list(response_decoder())(d)
112-
|> result.map(BatchResponseMessage)
74+
[
75+
{
76+
use params <- decode.optional_field(
77+
"params",
78+
option.None,
79+
decode.optional(decode.dynamic),
80+
)
81+
use method <- decode.field("method", decode.string)
82+
decode.success(Notification(params, method))
83+
},
84+
],
85+
)
86+
|> decode.collapse_errors("Request")
87+
}
88+
89+
fn response_decoder() -> decode.Decoder(Response(Dynamic)) {
90+
decode.one_of(
91+
{
92+
use result <- decode.field("result", decode.dynamic)
93+
use id <- decode.field("id", id_decoder())
94+
decode.success(SuccessResponse(result, id))
11395
},
96+
[
97+
{
98+
use error <- decode.field("error", error_data_decoder())
99+
use id <- decode.field("id", id_decoder())
100+
decode.success(ErrorResponse(error, id))
101+
},
102+
],
103+
)
104+
|> decode.collapse_errors("Response")
105+
}
106+
107+
fn error_decoder() -> decode.Decoder(ErrorData(Dynamic)) {
108+
use error <- decode.field("error", error_data_decoder())
109+
decode.success(error)
110+
}
111+
112+
fn message_decoder() -> decode.Decoder(Message(Dynamic)) {
113+
decode.one_of(response_decoder() |> decode.map(ResponseMessage), [
114+
request_decoder() |> decode.map(RequestMessage),
115+
error_decoder() |> decode.map(ErrorMessage),
116+
decode.list(request_decoder()) |> decode.map(BatchRequestMessage),
117+
decode.list(response_decoder()) |> decode.map(BatchResponseMessage),
114118
])
119+
|> decode.collapse_errors("Message")
115120
}
116121

117122
pub fn decode(text: String) -> Result(Message(Dynamic), json.DecodeError) {
118-
json.decode(text, message_decoder())
123+
json.parse(text, message_decoder())
119124
}
120125

121126
pub fn from_json(text: String) -> Result(Message(Dynamic), json.DecodeError) {

src/fiber/request.gleam

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import gleam/dynamic.{type Dynamic}
2+
import gleam/dynamic/decode
23
import gleam/json.{type Json}
34
import gleam/option.{type Option}
45
import youid/uuid
@@ -9,7 +10,7 @@ pub type Request(return) {
910
Request(
1011
method: String,
1112
params: Option(Json),
12-
decoder: dynamic.Decoder(return),
13+
decoder: decode.Decoder(return),
1314
id: Option(message.Id),
1415
)
1516
}
@@ -18,7 +19,7 @@ pub fn new(method method: String) -> Request(Dynamic) {
1819
Request(
1920
method:,
2021
params: option.None,
21-
decoder: dynamic.dynamic,
22+
decoder: decode.dynamic,
2223
id: option.None,
2324
)
2425
}
@@ -29,7 +30,7 @@ pub fn with_params(request: Request(a), params: Json) -> Request(a) {
2930

3031
pub fn with_decoder(
3132
request: Request(a),
32-
decoder decoder: dynamic.Decoder(b),
33+
decoder decoder: decode.Decoder(b),
3334
) -> Request(b) {
3435
Request(
3536
method: request.method,

0 commit comments

Comments
 (0)