Packages
Multi-surface application runtime for Elixir. One TEA module renders to terminal, browser (LiveView), SSH, and MCP (agents). 30+ widgets, flexbox + CSS grid, AI agent runtime, distributed swarm with CRDTs, time-travel debugging, session recording, sandboxed REPL, and agentic commerce.
Current section
Files
Jump to
Current section
Files
lib/raxol/core/utils/validation.ex
defmodule Raxol.Core.Utils.Validation do
@moduledoc """
Common validation utilities to reduce code duplication across the codebase.
Provides standardized validation functions for dimensions, configs, and common patterns.
"""
@doc """
Validates that a dimension is a positive integer, returning default if invalid.
"""
@spec validate_dimension(integer(), non_neg_integer()) :: non_neg_integer()
def validate_dimension(dimension, _default)
when is_integer(dimension) and dimension > 0 do
dimension
end
def validate_dimension(_, default), do: default
@doc """
Validates that coordinates are valid non-negative integers.
"""
@spec validate_coordinates(integer(), integer()) ::
{:ok, {non_neg_integer(), non_neg_integer()}}
| {:error, :invalid_coordinates}
def validate_coordinates(x, y)
when is_integer(x) and x >= 0 and is_integer(y) and y >= 0 do
{:ok, {x, y}}
end
def validate_coordinates(_, _), do: {:error, :invalid_coordinates}
@doc """
Validates a configuration map against required keys.
"""
@spec validate_config(map(), list(atom())) ::
{:ok, map()} | {:error, {:missing_keys, list(atom())}}
def validate_config(config, required_keys) when is_map(config) do
missing_keys = Enum.reject(required_keys, &Map.has_key?(config, &1))
case missing_keys do
[] -> {:ok, config}
keys -> {:error, {:missing_keys, keys}}
end
end
def validate_config(_, _), do: {:error, :invalid_config}
@doc """
Validates that a value is within specified bounds.
"""
@spec validate_bounds(number(), number(), number()) ::
{:ok, number()} | {:error, :out_of_bounds}
def validate_bounds(value, min, max)
when is_number(value) and value >= min and value <= max do
{:ok, value}
end
def validate_bounds(_, _, _), do: {:error, :out_of_bounds}
@doc """
Validates that a list contains only specific types.
"""
@spec validate_list_types(list(), atom()) ::
{:ok, list()} | {:error, :invalid_types}
def validate_list_types(list, type) when is_list(list) do
valid =
Enum.all?(list, fn item ->
case type do
:atom -> is_atom(item)
:string -> is_binary(item)
:integer -> is_integer(item)
:number -> is_number(item)
:map -> is_map(item)
_ -> false
end
end)
case valid do
true -> {:ok, list}
false -> {:error, :invalid_types}
end
end
def validate_list_types(_, _), do: {:error, :invalid_types}
@doc """
Validates that a string is not empty and optionally matches a pattern.
"""
@spec validate_string(binary(), Regex.t() | nil) ::
{:ok, binary()} | {:error, :invalid_string}
def validate_string(str, pattern \\ nil)
def validate_string(str, nil) when is_binary(str) and byte_size(str) > 0 do
{:ok, str}
end
def validate_string(str, pattern)
when is_binary(str) and byte_size(str) > 0 do
case Regex.match?(pattern, str) do
true -> {:ok, str}
false -> {:error, :invalid_string}
end
end
def validate_string(_, _), do: {:error, :invalid_string}
@doc """
Validates that a value is one of the allowed options.
"""
@spec validate_enum(any(), list()) :: {:ok, any()} | {:error, :invalid_option}
def validate_enum(value, allowed) when is_list(allowed) do
case value in allowed do
true -> {:ok, value}
false -> {:error, :invalid_option}
end
end
def validate_enum(_, _), do: {:error, :invalid_option}
end