[ANN] dream-html & pure-html 3.5.2

[ANN] dream-html 3.7.0

Happy to announce the addition of a helper module for typed form decoding functionality. See the docs here: Form (dream-html.Dream_html.Form)

An example:

type user = { name : string; age : int option }

open Dream_html.Form

let user_form =
  let+ name = required string "name"
  and+ age = optional int "age" in
  { name; age }

let dream_form = ["age", "42"; "name", "Bob"]
let user_result = validate user_form dream_form
(* => Ok { name = "Bob"; age = Some 42 } *)

let error_result = validate user_form ["age", "none"]
(* => Error [("age", "error.expected.int"); ("name", "error.required")] *)

Astute readers may observe that this provides some convenience functionality beyond what Dream itself offers; to validate the above form and get a complete set of field validation errors using only Dream you would do something like:

let user_result = match dream_form with
  | ["age", age; "name", name] ->
    (match int_of_string age with
    | age -> Ok { name; age = Some age }
    | exception Failure _ -> Error ["age", "error.expected.int"])
  | ["name", name] -> Ok { name; age = None }
  | ["age", age] ->
    (match int_of_string age with
    | age -> Error ["name", "error.required"]
    | exception Failure _ -> Error ["age", "error.expected.int"; "name", "error.required"])
  | _ -> Error ["name", "error.required"]

And this is a form with only two fields. You can imagine how convoluted the logic would be for more complex forms. Of course, you might just decide to use List.assoc_opt and build up the validation errors, but even that can get tricky. So if you are making heavy use of HTML forms, a helper module that takes care of all these validation details can be very useful. Enjoy!

4 Likes