AshPhoenixGenApi.Resource.ActionConfig behaviour (ash_phoenix_gen_api v1.0.3)

Copy Markdown View Source

Configuration struct for a single PhoenixGenApi action endpoint.

This struct is the target of the action entity in the gen_api DSL section. It holds all the configuration needed to generate a PhoenixGenApi.Structs.FunConfig from an Ash resource action.

Fields

  • name - The Ash action name (required)
  • request_type - The PhoenixGenApi request type string (defaults to action name)
  • timeout - Timeout in milliseconds
  • response_type - Response mode (:sync, :async, :stream, :none)
  • request_info - Whether to pass request info as last argument
  • check_permission - Permission check mode
  • permission_callback - Custom callback MFA for permission checking (takes precedence over check_permission). Callback receives (request_type, args) and returns true (continue) or false (denied).
  • choose_node_mode - Node selection strategy
  • nodes - Target nodes (list, MFA tuple, or :local)
  • retry - Retry configuration
  • version - API version string
  • mfa - Explicit MFA tuple (overrides auto-generated)
  • arg_types - Explicit argument types map (overrides auto-derived)
  • arg_orders - Explicit argument order list (overrides auto-derived), or :map to derive from arg_types keys (default)
  • disabled - Whether this endpoint is disabled
  • code_interface? - Whether to generate a code interface function for this action
  • result_encoder - How to encode the result returned from the action MFA call

Resolution Order

When generating a FunConfig, values are resolved in this order:

  1. Action-level explicit configuration (e.g., action :foo do timeout 10_000 end)
  2. Section-level defaults (e.g., gen_api do timeout 5_000 end)
  3. Built-in defaults (e.g., timeout defaults to 5000)

For arg_types and arg_orders:

  1. Explicit arg_types/arg_orders on the action entity
  2. Auto-derived from the Ash action's accepted attributes and arguments

Summary

Callbacks

Callback function signature for permission checking.

Functions

Resolves the effective check_permission, falling back to the provided default.

Resolves the effective choose_node_mode, falling back to the provided default.

Resolves the effective code_interface? setting, falling back to the provided default.

Resolves the effective mfa, falling back to auto-generation from the resource module and action name.

Resolves the effective nodes, falling back to the provided default.

Resolves the effective permission_callback, falling back to the provided default.

Resolves the effective request_info, falling back to the provided default.

Resolves the effective request_type for this action config.

Resolves the effective response type, falling back to the provided default.

Resolves the effective result_encoder setting, falling back to the provided default.

Resolves the effective retry, falling back to the provided default.

Resolves the effective timeout, falling back to the provided default.

Resolves the effective version, falling back to the provided default.

Checks if this config is enabled (not disabled).

Checks if this config has explicit arg_orders defined (not :map).

Checks if this config has explicit arg_types defined.

Types

choose_node_mode()

gen_api_type()

node_config()

permission_callback()

permission_mode()

result_encoder()

retry_config()

t()

@type t() :: %AshPhoenixGenApi.Resource.ActionConfig{
  __spark_metadata__: any(),
  arg_orders: [String.t()] | :map,
  arg_types: %{required(String.t()) => gen_api_type()} | nil,
  check_permission: permission_mode() | nil,
  choose_node_mode: choose_node_mode() | nil,
  code_interface?: boolean() | nil,
  disabled: boolean(),
  mfa: {module(), atom(), [any()]} | nil,
  name: atom(),
  nodes: node_config() | nil,
  permission_callback: permission_callback(),
  request_info: boolean() | nil,
  request_type: String.t() | nil,
  response_type: :sync | :async | :stream | :none | nil,
  result_encoder: result_encoder(),
  retry: retry_config() | nil,
  timeout: pos_integer() | :infinity | nil,
  version: String.t() | nil
}

Callbacks

permission_callback(request_type, args)

@callback permission_callback(request_type :: String.t(), args :: map()) :: boolean()

Callback function signature for permission checking.

The callback receives two arguments:

  • request_type - The PhoenixGenApi request type string (e.g., "delete_user")
  • args - A map of request arguments (e.g., %{"user_id" => "123", "role" => "admin"})

Returns true to allow the request, or false to deny permission.

Example

def check_permission(request_type, args) do
  case request_type do
    "delete_user" -> args["role"] == "admin"
    "update_profile" -> args["user_id"] == args["target_user_id"]
    _ -> true
  end
end

Functions

effective_check_permission(action_config, default)

@spec effective_check_permission(t(), permission_mode()) :: permission_mode()

Resolves the effective check_permission, falling back to the provided default.

effective_choose_node_mode(action_config, default)

@spec effective_choose_node_mode(t(), choose_node_mode()) :: choose_node_mode()

Resolves the effective choose_node_mode, falling back to the provided default.

effective_code_interface?(action_config, default)

@spec effective_code_interface?(t(), boolean()) :: boolean()

Resolves the effective code_interface? setting, falling back to the provided default.

When the action-level code_interface? is explicitly set (not nil), returns that value. Otherwise, returns the section-level default.

Examples

iex> config = %AshPhoenixGenApi.Resource.ActionConfig{code_interface?: false}
iex> AshPhoenixGenApi.Resource.ActionConfig.effective_code_interface?(config, true)
false

iex> config = %AshPhoenixGenApi.Resource.ActionConfig{code_interface?: nil}
iex> AshPhoenixGenApi.Resource.ActionConfig.effective_code_interface?(config, true)
true

effective_mfa(action_config, resource_module)

