# `Exdantic.Runtime.EnhancedSchema`
[🔗](https://github.com/nshkrdotcom/exdantic/blob/v0.1.0/lib/exdantic/runtime/enhanced_schema.ex#L1)

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

# `computed_field_spec`

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

# `t`

```elixir
@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()) =&gt; function()}
}
```

# `validator_spec`

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

# `add_computed_field`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@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`

```elixir
@spec process_computed_fields([computed_field_spec()], %{
  required(atom()) =&gt; function()
}) ::
  {[computed_field_spec()], %{required(atom()) =&gt; 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`

```elixir
@spec process_model_validators([validator_spec()]) ::
  {[validator_spec()], %{required(atom()) =&gt; 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`

```elixir
@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`

```elixir
@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"}}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
