# `AshPhoenixGenApi.TypeMapper`
[🔗](https://github.com/ohhi-vn/ash_phoenix_gen_api/blob/v1.0.3/lib/ash_phoenix_gen_api/type_mapper.ex#L1)

Maps Ash types to PhoenixGenApi argument types.
PhoenixGenApi supports the following argument types:

- `:string` - String values
- `:uuid` - UUID values (auto-validated and converted)
- `{:string, max_bytes}` - String with custom max byte size
- `:num` - Numeric values (integers, floats)
- `:boolean` - Boolean values
- `:datetime` - ISO 8601 datetime string, auto-converted to DateTime
- `:naive_datetime` - ISO 8601 datetime string, auto-converted to NaiveDateTime
- `:map` - Generic map
- `{:map, max_items}` - Map with max items constraint
- `:list` - Generic list
- `{:list, max_items}` - List with max items constraint
- `{:list_string, max_items, max_item_length}` - Lists of strings with constraints
- `{:list_num, max_items}` - Lists of numbers with constraints

alias Ash.Resource.Info, as: ResourceInfo

| Ash Type | PhoenixGenApi Type |
|----------|-------------------|
| `:string` / `Ash.Type.String` | `:string` or `{:string, max_bytes}` |
| `:integer` / `Ash.Type.Integer` | `:num` |
| `:float` / `Ash.Type.Float` | `:num` |
| `:decimal` / `Ash.Type.Decimal` | `:num` |
| `:boolean` / `Ash.Type.Boolean` | `:boolean` |
| `:uuid` / `Ash.Type.UUID` | `:uuid` |
| `:uuid_v7` / `Ash.Type.UUIDv7` | `:uuid` |
| `:date` / `Ash.Type.Date` | `:string` |
| `:time` / `Ash.Type.Time` | `:string` |
| `:datetime` / `Ash.Type.DateTime` | `:datetime` |
| `:utc_datetime` / `Ash.Type.UtcDateTime` | `:datetime` |
| `:utc_datetime_usec` / `Ash.Type.UtcDateTimeUsec` | `:datetime` |
| `:naive_datetime` / `Ash.Type.NaiveDateTime` | `:naive_datetime` |
| `:naive_datetime_usec` / `Ash.Type.NaiveDateTimeUsec` | `:naive_datetime` |
| `:atom` / `Ash.Type.Atom` | `:string` |
| `:map` / `Ash.Type.Map` | `:map` or `{:map, max_items}` |
| `:json` / `Ash.Type.Json` | `:map` |
| `:struct` / `Ash.Type.Struct` | `:map` |
| `:keyword` / `Ash.Type.Keyword` | `:map` |
| `:binary` / `Ash.Type.Binary` | `:string` |
| `:term` / `Ash.Type.Term` | `:string` |
| `:tuple` / `Ash.Type.Tuple` | `:string` |
| `{:array, :string}` | `{:list_string, 1000, 50}` |
| `{:array, :integer}` | `{:list_num, 1000}` |
| `{:array, :uuid}` | `{:list_string, 1000, 50}` |
| `{:array, :map}` | `{:list, 1000}` |
| `:ci_string` / `Ash.Type.CiString` | `:string` |
| `:duration` / `Ash.Type.Duration` | `:string` |
| `:duration_name` / `Ash.Type.DurationName` | `:string` |

# `argument_to_gen_api_type`

```elixir
@spec argument_to_gen_api_type(%{type: term(), constraints: keyword()}) ::
  :string
  | {:string, pos_integer()}
  | :num
  | :boolean
  | :datetime
  | :naive_datetime
  | :map
  | {:map, pos_integer()}
  | :list
  | {:list, pos_integer()}
  | {:list_string, pos_integer(), pos_integer()}
  | {:list_num, pos_integer()}
```

Maps an Ash action argument to a PhoenixGenApi argument type.

Takes an Ash action argument and returns the appropriate PhoenixGenApi type,
considering the argument's type and constraints.

## Parameters

  - `argument` - An Ash action argument struct

## Returns

A PhoenixGenApi compatible type atom or tuple.

# `attribute_to_gen_api_type`

```elixir
@spec attribute_to_gen_api_type(%{type: term(), constraints: keyword()}) ::
  :string
  | {:string, pos_integer()}
  | :num
  | :boolean
  | :datetime
  | :naive_datetime
  | :map
  | {:map, pos_integer()}
  | :list
  | {:list, pos_integer()}
  | {:list_string, pos_integer(), pos_integer()}
  | {:list_num, pos_integer()}
```

Maps an Ash attribute to a PhoenixGenApi argument type.

Takes an Ash resource attribute and returns the appropriate PhoenixGenApi type,
considering the attribute's type and constraints.

## Parameters

  - `attribute` - An Ash resource attribute struct

## Returns

A PhoenixGenApi compatible type atom or tuple.

## Examples

    iex> attr = %{__struct__: Ash.Resource.Attribute, name: :user_id, type: Ash.Type.UUID, constraints: []}
    iex> AshPhoenixGenApi.TypeMapper.attribute_to_gen_api_type(attr)
    :string

    iex> attr = %{__struct__: Ash.Resource.Attribute, name: :count, type: Ash.Type.Integer, constraints: []}
    iex> AshPhoenixGenApi.TypeMapper.attribute_to_gen_api_type(attr)
    :num

    iex> attr = %{__struct__: Ash.Resource.Attribute, name: :created_at, type: Ash.Type.DateTime, constraints: []}
    iex> AshPhoenixGenApi.TypeMapper.attribute_to_gen_api_type(attr)
    :datetime

    iex> attr = %{__struct__: Ash.Resource.Attribute, name: :metadata, type: Ash.Type.Map, constraints: []}
    iex> AshPhoenixGenApi.TypeMapper.attribute_to_gen_api_type(attr)
    :map

# `build_arg_config`

```elixir
@spec build_arg_config([
  {atom(), atom() | tuple(), boolean()}
  | {atom(), atom() | tuple(), boolean(), any()}
]) :: {map(), [String.t()]}
```

Builds arg_types map and arg_orders list from action fields.

## Parameters

  - `fields` - List of `{name, gen_api_type, allow_nil?}` tuples from `get_action_fields/2`

## Returns

A `{arg_types, arg_orders}` tuple where:
- `arg_types` is a map of `field_name_string => gen_api_type`
- `arg_orders` is a list of field name strings in order

# `build_type_config`

```elixir
@spec build_type_config(atom() | tuple(), boolean(), any()) ::
  atom() | tuple() | keyword()
```

Builds the type configuration for a field.

Returns either:
- A simple type atom (backward compatible) when `allow_nil?` is false
- A keyword list with `:type` and `:allow_nil?` options (extended format) when `allow_nil?` is true

## Examples

    iex> AshPhoenixGenApi.TypeMapper.build_type_config(:string, false)
    :string

    iex> AshPhoenixGenApi.TypeMapper.build_type_config(:string, true)
    [type: :string, allow_nil?: true]

    iex> AshPhoenixGenApi.TypeMapper.build_type_config({:string, 255}, true)
    [type: {:string, 255}, allow_nil?: true]

# `default_max_list_items`

```elixir
@spec default_max_list_items() :: pos_integer()
```

Returns the default max list items for list types.

# `default_max_map_items`

```elixir
@spec default_max_map_items() :: pos_integer()
```

Returns the default max map items for map types.

# `default_max_string_item_length`

```elixir
@spec default_max_string_item_length() :: pos_integer()
```

Returns the default max string item length for list_string types.

# `get_action_fields`

```elixir
@spec get_action_fields(module(), atom()) :: [{atom(), atom() | tuple(), boolean()}]
```

Gets the input fields for an Ash action, combining accepted attributes and arguments.

Returns a list of `{name, type, constraints, allow_nil?}` tuples suitable for
building PhoenixGenApi arg_types and arg_orders.

## Parameters

  - `resource` - The Ash resource module
  - `action_name` - The action name atom

## Returns

A list of `{field_name :: atom, gen_api_type, allow_nil? :: boolean}` tuples,
ordered by the action's accept list followed by arguments.

# `get_ash_default_value`

Gets the default value from an Ash attribute or argument.

Returns the default value if set, or `nil` if not set.

# `list_type?`

```elixir
@spec list_type?(atom() | tuple()) :: boolean()
```

Determines if an Ash type maps to a PhoenixGenApi list type.

## Examples

    iex> AshPhoenixGenApi.TypeMapper.list_type?({:array, :string})
    true

    iex> AshPhoenixGenApi.TypeMapper.list_type?(:string)
    false

# `to_gen_api_type`

```elixir
@spec to_gen_api_type(
  atom() | tuple(),
  keyword()
) ::
  :string
  | {:string, pos_integer()}
  | :num
  | :boolean
  | :datetime
  | :naive_datetime
  | :map
  | {:map, pos_integer()}
  | :list
  | {:list, pos_integer()}
  | {:list_string, pos_integer(), pos_integer()}
  | {:list_num, pos_integer()}
```

Maps an Ash type to a PhoenixGenApi argument type.

## Parameters

  - `ash_type` - The Ash type (atom or tuple) to map
  - `constraints` - Optional Ash type constraints (used for list constraints, etc.)

## Returns

A PhoenixGenApi compatible type atom or tuple.

## Examples

    iex> AshPhoenixGenApi.TypeMapper.to_gen_api_type(:string)
    :string

    iex> AshPhoenixGenApi.TypeMapper.to_gen_api_type(:integer)
    :num

    iex> AshPhoenixGenApi.TypeMapper.to_gen_api_type(:uuid)
    :uuid

    iex> AshPhoenixGenApi.TypeMapper.to_gen_api_type(:datetime)
    :datetime

    iex> AshPhoenixGenApi.TypeMapper.to_gen_api_type(:naive_datetime)
    :naive_datetime

    iex> AshPhoenixGenApi.TypeMapper.to_gen_api_type(:map)
    :map

    iex> AshPhoenixGenApi.TypeMapper.to_gen_api_type(:map, max_items: 50)
    {:map, 50}

    iex> AshPhoenixGenApi.TypeMapper.to_gen_api_type({:array, :string})
    {:list_string, 1000, 50}

    iex> AshPhoenixGenApi.TypeMapper.to_gen_api_type({:array, :integer})
    {:list_num, 1000}

    iex> AshPhoenixGenApi.TypeMapper.to_gen_api_type({:array, :map})
    {:list, 1000}

# `wrap_nil_type`

```elixir
@spec wrap_nil_type(atom() | tuple()) :: {nil, atom() | tuple()}
```

Wraps a type with nil support.

In PhoenixGenApi, to indicate that an argument can accept nil values,
wrap the type in a `{:nil, type}` tuple.

## Examples

    iex> AshPhoenixGenApi.TypeMapper.wrap_nil_type(:string)
    {:nil, :string}

    iex> AshPhoenixGenApi.TypeMapper.wrap_nil_type({:string, 255})
    {:nil, {:string, 255}}

    iex> AshPhoenixGenApi.TypeMapper.wrap_nil_type(:num)
    {:nil, :num}

---

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