# `GuardedStruct.AshResource.Info`
[🔗](https://github.com/mishka-group/guarded_struct/blob/v0.1.4/lib/guarded_struct/ash_resource/info.ex#L1)

Runtime introspection for the `GuardedStruct.AshResource` extension.

Same shape as `GuardedStruct.Info` but reads from the `__guarded_*`
namespaced functions the Ash extension generates (so it doesn't
collide with Ash's own `Ash.Resource.Info` callbacks).

## Example

    defmodule MyApp.User do
      use Ash.Resource,
        domain: MyApp.MyDomain,
        extensions: [GuardedStruct.AshResource]

      guardedstruct do
        field :nickname, :string, derives: "validate(string, max_len=20)"
      end
    end

    GuardedStruct.AshResource.Info.fields(MyApp.User)
    #=> [:nickname]

    GuardedStruct.AshResource.Info.field(MyApp.User, :nickname)
    #=> %{kind: :field, name: :nickname, derives: "validate(string, max_len=20)", ...}

# `field`

Return metadata for a single field name, or `nil`.

# `field?`

True if a guardedstruct-declared field exists with this name.

# `fields`

Return field, sub_field, and conditional_field names in declaration order.

# `fields_meta`

Return the runtime field metadata stored under `__guarded_fields__/0`.

# `guardedstruct`

```elixir
@spec guardedstruct(dsl_or_extended :: module() | map()) :: [struct()]
```

guardedstruct DSL entities

# `guardedstruct_auto_wire`

```elixir
@spec guardedstruct_auto_wire(dsl_or_extended :: module() | map()) ::
  {:ok, boolean()} | :error
```

Only effective inside the `GuardedStruct.AshResource` extension. When `true`, injects `GuardedStruct.AshResource.Change` into the resource's top-level `changes` section so every `:create` and `:update` action automatically runs the GuardedStruct pipeline. Equivalent to writing `changes do change GuardedStruct.AshResource.Change end` by hand. No-op outside the Ash extension.

# `guardedstruct_auto_wire!`

```elixir
@spec guardedstruct_auto_wire!(dsl_or_extended :: module() | map()) ::
  boolean() | no_return()
```

Only effective inside the `GuardedStruct.AshResource` extension. When `true`, injects `GuardedStruct.AshResource.Change` into the resource's top-level `changes` section so every `:create` and `:update` action automatically runs the GuardedStruct pipeline. Equivalent to writing `changes do change GuardedStruct.AshResource.Change end` by hand. No-op outside the Ash extension.

# `guardedstruct_json`

```elixir
@spec guardedstruct_json(dsl_or_extended :: module() | map()) ::
  {:ok, boolean()} | :error
```

When `true`, derives a JSON encoder. Uses `Jason.Encoder` if `:jason` is in the user's deps; otherwise falls back to the built-in `JSON.Encoder` on Elixir 1.18+. No-op if neither is available.

# `guardedstruct_json!`

```elixir
@spec guardedstruct_json!(dsl_or_extended :: module() | map()) ::
  boolean() | no_return()
```

When `true`, derives a JSON encoder. Uses `Jason.Encoder` if `:jason` is in the user's deps; otherwise falls back to the built-in `JSON.Encoder` on Elixir 1.18+. No-op if neither is available.

# `guardedstruct_main_validator`

```elixir
@spec guardedstruct_main_validator(dsl_or_extended :: module() | map()) ::
  {:ok, {atom(), atom()}} | :error
```

A `{Module, :function}` called with the attributes once every field has passed its validator; it returns `{:ok, attrs}` or `{:error, errors}`. When it is not set, a `main_validator/1` defined in the module is called instead.

# `guardedstruct_main_validator!`

```elixir
@spec guardedstruct_main_validator!(dsl_or_extended :: module() | map()) ::
  {atom(), atom()} | no_return()
```

A `{Module, :function}` called with the attributes once every field has passed its validator; it returns `{:ok, attrs}` or `{:error, errors}`. When it is not set, a `main_validator/1` defined in the module is called instead.

# `guardedstruct_options`

```elixir
@spec guardedstruct_options(dsl_or_extended :: module() | map()) :: %{
  required(atom()) =&gt; any()
}
```

guardedstruct DSL options

Returns a map containing the and any configured or default values.

# `guardedstruct_sanitize_derive`

```elixir
@spec guardedstruct_sanitize_derive(dsl_or_extended :: module() | map()) ::
  {:ok, atom() | [atom()]} | :error
```

A module, or a list of modules, whose `sanitize/2` serves the `sanitize(...)` ops the built-in ones and the derive extensions do not know. They are tried before the `:sanitize_derive` application config, which still serves the ops they do not handle.

# `guardedstruct_sanitize_derive!`

```elixir
@spec guardedstruct_sanitize_derive!(dsl_or_extended :: module() | map()) ::
  (atom() | [atom()]) | no_return()
```

A module, or a list of modules, whose `sanitize/2` serves the `sanitize(...)` ops the built-in ones and the derive extensions do not know. They are tried before the `:sanitize_derive` application config, which still serves the ops they do not handle.

# `guardedstruct_validate_derive`

```elixir
@spec guardedstruct_validate_derive(dsl_or_extended :: module() | map()) ::
  {:ok, atom() | [atom()]} | :error
```

A module, or a list of modules, whose `validate/3` serves the `validate(...)` ops the built-in ones and the derive extensions do not know. They are tried before the `:validate_derive` application config, which still serves the ops they do not handle.

# `guardedstruct_validate_derive!`

```elixir
@spec guardedstruct_validate_derive!(dsl_or_extended :: module() | map()) ::
  (atom() | [atom()]) | no_return()
```

A module, or a list of modules, whose `validate/3` serves the `validate(...)` ops the built-in ones and the derive extensions do not know. They are tried before the `:validate_derive` application config, which still serves the ops they do not handle.

# `information`

Return the full information map (path, keys, enforce_keys, options, etc.).

# `validate`

Run the validation pipeline on `attrs` and return `{:ok, validated_map}`
or `{:error, errors}`. Convenience wrapper over the resource's own
`__guarded_change__/1`.

---

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