Exdantic.Runtime.EnhancedSchema (exdantic v0.0.2)

View Source

Enhanced runtime schema with model validators and computed fields support.

This module extends DynamicSchema with support for:

  • Model validators with both named and anonymous functions
  • Computed fields with both named and anonymous functions
  • Full validation pipeline execution
  • JSON Schema generation with enhanced metadata

Summary

Functions

Adds a computed field to an existing enhanced schema.

Adds a model validator to an existing enhanced schema.

Creates an enhanced runtime schema with model validators and computed fields.

Returns information about the enhanced schema.

Processes computed field specifications and converts anonymous functions to named references.

Processes model validators and converts anonymous functions to named references.

Generates JSON Schema for an enhanced runtime schema.

Validates data against an enhanced runtime schema.

Types

computed_field_spec()

@type computed_field_spec() ::
  {atom(), Exdantic.Types.type_definition(), validator_spec()}

t()

@type t() :: %Exdantic.Runtime.EnhancedSchema{
  base_schema: Exdantic.Runtime.DynamicSchema.t(),
  computed_fields: [computed_field_spec()],
  metadata: map(),
  model_validators: [validator_spec()],
  runtime_functions: %{required(atom()) => function()}
}

validator_spec()

@type validator_spec() :: {module(), atom()} | function()

Functions

add_computed_field(enhanced_schema, field_name, field_type, computation)

@spec add_computed_field(t(), atom(), term(), validator_spec()) :: t()

Adds a computed field to an existing enhanced schema.

Parameters

  • enhanced_schema - An EnhancedSchema struct
  • field_name - Name of the computed field
  • field_type - Type specification for the field
  • computation - Computation function or {module, function} tuple

Returns

  • Updated EnhancedSchema struct

add_model_validator(enhanced_schema, validator)

@spec add_model_validator(t(), validator_spec()) :: t()

Adds a model validator to an existing enhanced schema.

Parameters

  • enhanced_schema - An EnhancedSchema struct
  • validator - Validator function or {module, function} tuple

Returns

  • Updated EnhancedSchema struct

create(field_definitions, opts \\ [])

@spec create(
  [term()],
  keyword()
) :: t()

Creates an enhanced runtime schema with model validators and computed fields.

Parameters

  • field_definitions - List of field definitions
  • opts - Enhanced schema options

Options

  • :model_validators - List of model validator functions or {module, function} tuples
  • :computed_fields - List of computed field specifications
  • :title, :description, :strict - Standard schema options
  • :name - Schema name for references

Examples

iex> fields = [{:name, :string, [required: true]}, {:age, :integer, [optional: true]}]
iex> validators = [fn data -> {:ok, %{data | name: String.trim(data.name)}} end]
iex> computed = [{:display_name, :string, fn data -> {:ok, String.upcase(data.name)} end}]
iex> schema = Exdantic.Runtime.EnhancedSchema.create(fields,
...>   model_validators: validators,
...>   computed_fields: computed
...> )
%Exdantic.Runtime.EnhancedSchema{...}

info(enhanced_schema)

@spec info(t()) :: map()

Returns information about the enhanced schema.

Parameters

  • enhanced_schema - An EnhancedSchema struct

Returns

  • Map with enhanced schema information

process_computed_fields(computed_fields, initial_functions)

@spec process_computed_fields([computed_field_spec()], %{
  required(atom()) => function()
}) ::
  {[computed_field_spec()], %{required(atom()) => function()}}

Processes computed field specifications and converts anonymous functions to named references.

Parameters

  • computed_fields - List of computed field specifications
  • initial_functions - Map of existing runtime functions to extend

Returns

  • Tuple of {processed_fields, updated_functions} where updated_functions contains both initial and any new anonymous functions converted to named references

Examples

iex> fields = [%{name: :full_name, function: fn x -> x.first <> " " <> x.last end}]
iex> {processed, functions} = process_computed_fields(fields, %{})
{[%{name: :full_name, function: {:runtime, :generated_name}}], %{generated_name: #Function<...>}}

process_model_validators(validators)

@spec process_model_validators([validator_spec()]) ::
  {[validator_spec()], %{required(atom()) => function()}}

Processes model validators and converts anonymous functions to named references.

Parameters

  • validators - List of validator specifications (module/function tuples or functions)

Returns

  • Tuple of {processed_validators, runtime_functions} where runtime_functions contains any anonymous functions converted to named references

Examples

iex> validators = [{MyModule, :my_validator}, fn x -> x.valid end]
iex> {processed, functions} = process_model_validators(validators)
{[{MyModule, :my_validator}, {:runtime, :generated_name}], %{generated_name: #Function<...>}}

to_json_schema(enhanced_schema, opts \\ [])

@spec to_json_schema(
  t(),
  keyword()
) :: map()

Generates JSON Schema for an enhanced runtime schema.

Parameters

  • enhanced_schema - An EnhancedSchema struct
  • opts - JSON Schema generation options

Returns

  • JSON Schema map including computed field metadata

Examples

iex> json_schema = Exdantic.Runtime.EnhancedSchema.to_json_schema(schema)
%{
  "type" => "object",
  "properties" => %{
    "name" => %{"type" => "string"},
    "display_name" => %{"type" => "string", "readOnly" => true}
  }
}

validate(data, enhanced_schema, opts \\ [])

@spec validate(map(), t(), keyword()) :: {:ok, map()} | {:error, [Exdantic.Error.t()]}

Validates data against an enhanced runtime schema.

Parameters

  • data - The data to validate (map)
  • enhanced_schema - An EnhancedSchema struct
  • opts - Validation options

Returns

  • {:ok, validated_data} on success (includes computed fields)
  • {:error, errors} on validation failure

Examples

iex> data = %{name: "  John  ", age: 30}
iex> Exdantic.Runtime.EnhancedSchema.validate(data, schema)
{:ok, %{name: "John", age: 30, display_name: "JOHN"}}