Current section
Files
Jump to
Current section
Files
src/okay.gleam
import gleam/list
import gleam/option
import gleam/string
/// The different types of failure messages, these can be used to later build human readable messages like:
/// `The string "John" expected to be longer then 10 characters but was actually 4`
pub type Failure {
/// Returned when is_gt failed
IsGreaterFailure(value: Int, expected: Int)
/// Returned when is_gte failed
IsGreaterOrEqualFailure(value: Int, expected: Int)
/// Returned when is_longer failed
IsLongerFailure(value: String, actual: Int, expected: Int)
/// Returned when is_lt failed
IsLesserFailure(value: Int, expected: Int)
/// Returned when is_lte failed
IsLesserOrEqualFailure(value: Int, expected: Int)
/// Returned when is_equal failed
IsEqualFailure(value: String, expected: String)
/// Returned when is_included_in failed
IsIncludedInFailure(value: String, expected: String)
/// Returned when is_true/is_false failed
IsBoolFailure(value: Bool, expected: Bool)
/// Returned when is_some failed
IsSomeFailure
/// Returned when is_none failed
IsNoneFailure(value: String)
}
/// The `ValidationError` type consists of the field name and the error
pub type ValidationError {
ValidationError(field: String, failure: Failure)
}
/// The `Okay` type is used to store the list of validation failures
pub type Okay {
Okay(failures: List(ValidationError))
}
/// Checks if the `Okay` record contains any failures and responds with a Result
pub fn run(okay: Okay) -> Result(Nil, Okay) {
case list.is_empty(okay.failures) {
True -> Ok(Nil)
False -> Error(okay)
}
}
/// Initializes a `Okay` record with an empty list of failures
pub fn new() -> Okay {
Okay(failures: [])
}
/// Based on the validation function result, it'll append the Error to the `Okay.failures` list
pub fn field(okay: Okay, field: String, result: Result(Nil, Failure)) -> Okay {
case result {
Error(failure) -> {
let updated_failures =
list.append(okay.failures, [ValidationError(field:, failure:)])
Okay(failures: updated_failures)
}
_ -> okay
}
}
/// Checks if values is included in the list
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_included_in(1, [1, 2])
/// let assert Error(_error) = okay.is_included_in(3, [1, 2])
/// ```
///
pub fn is_included_in(value: t, whitelist: List(t)) -> Result(Nil, Failure) {
case list.contains(whitelist, value) {
True -> Ok(Nil)
False ->
Error(IsIncludedInFailure(
string.inspect(value),
string.inspect(whitelist),
))
}
}
/// Checks if string is longer than X amount
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_longer("hello", 1)
/// let assert Error(_error) = okay.is_longer("A", 2)
/// ```
///
pub fn is_longer(value: String, length: Int) -> Result(Nil, Failure) {
let value_length = string.length(value)
case value_length > length {
True -> Ok(Nil)
False -> Error(IsLongerFailure(value, value_length, length))
}
}
/// Checks if two values are equal to each other
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_equal("hi", "hi")
/// let assert Error(_error) = okay.is_equal(1, 2)
/// ```
///
pub fn is_equal(value: t, compare: t) -> Result(Nil, Failure) {
case value == compare {
True -> Ok(Nil)
False ->
Error(IsEqualFailure(string.inspect(value), string.inspect(compare)))
}
}
/// Checks if one Int is greater than another
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_gt(10, 1)
/// let assert Error(_error) = okay.is_gt(1, 10)
/// ```
///
pub fn is_gt(value: Int, compare: Int) -> Result(Nil, Failure) {
case value > compare {
True -> Ok(Nil)
False -> Error(IsGreaterFailure(value, compare))
}
}
/// Checks if one Int is greater than or equal to another
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_gte(10, 10)
/// let assert Error(_error) = okay.is_gte(9, 10)
/// ```
///
pub fn is_gte(value: Int, compare: Int) -> Result(Nil, Failure) {
case value >= compare {
True -> Ok(Nil)
False -> Error(IsGreaterOrEqualFailure(value, compare))
}
}
/// Checks if one Int is less than another
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_lt(1, 2)
/// let assert Error(_error) = okay.is_lt(5, 1)
/// ```
///
pub fn is_lt(value: Int, compare: Int) -> Result(Nil, Failure) {
case value < compare {
True -> Ok(Nil)
False -> Error(IsLesserFailure(value, compare))
}
}
/// Checks if one Int is less than or equal to another
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_lte(8, 8)
/// let assert Error(_error) = okay.is_lte(9, 8)
/// ```
///
pub fn is_lte(value: Int, compare: Int) -> Result(Nil, Failure) {
case value <= compare {
True -> Ok(Nil)
False -> Error(IsLesserOrEqualFailure(value, compare))
}
}
/// Checks if bool is True
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_true(True)
/// let assert Error(_error) = okay.is_true(False)
/// ```
///
pub fn is_true(value: Bool) -> Result(Nil, Failure) {
case value == True {
True -> Ok(Nil)
False -> Error(IsBoolFailure(value, True))
}
}
/// Checks if bool is False
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_false(False)
/// let assert Error(_error) = okay.is_false(True)
/// ```
///
pub fn is_false(value: Bool) -> Result(Nil, Failure) {
case value == False {
True -> Ok(Nil)
False -> Error(IsBoolFailure(value, False))
}
}
/// Checks if Option is Some
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_some(option.Some(1))
/// let assert Error(_error) = okay.is_some(option.None)
/// ```
///
pub fn is_some(value: option.Option(t)) -> Result(Nil, Failure) {
case value {
option.Some(_) -> Ok(Nil)
option.None -> Error(IsSomeFailure)
}
}
/// Checks if Option is None
/// # Examples
/// ```gleam
/// let assert Ok(_) = okay.is_none(option.None)
/// let assert Error(_error) = okay.is_noe(option.Some(1))
/// ```
///
pub fn is_none(value: option.Option(t)) -> Result(Nil, Failure) {
case value {
option.None -> Ok(Nil)
option.Some(x) -> Error(IsNoneFailure(string.inspect(x)))
}
}