AshPhoenixGenApi.Transformers.DefineDomainSupporter (ash_phoenix_gen_api v1.0.3)

Copy Markdown View Source

Transformer that generates the PhoenixGenApi supporter module for an Ash domain.

This transformer reads the domain-level gen_api DSL configuration and generates a module that aggregates FunConfig structs from all resources in the domain that have the AshPhoenixGenApi.Resource extension configured.

The generated supporter module implements the PhoenixGenApi client config interface, allowing gateway nodes to pull API configurations from service nodes.

Generated Module

Given a domain configuration like:

defmodule MyApp.Chat do
  use Ash.Domain,
    extensions: [AshPhoenixGenApi.Domain]

  gen_api do
    service "chat"
    nodes {ClusterHelper, :get_nodes, [:chat]}
    supporter_module MyApp.Chat.GenApiSupporter
    version "0.0.1"
  end

  resources do
    resource MyApp.Chat.DirectMessage
    resource MyApp.Chat.GroupMessage
  end
end

This transformer generates:

defmodule MyApp.Chat.GenApiSupporter do
  @moduledoc """
  Auto-generated PhoenixGenApi supporter module for MyApp.Chat.

  Aggregates FunConfigs from all resources in the domain that have
  the AshPhoenixGenApi.Resource extension configured.

  ## Functions

  - `get_config/1` - Returns `{:ok, fun_configs()}` for PhoenixGenApi pull
  - `get_config_version/1` - Returns `{:ok, version}` for version checking
  - `fun_configs/0` - Returns the aggregated list of FunConfig structs
  - `list_request_types/0` - Returns all available request type strings
  - `get_fun_config/1` - Returns a specific FunConfig by request_type
  """

  alias PhoenixGenApi.Structs.FunConfig

  require Logger

  @doc """
  Support for remote pull general api config.
  Returns {:ok, list_of_fun_configs}
  """
  def get_config(remote_id) do
    Logger.info("Get config from remote: #{inspect(remote_id)}")
    {:ok, fun_configs()}
  end

  @doc """
  Support for remote pull general api config version.
  """
  def get_config_version(remote_id) do
    Logger.info("Get config version from remote: #{inspect(remote_id)}")
    {:ok, "0.0.1"}
  end

  @doc """
  Return list of %FunConfig{} for all APIs in this domain.
  """
  def fun_configs do
    MyApp.Chat.DirectMessage.__ash_phoenix_gen_api_fun_configs__() ++
      MyApp.Chat.GroupMessage.__ash_phoenix_gen_api_fun_configs__()
  end

  @doc """
  Get a specific function configuration by request_type.
  """
  def get_fun_config(request_type) do
    fun_configs()
    |> Enum.find(&(&1.request_type == request_type))
  end

  @doc """
  Get all available request types.
  """
  def list_request_types do
    fun_configs()
    |> Enum.map(& &1.request_type)
  end
end

Push Configuration Functions

When push_nodes is configured, the generated supporter module also includes functions for actively pushing configuration to gateway nodes:

gen_api do
  service "chat"
  supporter_module MyApp.Chat.GenApiSupporter
  version "0.0.1"
  push_nodes [:"gateway1@host", :"gateway2@host"]
  # Or use an MFA tuple for runtime resolution:
  # push_nodes {ClusterHelper, :get_gateway_nodes, []}
end

This adds the following functions to the generated supporter module:

# Builds a PushConfig struct from the domain configuration
def build_push_config do
  # Resolves nodes at runtime (calls MFA if configured)
  # Returns %PushConfig{service: "chat", nodes: [...], ...}
end

# Pushes config to a specific gateway node
def push_to_gateway(server_node, opts \ [])

# Pushes config on application startup (with enhanced logging)
def push_on_startup(server_node, opts \ [])

# Verifies config version on a gateway node
def verify_on_gateway(server_node, opts \ [])

# Resolves push_nodes at runtime (handles MFA tuples, lists, :local, nil)
def resolve_push_nodes

# Pushes config to all configured push_nodes
def push_to_configured_nodes(opts \ [])

Configuration

The define_supporter? option controls whether the supporter module is auto-generated. Set it to false if you want to define the module manually (e.g., when you need to add custom logic or merge configs from non-Ash sources).

When define_supporter? is false, you can still use AshPhoenixGenApi.Domain.Info.fun_configs/1 to get the aggregated FunConfigs and build your own supporter module.

Summary

Functions

Runs after the DefineFunConfigs transformer so that resource FunConfigs are already generated.

Does not need to run before any specific transformer.

Functions

after?(arg1)

Runs after the DefineFunConfigs transformer so that resource FunConfigs are already generated.

after_compile?()

Callback implementation for Spark.Dsl.Transformer.after_compile?/0.

before?(_)

Does not need to run before any specific transformer.