AshTypescript.Rpc.FieldProcessing.FieldSelector (ash_typescript v0.18.1)

Copy Markdown View Source

Unified field selection processor using type-driven recursive dispatch.

This module mirrors the architecture of ValueFormatter, using the same {type, constraints} pattern for type-driven dispatch. Each type is self-describing - no separate classification step is needed.

Design Principle

The key insight is that field selection and value formatting are parallel operations - both traverse composite types recursively based on type information. By using the same dispatch pattern, we achieve consistency and simplicity.

Type Categories

Dispatch is driven by the manifest: select_fields/5 pattern-matches %Ash.Info.Manifest.Type{} and branches on its kind. Every handler takes a trailing ctx argument (a map carrying the manifest module plus entrypoint-level feature flags). Raw Ash types (atoms, {:array, _}) hit fallback clauses that resolve via Ash.Info.Manifest.Generator.TypeResolver and re-dispatch.

CategoryDetection (type_info.kind)Handler
Ash / embedded resource:resource, :embedded_resourceselect_resource_fields/4
Typed struct:struct with instance_of + fieldsselect_typed_struct_fields/4
Typed Map/Keyword:map/:keyword with fieldsselect_typed_map_fields/4
Tuple:tupleselect_tuple_fields/4
Union:unionselect_union_fields/5
Array:arrayRecurse with item_type
Named type reference:type_refResolve via AshTypescript.type_lookup, re-dispatch
PrimitiveDefaultValidate no fields requested

Summary

Functions

Converts an action to its type specification.

Processes requested fields for a given resource and action.

Main recursive dispatch function for field selection.

Selects fields from a tuple type using named fields.

Selects fields from a typed map (Ash.Type.Map/Keyword with field constraints).

Selects fields from a TypedStruct or NewType with typescript_field_names callback.

Types

select_result()

@type select_result() :: {select :: [atom()], load :: [term()], template :: [term()]}

Functions

action_to_type_spec(resource, action)

@spec action_to_type_spec(module(), map()) ::
  {Ash.Info.Manifest.Type.t() | nil, keyword()}

Converts an action to its type specification.

Returns {type, constraints} tuple representing the action's return type. Operates on %Ash.Info.Manifest.Action{} (returns is already a resolved type).

process(resource, action_name, requested_fields, manifest, opts \\ [])

@spec process(module(), atom(), list(), module(), keyword()) ::
  {:ok, select_result()} | {:error, term()}

Processes requested fields for a given resource and action.

Returns {:ok, {select_fields, load_fields, extraction_template}} or {:error, error}.

Parameters

  • resource - The Ash resource module
  • action_name - The action name (atom)
  • requested_fields - List of field selections (atoms, strings, or maps)

Examples

iex> process(MyApp.Todo, :read, [:id, :title, %{user: [:id, :name]}])
{:ok, {[:id, :title], [{:user, [:id, :name]}], [:id, :title, {:user, [:id, :name]}]}}

select_fields(type_info, constraints, requested_fields, path, ctx)

@spec select_fields(
  atom() | tuple() | Ash.Info.Manifest.Type.t(),
  keyword(),
  list(),
  list(),
  module() | map()
) :: select_result()

Main recursive dispatch function for field selection.

Mirrors ValueFormatter.format/5 - uses the same type detection and dispatch pattern. Each type category has its own handler that may recurse back into this function.

select_resource_fields(resource, requested_fields, path, ctx)

Selects fields from an Ash resource.

Handles attributes, calculations, relationships, and aggregates.

select_tuple_fields(type_info, requested_fields, path, ctx)

Selects fields from a tuple type using named fields.

Tuples in Ash have named positions (like :latitude, :longitude) and the template stores both the field_name and its index for result processing. When no fields are requested, all fields are returned.

select_typed_map_fields(type_info, requested_fields, path, ctx, error_type \\ "field_constrained_type")

Selects fields from a typed map (Ash.Type.Map/Keyword with field constraints).

The error_type parameter allows distinguishing between different type categories for better error messages.

select_typed_struct_fields(type_info, requested_fields, path, ctx)

Selects fields from a TypedStruct or NewType with typescript_field_names callback.

select_union_fields(type_info, requested_fields, path, error_type, ctx)

Selects fields from a union type.

Supports:

  • Simple member selection: [:member_name]
  • Member with nested fields: [%{member_name: fields}]
  • Multiple members in a single map: %{member1: fields1, member2: fields2}