crossbar
Types
The CrossBarError
type is used to represent errors that occur during validation.
pub type CrossBarError {
FailedRule(name: String, rule: String, error: String)
}
Constructors
-
FailedRule(name: String, rule: String, error: String)
pub type JsonMode {
Array
KeyValue
}
Constructors
-
Array
Return errors as an array of error strings
["is required", "must be at least 5 characters"]
-
KeyValue
Return errors as an object with the rule name as the key and the error string as the value
{ "required": "is required", "min_length": "must be at least 5 characters" }
pub type ValidationResult(a) =
Result(Field(a), List(CrossBarError))
Functions
pub fn bool(name name: String, value value: Bool) -> Field(Bool)
Creates a new Bool
field with the given name and value
pub fn eq(
field field: Field(a),
name name: String,
value value: a,
) -> Field(a)
The eq
rule makes sure that the field is equal to the given value, strings are NOT compared securely, so this is NOT safe to use for passwords, all types are compared directly.
pub fn extract_errors(
result: Result(Field(a), List(CrossBarError)),
) -> List(#(String, String))
Useful for extracting the errors as a list of tuples (#(rule_name, error_as_string)), this is useful for returning errors as JSON.
pub fn float(
name name: String,
value value: Float,
) -> Field(Float)
Creates a new Float
field with the given name and value
pub fn has_errors(json_errors: List(#(String, Json))) -> Bool
Useful for checking if the result of to_serializable
collected into a list has any errors, this is useful for checking if any of the fields failed validation.
Example
let first_name =
string("first_name", "John")
|> required
|> min_length(3)
|> to_serializable(KeyValue)
let last_name =
string("last_name", "Smith")
|> required
|> min_length(1)
|> max_length(10)
|> to_serializable(KeyValue)
let errors = [first_name, last_name]
case has_errors(errors) {
True -> io.println("There are errors")
False -> io.println("There are no errors")
}
pub fn int(name name: String, value value: Int) -> Field(Int)
Creates a new Int
field with the given name and value
pub fn max_length(
field field: Field(String),
length length: Int,
) -> Field(String)
The max_length
rule makes sure that the field is at most the given length, this is the expected behaviour in the following cases:
Int
: the length of the string representation of the number, this isn’t very useful to you, but it’s here for completeness sake. You probably want to usemax_value
instead.
Float
: the length of the string representation of the number, this also isn’t very useful to you, but it’s here for completeness sake. You probably want to usemax_value
instead.
String
: the length of the string is evaluated directly
Bool
: this also isn’t very useful to you, but it’s here for completeness sake.
NOTE: This function has been momentarily restricted to String
fields, because it’s not very useful for other types, open an issue if you ever find a use for it.
pub fn max_value(
field field: Field(Float),
size size: Float,
) -> Field(Float)
The max_value
rule makes sure that the field is at most the given (byte) size.
Strings are counted in bytes (as bit arrays),
Int
s andFloat
s are evaluated directly,Bool
s are treated as their binary equivalent (0 or 1).
NOTE: This function has been momentarily restricted to Float
fields, because it’s not very useful for other types, open an issue if you ever find a use for it. There is also a to_float
function to transform int fields to float fields (meant to be used before you add any rules)
pub fn min_length(
field field: Field(String),
length length: Int,
) -> Field(String)
The min_length
rule makes sure that the field is at least the given length, this is the expected behaviour in the following cases:
Int
: the length of the string representation of the number, this isn’t very useful to you, but it’s here for completeness sake. You probably want to usemin_value
instead.
Float
: the length of the string representation of the number, this isn’t very useful to you, but it’s here for completeness sake. You probably want to usemin_value
instead.
String
: the length of the string is evaluated directly
Bool
: this also isn’t very useful to you, but it’s here for completeness sake.
NOTE: This function has been momentarily restricted to String
fields, because it’s not very useful for other types, open an issue if you ever find a use for it.
pub fn min_value(
field field: Field(Float),
size size: Float,
) -> Field(Float)
The min_value
rule makes sure that the field is at least the given (byte where it applies) size.
Strings are counted in bytes (as bit arrays),
Int
s andFloat
s are evaluated directly,Bool
s are treated as their binary equivalent (0 or 1).
NOTE: This function has been momentarily restricted to Float
fields, because it’s not very useful for other types, open an issue if you ever find a use for it. There is also a to_float
function to transform int fields to float fields (meant to be used before you add any rules)
pub fn not_eq(
field field: Field(a),
name name: String,
value value: a,
) -> Field(a)
The not_eq
rule makes sure that the field is not equal to the given value, strings are NOT compared securely, so this is NOT safe to use for passwords, other types are compared directly.
pub fn regex(
field field: Field(a),
rule_name name: String,
regex regex: Regex,
error_message error: String,
) -> Field(a)
The regex
rule makes sure that the field matches the given regex, you are required to compile the regex yourself, if you want to use an uncompiled regex, use the uncompiled_regex
rule instead.
Example
import gleam/regex
let options = Options(case_insensitive: False, multi_line: True)
let assert Ok(re) = compile("^[0-9]", with: options)
string("name", "1john")
|> regex("starts_with_number", re, "must start with a number")
pub fn required(field field: Field(a)) -> Field(a)
The required rule makes sure that the field is not empty, this is the expected behaviour in the following cases:
Int
: 0 is considered empty
Float
: 0.0 is also considered empty
String
: “” (or anything that trims down to that) is considered empty
Bool
: this isn’t really a thing, but it’s here for completeness sake and it will always return true, because a bool is never empty (unless it is wrapped in an option)
pub fn rule_to_error_string(rule: Rule(a)) -> String
Get the default error message for a rule - this is internally used for error states
pub fn rule_to_string(rule: Rule(a)) -> String
Returns the string representation of a rule - this is internally used for error states
pub fn serializables_to_string(
serializables: List(#(String, Json)),
) -> String
Utility function to convert a list of serializable tuples into a JSON string.
pub fn string(
name name: String,
value value: String,
) -> Field(String)
Creates a new String
field with the given name and value
pub fn to_float(field: Field(Int)) -> Field(Float)
Convenient function to convert an Int
to a Float
, you should use this BEFORE applying any rules.
Example
int("age", 6)
|> to_float
|> min_value(5.0)
pub fn to_serializable(
result validation_result: Result(Field(a), List(CrossBarError)),
field_name field_name: String,
mode mode: JsonMode,
) -> #(String, Json)
Transform a field into a tuple that can be used to generate JSON, this is useful for returning errors as JSON. The field_name
argument is optional, if you don’t provide it, the field name will be extracted from the validation result if it can be (which is usually the case).
Example
let first_name =
string("first_name", "")
|> required
|> min_length(3)
|> validate
|> to_serializable("", KeyValue)
let last_name =
string("last_name", "Smith")
|> required
|> min_length(1)
|> max_length(3)
|> validate
|> to_serializable("renamed_last_field", KeyValue)
json.object([first_name, last_name])
|> json.to_string
|> io.println
The above example will produce the following JSON:
{
"first_name": {
"required": "is required",
"min_length": "must be at least 3 characters"
},
"renamed_last_name": {
"max_length": "must not be longer than 3 characters"
}
}
pub fn to_serializable_list(
results: List(#(String, List(CrossBarError))),
mode: JsonMode,
) -> List(#(String, Json))
Validate a list of fields and transform them into a list of tuples that can be used to generate JSON, this is useful for returning errors as JSON.
Example
let first_name =
string("first_name", "")
|> required
|> min_length(3)
let last_name =
string("last_name", "Smith")
|> required
|> min_length(1)
|> max_length(3)
to_serializable_list([first_name, last_name], KeyValue)
|> serializables_to_string
|> io.println
The above example will produce the following JSON:
{
"first_name": {
"required": "is required",
"min_length": "must be at least 3 characters"
},
"last_name": {
"max_length": "must not be longer than 3 characters"
}
}
pub fn validate(
field: Field(a),
) -> Result(Field(a), List(CrossBarError))
Run the validation on the given field, returns an Ok
if the validation was successful, otherwise returns an Error
with a list of errors.
Example
let field = int("age", 6)
|> to_float
|> min_value(5.0)
|> validate
pub fn validate_many(
fields: List(Field(a)),
) -> List(#(String, List(CrossBarError)))
Validate a list of fields, returns a list of tuples with the field name and a list of errors - unfortunately, currently, only supports validating fields of the same type.
pub fn with_validator(
field field: Field(a),
rule_name name: String,
validator func: fn(a) -> Bool,
error error: String,
) -> Field(a)
The with_validator
rule makes sure that the field passes the given validator function, the function should return a Bool
and take the field value as its only argument.
Example
let validator = fn(x) { x > 5 }
let error = "must be greater than 5"
int("age", 6)
|> with_validator("greater_than_5", validator, error)