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
-
ArrayReturn errors as an array of error strings
["is required", "must be at least 5 characters"] -
KeyValueReturn 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(@internal Field(a), List(CrossBarError))
Values
pub fn bool(
name name: String,
value value: Bool,
) -> @internal Field(Bool)
Creates a new Bool field with the given name and value
pub fn bool_value(field: @internal Field(Bool)) -> Bool
Convenience functions for extracting the value from a Bool field
pub fn eq(
field field: @internal Field(a),
name name: String,
value value: a,
) -> @internal 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 const equals: fn(@internal Field(a), String, a) -> @internal Field(
a,
)
Alias for eq
pub fn extract_errors(
result: Result(@internal 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,
) -> @internal Field(Float)
Creates a new Float field with the given name and value
pub fn float_value(field: @internal Field(Float)) -> Float
Convenience functions for extracting the value from an Float field
pub fn has_errors(
json_errors: List(#(String, json.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,
) -> @internal Field(Int)
Creates a new Int field with the given name and value
pub fn int_value(field: @internal Field(Int)) -> Int
Convenience functions for extracting the value from an Int field
pub fn max_length(
field field: @internal Field(String),
length length: Int,
) -> @internal 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_valueinstead.
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_valueinstead.
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: @internal Field(Float),
size size: Float,
) -> @internal 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),
Ints andFloats are evaluated directly,Bools 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: @internal Field(String),
length length: Int,
) -> @internal 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_valueinstead.
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_valueinstead.
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: @internal Field(Float),
size size: Float,
) -> @internal 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),
Ints andFloats are evaluated directly,Bools 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: @internal Field(a),
name name: String,
value value: a,
) -> @internal 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 const not_equals: fn(@internal Field(a), String, a) -> @internal Field(
a,
)
Alias for not_eq
pub fn regex(
field field: @internal Field(a),
rule_name name: String,
regex regex: regexp.Regexp,
error_message error: String,
) -> @internal 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: @internal Field(a),
) -> @internal 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: @internal Rule(a)) -> String
Get the default error message for a rule - this is internally used for error states
pub fn rule_to_string(rule: @internal 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.Json)),
) -> String
Utility function to convert a list of serializable tuples into a JSON string.
pub fn string(
name name: String,
value value: String,
) -> @internal Field(String)
Creates a new String field with the given name and value
pub fn string_value(field: @internal Field(String)) -> String
Convenience functions for extracting the value from a String field
pub fn to_float(
field: @internal Field(Int),
) -> @internal 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(
@internal Field(a),
List(CrossBarError),
),
field_name field_name: String,
mode mode: JsonMode,
) -> #(String, json.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.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: @internal Field(a),
) -> Result(@internal 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 fields: List(@internal Field(a)),
keep_failed_only failed_only: Bool,
) -> 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: @internal Field(a),
rule_name name: String,
validator func: fn(a) -> Bool,
error error: String,
) -> @internal 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)