@spec effective_mfa(t(), module()) :: {module(), atom(), [any()]}

Resolves the effective mfa, falling back to auto-generation from the resource module and action name.

When mfa is explicitly set on the action config, it is returned as-is. Otherwise, generates {resource_module, action_name, []}.

The generated function is expected to accept positional arguments matching arg_orders, plus an optional request_info map as the last argument.

effective_nodes(action_config, default)

@spec effective_nodes(t(), node_config()) :: node_config()

Resolves the effective nodes, falling back to the provided default.

effective_permission_callback(action_config, default)

@spec effective_permission_callback(t(), permission_callback()) ::
  permission_callback()

Resolves the effective permission_callback, falling back to the provided default.

When the entity-level permission_callback is set, returns that value. Otherwise, returns the section-level default.

The callback MFA function receives (request_type, args) as arguments and returns true (continue) or false (permission denied).

Examples

iex> config = %Elixir.AshPhoenixGenApi.Resource.ActionConfig{permission_callback: {MyModule, :check, []}}
iex> Elixir.AshPhoenixGenApi.Resource.ActionConfig.effective_permission_callback(config, nil)
{MyModule, :check, []}

iex> config = %Elixir.AshPhoenixGenApi.Resource.ActionConfig{permission_callback: nil}
iex> Elixir.AshPhoenixGenApi.Resource.ActionConfig.effective_permission_callback(config, {MyModule, :check, []})
{MyModule, :check, []}

iex> config = %Elixir.AshPhoenixGenApi.Resource.ActionConfig{permission_callback: nil}
iex> Elixir.AshPhoenixGenApi.Resource.ActionConfig.effective_permission_callback(config, nil)
nil

effective_request_info(action_config, default)

@spec effective_request_info(t(), boolean()) :: boolean()

Resolves the effective request_info, falling back to the provided default.

effective_request_type(action_config)

@spec effective_request_type(t()) :: String.t()

Resolves the effective request_type for this action config.

Returns the explicit request_type if set, otherwise derives it from the action name by converting to a string.

Examples

iex> config = %AshPhoenixGenApi.Resource.ActionConfig{name: :send_message, request_type: "send_msg"}
iex> AshPhoenixGenApi.Resource.ActionConfig.effective_request_type(config)
"send_msg"

iex> config = %AshPhoenixGenApi.Resource.ActionConfig{name: :send_message, request_type: nil}
iex> AshPhoenixGenApi.Resource.ActionConfig.effective_request_type(config)
"send_message"

effective_response_type(action_config, default)

@spec effective_response_type(t(), :sync | :async | :stream | :none) ::
  :sync | :async | :stream | :none

Resolves the effective response type, falling back to the provided default.

effective_result_encoder(action_config, default)

@spec effective_result_encoder(t(), result_encoder()) :: result_encoder()

Resolves the effective result_encoder setting, falling back to the provided default.

The result_encoder determines how the result from the action MFA call is encoded:

  • :struct — Return the Ash resource struct as-is (default behavior)
  • :map — Convert the Ash resource struct to a map containing only public fields (using Ash.Resource.Info.public_fields/1 to filter; falls back to Map.from_struct/1 for non-Ash-resource structs)
  • {Module, :function, args} — Custom encoder MFA. The function receives the result as its first argument, followed by args, and must return the encoded result.
  • nil — Inherit from the section-level default

When the action-level result_encoder is explicitly set (not nil), returns that value. Otherwise, returns the section-level default.

Examples

iex> config = %AshPhoenixGenApi.Resource.ActionConfig{result_encoder: :map}
iex> AshPhoenixGenApi.Resource.ActionConfig.effective_result_encoder(config, :struct)
:map

iex> config = %AshPhoenixGenApi.Resource.ActionConfig{result_encoder: nil}
iex> AshPhoenixGenApi.Resource.ActionConfig.effective_result_encoder(config, :struct)
:struct

iex> config = %AshPhoenixGenApi.Resource.ActionConfig{result_encoder: {MyEncoder, :encode, []}}
iex> AshPhoenixGenApi.Resource.ActionConfig.effective_result_encoder(config, :struct)
{MyEncoder, :encode, []}

effective_retry(action_config, default)

@spec effective_retry(t(), retry_config()) :: retry_config()

Resolves the effective retry, falling back to the provided default.

effective_timeout(action_config, default)

@spec effective_timeout(t(), pos_integer() | :infinity) :: pos_integer() | :infinity

Resolves the effective timeout, falling back to the provided default.

Examples

iex> config = %Elixir.AshPhoenixGenApi.Resource.ActionConfig{timeout: 10_000}
iex> Elixir.AshPhoenixGenApi.Resource.ActionConfig.effective_timeout(config, 5_000)
10_000

iex> config = %Elixir.AshPhoenixGenApi.Resource.ActionConfig{timeout: nil}
iex> Elixir.AshPhoenixGenApi.Resource.ActionConfig.effective_timeout(config, 5_000)
5000

effective_version(action_config, default)

@spec effective_version(t(), String.t()) :: String.t()

Resolves the effective version, falling back to the provided default.

enabled?(action_config)

@spec enabled?(t()) :: boolean()

Checks if this config is enabled (not disabled).

has_explicit_arg_orders?(action_config)

@spec has_explicit_arg_orders?(t()) :: boolean()

Checks if this config has explicit arg_orders defined (not :map).

has_explicit_arg_types?(action_config)

@spec has_explicit_arg_types?(t()) :: boolean()

Checks if this config has explicit arg_types defined.