AshIntrospection.Rpc.ValueFormatter (AshIntrospection v0.3.0)

View Source

Unified value formatting for RPC input/output.

Traverses composite values recursively, applying field name mappings and type-aware formatting at each level.

The type and constraints parameters provide all context needed - no separate "resource" context is required because each type is self-describing:

  • For Ash resources: field types come from Ash.Resource.Info.attribute/2
  • For TypedStructs: field types come from constraints[:fields]
  • For typed maps: field types come from constraints[:fields]
  • For unions: member type and constraints come from constraints[:types][member]

Configuration

This module uses a config map for language-specific customization:

%{
  input_field_formatter: :camel_case,
  output_field_formatter: :camel_case,
  field_names_callback: :interop_field_names,  # or :typescript_field_names
  get_original_field_name: fn resource, client_key -> ... end,
  format_field_for_client: fn field_name, resource, formatter -> ... end
}

Key Design Principle

The "parent resource" is never needed because each type is self-describing. When we recurse into a nested value, we pass the field's type and constraints, which contain all the information needed to format that value correctly.

Summary

Functions

Formats a value based on its type and constraints.

Types

config()

@type config() :: %{
  optional(:input_field_formatter) => atom(),
  optional(:output_field_formatter) => atom(),
  optional(:field_names_callback) => atom(),
  optional(:get_original_field_name) => (module(), String.t() -> atom() | nil),
  optional(:format_field_for_client) => (atom(), module() | nil, atom() ->
                                           String.t())
}

direction()

@type direction() :: :input | :output

Functions

format(value, type, constraints, direction, config \\ %{})

@spec format(term(), atom() | tuple() | nil, keyword(), direction(), config()) ::
  term()

Formats a value based on its type and constraints.

Parameters

  • value - The value to format
  • type - The Ash type (e.g., MyApp.EmbeddedResource, Ash.Type.Map, {:array, X})
  • constraints - Type constraints (e.g., [fields: [...]], [instance_of: Module])
  • direction - :input (client→internal) or :output (internal→client)
  • config - Configuration map with formatters and callbacks

Returns

The formatted value with field names converted according to direction.