# `AshLua.Encoder`
[🔗](https://github.com/ash-project/ash_lua/blob/v0.1.0/lib/ash_lua/encoder.ex#L5)

Conversions between Elixir/Ash values and the plain shapes that `:luerl` (via the `:lua` package)
can encode as Lua tables.

Lua doesn't have atoms or sigils — atoms are rendered as strings, `Decimal`/`Date`/`DateTime`/
`NaiveDateTime`/`Time` as their canonical string forms, and structs as plain attribute maps
(no relationships, no calculations, no aggregates unless they happen to be already loaded as a
field value).

# `decode_input`

```elixir
@spec decode_input(term()) :: term()
```

Decodes a Lua-side input value into the shape Ash actions expect for `params`/arguments.

Luerl decodes Lua tables as a list of two-tuples — keyed by integers for sequences and by
strings for maps. We normalize:

  * integer-keyed (sequence) tables → plain lists, sorted by index
  * string-keyed tables → maps with string keys (Ash accepts string-keyed params)
  * empty tables → empty maps (Ash actions are always invoked with a map of params)

Recurses into values.

# `encode_error`

```elixir
@spec encode_error(term()) :: map()
```

Encodes an Ash error tree into a Lua-friendly table.

Walks `Ash.Error.Invalid`/`Ash.Error.Forbidden` classes to their leaves, then dispatches each
leaf through the `AshLua.Error` protocol. Leaves without a protocol impl render as an opaque
"unknown error" entry with a uuid that's logged via `Logger.warning/1` so operators can
correlate the surfaced uuid with full stacktrace details.

The envelope carries a `class` tag (`"invalid" | "forbidden" | "framework" | "unknown"`)
and the full per-error list in `errors`. Consumers that want a one-line summary should pick
the appropriate entry from `errors` themselves rather than read a top-level message — joining
or first-pick'ing here would silently mislead in the multi-error case.

# `encode_result`

```elixir
@spec encode_result(term()) :: term()
```

Encodes an Ash action result to a Lua-friendly value (plain Elixir maps/lists/primitives
that `Lua.encode!/2` knows how to convert).

# `encode_with_template`

```elixir
@spec encode_with_template(term(), term()) :: term()
```

Encodes a result against a template produced by `AshLua.Fields.for_action/4`.

Walks the template recursively, pulling only the requested fields from records,
typed maps, tuples, and union values. `:passthrough` template nodes fall back to
the unconstrained `encode_result/1` path.

---

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