Valid
A validation library for Gleam.
API Docs: https://hexdocs.pm/valid.
This library follows the principle Parse don’t validate.
API
import valid
fn user_validator(input: InputUser) {
use age <- valid.check(input.age, valid.int_min(13, "Should be at least 13"))
use name <- valid.check(input.name, valid.string_is_not_empty("Missing name"))
use email <- valid.check(input.email, valid.string_is_email("Missing email"))
valid.ok(ValidUser(age:, name:, email:))
}
let input = InputUser(age: 14, name: "Sam", email: "sam@sample.com")
let result = input
|> valid.validate(user_validator)
result ==
Ok(ValidUser(14, "Sam", "sam@sample.com"))
Creating a custom validator
A validator is a function that takes an input, and returns a tuple #(output, errors)
.
E.g.
import valid
fn is_99(input) {
case input == 99 {
True -> #(input, [])
False -> #(0, ["Not 99"])
}
}
fn validator(input) {
use out <- valid.check(input, is_99)
valid.ok(out)
}
A validator must return a default value. This is so we can collect all the errors for all validators (instead of returning early).
Composing validators
You can use then
two chain two validators:
fn (input_name: Option(String)) {
use name <- valid.check(
input_name,
valid.is_some("", valid.ok, "Input")
|> valid.then(valid.string_min_length(2, "Size")),
)
valid.ok(name)
}
Using own errors
By using your own errors you can add information to link to the source of the issue. e.g.
type Field {
FieldAge
FieldName
FieldEmail
}
fn user_validator(input: InputUser) {
use age <- valid.check(input.age, valid.int_min(13, #(FieldAge, "Should be at least 13")))
use name <- valid.check(input.name, valid.string_is_not_empty(#(FieldName, "Missing name")))
use email <- valid.check(input.email, valid.string_is_email(#(FieldEmail, "Missing email")))
valid.ok(ValidUser(age:, name:, email:))
}