Sinter.Schema (Sinter v0.0.1)
View SourceUnified schema definition for Sinter.
This module provides the single, canonical way to define data validation schemas
in Sinter. It follows the "One True Way" principle - all schema creation flows
through define/2
, whether at runtime or compile-time.
Basic Usage
# Runtime schema definition
schema = Sinter.Schema.define([
{:name, :string, [required: true, min_length: 2]},
{:age, :integer, [optional: true, gt: 0]}
])
# Compile-time schema definition
defmodule UserSchema do
use Sinter.Schema
use_schema do
field :name, :string, required: true, min_length: 2
field :age, :integer, optional: true, gt: 0
end
end
Field Specifications
Each field is specified as a tuple: {name, type_spec, options}
Supported Options
:required
- Field must be present (default: true):optional
- Field may be omitted (default: false):default
- Default value if field is missing (implies optional: true):description
- Human-readable description:example
- Example value for documentation
Constraints
:min_length
,:max_length
- For strings and arrays:gt
,:gteq
,:lt
,:lteq
- For numbers:format
- Regex pattern for strings:choices
- List of allowed values
Schema Configuration
:title
- Schema title for documentation:description
- Schema description:strict
- Reject unknown fields (default: false):post_validate
- Custom validation function
Summary
Functions
Returns the schema configuration.
Extracts constraint information from schema fields.
Defines a schema from field specifications.
Defines a field in the schema.
Extracts field types from a schema for analysis and introspection.
Returns the field definitions map.
Returns summary information about the schema.
Adds an option to the schema being defined.
Returns a list of optional field names.
Returns the post-validation function if defined.
Returns a list of required field names.
Returns true if the schema is in strict mode.
Compile-time schema definition macro.
Types
@type field_spec() :: {atom(), Sinter.Types.type_spec(), keyword()}
@type metadata() :: %{ created_at: DateTime.t(), field_count: non_neg_integer(), sinter_version: String.t() }
@type t() :: %Sinter.Schema{ config: config(), definition: map(), fields: %{required(atom()) => field_definition()}, metadata: metadata() }
Functions
Returns the schema configuration.
Examples
iex> schema = Sinter.Schema.define([], title: "Test Schema")
iex> config = Sinter.Schema.config(schema)
iex> config.title
"Test Schema"
Extracts constraint information from schema fields.
Returns a map of field names to their constraint lists, useful for teleprompter analysis and optimization.
Parameters
schema
- A Sinter schema
Returns
- A map of field_name => constraints_list
Examples
iex> schema = Sinter.Schema.define([
...> {:name, :string, [required: true, min_length: 2, max_length: 50]},
...> {:score, :integer, [required: true, gt: 0, lteq: 100]}
...> ])
iex> Sinter.Schema.constraints(schema)
%{
name: [min_length: 2, max_length: 50],
score: [gt: 0, lteq: 100]
}
@spec define( [field_spec()], keyword() ) :: t()
Defines a schema from field specifications.
This is the unified entry point for all schema creation in Sinter. Both runtime and compile-time schema definition ultimately use this function.
Parameters
field_specs
- List of field specificationsopts
- Schema configuration options
Options
:title
- Schema title for documentation:description
- Schema description:strict
- Reject unknown fields (default: false):post_validate
- Custom validation function
Examples
iex> schema = Sinter.Schema.define([
...> {:name, :string, [required: true, min_length: 2]},
...> {:age, :integer, [optional: true, gt: 0]}
...> ], title: "User Schema")
iex> schema.config.title
"User Schema"
iex> schema.fields[:name].required
true
Defines a field in the schema.
Used within use_schema
blocks.
Examples
field :name, :string, required: true, min_length: 2
field :age, :integer, optional: true, gt: 0
field :active, :boolean, optional: true, default: true
@spec field_types(t()) :: %{required(atom()) => Sinter.Types.type_spec()}
Extracts field types from a schema for analysis and introspection.
This is useful for DSPEx teleprompters that need to analyze the structure of schemas for optimization purposes.
Parameters
schema
- A Sinter schema
Returns
- A map of field_name => type_spec
Examples
iex> schema = Sinter.Schema.define([
...> {:name, :string, [required: true]},
...> {:tags, {:array, :string}, [optional: true]}
...> ])
iex> Sinter.Schema.field_types(schema)
%{
name: :string,
tags: {:array, :string}
}
@spec fields(t()) :: %{required(atom()) => field_definition()}
Returns the field definitions map.
Examples
iex> schema = Sinter.Schema.define([{:name, :string, [required: true]}])
iex> fields = Sinter.Schema.fields(schema)
iex> fields[:name].required
true
Returns summary information about the schema.
Examples
iex> schema = Sinter.Schema.define([
...> {:name, :string, [required: true]},
...> {:age, :integer, [optional: true]}
...> ], title: "User Schema")
iex> info = Sinter.Schema.info(schema)
iex> info.field_count
2
iex> info.title
"User Schema"
Adds an option to the schema being defined.
Used within use_schema
blocks.
Examples
option :title, "User Schema"
option :strict, true
Returns a list of optional field names.
Examples
iex> schema = Sinter.Schema.define([
...> {:name, :string, [required: true]},
...> {:age, :integer, [optional: true]}
...> ])
iex> Sinter.Schema.optional_fields(schema)
[:age]
Returns the post-validation function if defined.
Examples
iex> post_fn = fn data -> {:ok, data} end
iex> schema = Sinter.Schema.define([], post_validate: post_fn)
iex> Sinter.Schema.post_validate_fn(schema)
#Function<...>
Returns a list of required field names.
Examples
iex> schema = Sinter.Schema.define([
...> {:name, :string, [required: true]},
...> {:age, :integer, [optional: true]}
...> ])
iex> Sinter.Schema.required_fields(schema)
[:name]
Returns true if the schema is in strict mode.
Examples
iex> schema = Sinter.Schema.define([], strict: true)
iex> Sinter.Schema.strict?(schema)
true
Compile-time schema definition macro.
This macro provides a DSL for defining schemas at compile time.
It accumulates field and option definitions and creates a schema
using define/2
.
Example
defmodule UserSchema do
use Sinter.Schema
use_schema do
option :title, "User Schema"
option :strict, true
field :name, :string, required: true, min_length: 2
field :age, :integer, optional: true, gt: 0
field :active, :boolean, optional: true, default: true
end
end
# The module will have a schema/0 function
UserSchema.schema()