Current section
Files
Jump to
Current section
Files
gen/docs/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>validator</title>
<link rel="stylesheet" href="./index.css" type="text/css" />
</head>
<body>
<header class="page-header">
<h2>
validator<!-- - -->
</h2>
</header>
<div class="page">
<nav class="sidebar">
<a class="sidebar-toggle" href="#">
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="bars"
class="svg-inline--fa fa-bars fa-w-14"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 448 512"
>
<path
fill="#fff"
d="M16 132h416c8.837 0 16-7.163 16-16V76c0-8.837-7.163-16-16-16H16C7.163 60 0 67.163 0 76v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16zm0 160h416c8.837 0 16-7.163 16-16v-40c0-8.837-7.163-16-16-16H16c-8.837 0-16 7.163-16 16v40c0 8.837 7.163 16 16 16z"
></path>
</svg>
</a>
<h2>Pages</h2>
<ul>
<li><a href="./index.html">README</a></li>
</ul>
<h2>Modules</h2>
<ul>
<li><a href="./validator/">validator</a></li>
<li><a href="./validator/common/">validator/common</a></li>
<li><a href="./validator/int/">validator/int</a></li>
<li><a href="./validator/list/">validator/list</a></li>
<li><a href="./validator/option/">validator/option</a></li>
<li><a href="./validator/string/">validator/string</a></li>
</ul>
</nav>
<div class="content">
<h1>Validator</h1>
<p>A validation library for <a href="https://gleam.run/">Gleam</a>.</p>
<p>This library follows the principle <a href="https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/">Parse don't validate</a>.</p>
<p>You start with an input type and validate into an output type. These two types can be different. For example:</p>
<pre><code class="language-haskell">type UserInput { UserInput(name: Option(String), age: Int) }
type ValidUser { ValidUser(name: String, age: Int) }
</code></pre>
<p>Then you create a validator like:</p>
<pre><code class="language-haskell">import validator
import validator/common.{ValidatorResult}
import validator/int
import validator/option
fn user_validator(user: UserInput) -> ValidatorResult(ValidUser, String) {
validator.build2(ValidUser)
|> validator.validate(user.name, option.is_some("Please provide a name"))
|> validator.validate(user.age, int.min(13, "Must be at least 13 years old"))
}
</code></pre>
<p>And run it:</p>
<pre><code class="language-rust">case user_validator(input) {
Ok(valid_user) -> ...
Error(tuple(first_error, all_errors)) -> ...
}
</code></pre>
<h2>Error type</h2>
<p>Errors can be your own type e.g.</p>
<pre><code class="language-haskell">import validator
import validator/common.{ValidatorResult}
import validator/int
import validator/option
type Error {
ErrorEmptyName,
ErrorTooYoung,
}
fn user_validator(user: UserInput) -> ValidatorResult(ValidUser, String) {
validator.build2(ValidUser)
|> validator.validate(user.name, option.is_some(ErrorEmptyName))
|> validator.validate(user.age, int.min(13, ErrorTooYoung))
}
</code></pre>
<h2>ValidatorResult</h2>
<p><code>ValidatorResult(valid, error)</code> is an alias for <code>Result(valid, tuple(error, List(error)))</code></p>
<p>The <code>Ok</code> branch has the valid output.</p>
<p>The <code>Error</code> branch has a tuple <code>tuple(error, List(error))</code>.
The first value is the first error. The second value is a list with all errors (including the first).</p>
<h2>Custom property validator</h2>
<p>A property validator has two components:</p>
<ul>
<li>The error to return</li>
<li>A function that transforms the property if successful (<code>fn(input) -> Option(output)</code>)</li>
</ul>
<p>Example:</p>
<pre><code class="language-rust">fn bigger_than_10(num: Int) -> Option(num) {
case num > 10 {
True ->
Some(num)
False ->
None
}
}
let custom = validator.custom("Must be bigger than 10", bigger_than_10)
let validator = fn(form: FormInput) {
validator.build1(ValidForm)
|> validator.validate(form.quantity, custom)
}
</code></pre>
<h2>Test</h2>
<pre><code class="language-sh">rebar3 compile
rebar3 eunit
</code></pre>
<h2>Installation</h2>
<p>This package can be installed by adding <code>gleam_validator</code> to your <code>rebar.config</code> dependencies:</p>
<pre><code class="language-erlang">{deps, [
gleam_validator
]}.
</code></pre>
</div>
</div>
<footer class="pride" onclick="document.querySelector('.pride').classList.toggle('show')">
<div class="blue">Lucy</div>
<div class="pink">says</div>
<div class="white">trans</div>
<div class="pink">rights</div>
<div class="blue">✨</div>
<a>✨</a>
</footer>
</body>
</html>