Sinter.Validator (Sinter v0.0.1)
View SourceThe unified validation engine for Sinter.
This module provides the single validation pipeline that handles all types
of validation in Sinter. It processes schemas created by Sinter.Schema.define/2
and runs a clean, predictable validation process.
Validation Pipeline
- Input Validation - Ensure input is valid format
- Required Field Check - Verify all required fields are present
- Field Validation - Validate each field against its type and constraints
- Strict Mode Check - Reject unknown fields if strict mode enabled
- Post Validation - Run custom cross-field validation if configured
Design Philosophy
The validator focuses purely on validation - it does NOT perform data transformation. Any data transformation should be explicit in your application code, keeping your validation logic pure and your transformations visible.
Usage
schema = Sinter.Schema.define([
{:name, :string, [required: true, min_length: 2]},
{:age, :integer, [optional: true, gt: 0]}
])
# Basic validation
{:ok, validated} = Sinter.Validator.validate(schema, %{name: "Alice", age: 30})
# With coercion
{:ok, validated} = Sinter.Validator.validate(schema, %{name: "Alice", age: "30"}, coerce: true)
# Batch validation
data_list = [%{name: "Alice", age: 30}, %{name: "Bob", age: 25}]
{:ok, validated_list} = Sinter.Validator.validate_many(schema, data_list)
Summary
Functions
Validates data against a Sinter schema.
Validates data against a schema, raising an exception on failure.
Validates multiple data items against the same schema efficiently.
Validates a stream of data maps against a schema with memory efficiency.
Types
Functions
@spec validate(Sinter.Schema.t(), map(), validation_opts()) :: validation_result()
Validates data against a Sinter schema.
This is the core validation function that all other validation in Sinter ultimately uses. It implements a clean, predictable pipeline.
Parameters
schema
- A schema created bySinter.Schema.define/2
data
- The data to validate (must be a map)opts
- Validation options
Options
:coerce
- Enable type coercion (default: false):strict
- Override schema's strict setting:path
- Base path for error reporting (default: [])
Returns
{:ok, validated_data}
- Validation succeeded{:error, errors}
- List of validation errors
Examples
iex> schema = Sinter.Schema.define([
...> {:name, :string, [required: true]},
...> {:age, :integer, [optional: true, gt: 0]}
...> ])
iex> Sinter.Validator.validate(schema, %{name: "Alice", age: 30})
{:ok, %{name: "Alice", age: 30}}
iex> Sinter.Validator.validate(schema, %{age: 30})
{:error, [%Sinter.Error{path: [:name], code: :required, ...}]}
@spec validate!(Sinter.Schema.t(), map(), validation_opts()) :: map() | no_return()
Validates data against a schema, raising an exception on failure.
Examples
iex> validated = Sinter.Validator.validate!(schema, data)
%{name: "Alice", age: 30}
# Raises Sinter.ValidationError on failure
@spec validate_many(Sinter.Schema.t(), [map()], validation_opts()) :: {:ok, [map()]} | {:error, %{required(integer()) => [Sinter.Error.t()]}}
Validates multiple data items against the same schema efficiently.
Parameters
schema
- Schema to validate againstdata_list
- List of data maps to validateopts
- Validation options
Returns
{:ok, validated_list}
if all validations succeed{:error, errors_by_index}
if any validation fails
Examples
iex> data_list = [
...> %{name: "Alice", age: 30},
...> %{name: "Bob", age: 25}
...> ]
iex> Sinter.Validator.validate_many(schema, data_list)
{:ok, [%{name: "Alice", age: 30}, %{name: "Bob", age: 25}]}
@spec validate_stream(Sinter.Schema.t(), Enumerable.t(), validation_opts()) :: Enumerable.t()
Validates a stream of data maps against a schema with memory efficiency.
This function is designed for processing large datasets without loading everything into memory at once. Perfect for DSPEx teleprompter optimization on large training sets.
Parameters
schema
- A schema created bySinter.Schema.define/2
data_stream
- An Enumerable of data maps to validateopts
- Validation options
Returns
- A stream of
{:ok, validated_data}
or{:error, [Error.t()]}
tuples
Examples
iex> schema = Sinter.Schema.define([{:id, :integer, [required: true]}])
iex> data_stream = Stream.map(1..1000, &%{"id" => &1})
iex> results = Sinter.Validator.validate_stream(schema, data_stream)
iex> Enum.take(results, 3)
[
{:ok, %{id: 1}},
{:ok, %{id: 2}},
{:ok, %{id: 3}}
]
Memory Efficiency
This function processes items one at a time and does not accumulate results, making it suitable for very large datasets that would not fit in memory.