AshPhoenixGenApi.TypeMapper (ash_phoenix_gen_api v1.1.0)

Copy Markdown View Source

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 TypePhoenixGenApi 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
Ash.Type.Enum:string
:enum:string

Notes:

  • {:array, :uuid} maps to {:list_string, 1000, 50} — UUIDs are always 36 characters, so the 50-byte max_item_bytes cap provides a small safety margin.
  • Ash.Type.Enum and :enum map to :string. If PhoenixGenApi adds native enum validation in the future, consider registering a custom mapping via AshPhoenixGenApi.TypeMapper.register/2.
  • Custom Ash types (types that use Ash.Type) that are not in this table will attempt to resolve via type/1 and recursively map. If resolution fails, they default to :string. Use register/2 to provide an explicit mapping.

Summary

Functions

Maps an Ash action argument to a PhoenixGenApi argument type.

Maps an Ash attribute to a PhoenixGenApi argument type.

Builds arg_types map and arg_orders list from action fields.

Builds the type configuration for a field.

Clears all registered custom type mappings.

Returns all registered custom type mappings.

Returns the default max list items for list types.

Returns the default max map items for map types.

Returns the default max string item length for list_string types.

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

Gets the default value from an Ash attribute or argument.

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

Looks up a registered custom type mapping.

Registers a custom type mapping.

Maps an Ash type to a PhoenixGenApi argument type.

Unregisters a custom type mapping.

Wraps a type with nil support.

Functions

argument_to_gen_api_type(map)

@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(map)

@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(fields)

@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

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(type, bool, default_val)

@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]

clear_custom_mappings()

@spec clear_custom_mappings() :: :ok

Clears all registered custom type mappings.

custom_mappings()

@spec custom_mappings() :: %{required(atom() | module()) => atom() | tuple()}

Returns all registered custom type mappings.

Examples

AshPhoenixGenApi.TypeMapper.register(MyType, :string)
mappings = AshPhoenixGenApi.TypeMapper.custom_mappings()
%{MyType => :string} = mappings

default_max_list_items()

@spec default_max_list_items() :: pos_integer()

Returns the default max list items for list types.

default_max_map_items()

@spec default_max_map_items() :: pos_integer()

Returns the default max map items for map types.

default_max_string_item_length()

@spec default_max_string_item_length() :: pos_integer()

Returns the default max string item length for list_string types.

get_action_fields(resource, action_name)

@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(arg1)

Gets the default value from an Ash attribute or argument.

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

list_type?(arg1)

@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

lookup(ash_type)

@spec lookup(atom() | module()) :: {:ok, atom() | tuple()} | :error

Looks up a registered custom type mapping.

Returns {:ok, gen_api_type} if a mapping exists, or :error if not registered.

Examples

iex> AshPhoenixGenApi.TypeMapper.register(MyCustomType, :string)
iex> AshPhoenixGenApi.TypeMapper.lookup(MyCustomType)
{:ok, :string}

iex> AshPhoenixGenApi.TypeMapper.lookup(UnregisteredType)
:error

register(ash_type, gen_api_type)

@spec register(atom() | module(), atom() | tuple()) :: :ok

Registers a custom type mapping.

Allows users to extend or override the default Ash-to-PhoenixGenApi type mappings for custom Ash types (types that use Ash.Type).

Parameters

  • ash_type — The Ash type module (e.g., MyApp.CustomType) or a type identifier
  • gen_api_type — The PhoenixGenApi type to map to (e.g., :string, :num, {:string, 255})

Examples

# In your application startup or config:
AshPhoenixGenApi.TypeMapper.register(MyApp.CustomType, :string)
AshPhoenixGenApi.TypeMapper.register(MyApp.Types.Status, :num)

to_gen_api_type(type, constraints \\ [])

@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}

unregister(ash_type)

@spec unregister(atom() | module()) :: :ok

Unregisters a custom type mapping.

Examples

AshPhoenixGenApi.TypeMapper.unregister(MyApp.CustomType)

wrap_nil_type(type)

@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}