/ src / lightspeed / event.gleam
event.gleam
 1  //// Typed event decoders for browser-originated event payloads.
 2  
 3  import lightspeed/form
 4  
 5  /// Browser-originated inbound event frame payload.
 6  pub type InboundEvent {
 7    InboundEvent(name: String, payload: String)
 8  }
 9  
10  /// Typed event decoder errors.
11  pub type DecodeError {
12    UnexpectedEvent(expected: String, actual: String)
13    InvalidForm(form.FormError)
14  }
15  
16  /// Build an inbound event.
17  pub fn inbound(name: String, payload: String) -> InboundEvent {
18    InboundEvent(name: name, payload: payload)
19  }
20  
21  /// Event name.
22  pub fn name(event: InboundEvent) -> String {
23    event.name
24  }
25  
26  /// Raw payload string.
27  pub fn payload(event: InboundEvent) -> String {
28    event.payload
29  }
30  
31  /// Decode an event with no payload requirement.
32  pub fn decode_unit(
33    event: InboundEvent,
34    expected_name: String,
35    message: msg,
36  ) -> Result(msg, DecodeError) {
37    case event.name == expected_name {
38      True -> Ok(message)
39      False -> Error(UnexpectedEvent(expected: expected_name, actual: event.name))
40    }
41  }
42  
43  /// Decode an event payload through form bindings.
44  pub fn decode_form(
45    event: InboundEvent,
46    expected_name: String,
47    with: fn(form.FormData) -> Result(msg, form.FormError),
48  ) -> Result(msg, DecodeError) {
49    case event.name == expected_name {
50      False -> Error(UnexpectedEvent(expected: expected_name, actual: event.name))
51      True ->
52        event.payload
53        |> form.parse_payload
54        |> with
55        |> map_form_error
56    }
57  }
58  
59  /// Convert decoder errors to stable log strings.
60  pub fn error_to_string(error: DecodeError) -> String {
61    case error {
62      UnexpectedEvent(expected, actual) ->
63        "unexpected_event:" <> expected <> ":" <> actual
64      InvalidForm(form_error) ->
65        "invalid_form:" <> form.error_to_string(form_error)
66    }
67  }
68  
69  fn map_form_error(
70    result: Result(msg, form.FormError),
71  ) -> Result(msg, DecodeError) {
72    case result {
73      Ok(message) -> Ok(message)
74      Error(error) -> Error(InvalidForm(error))
75    }
76  }