Packages
Event-driven notification system for Ash Framework with multiple transport types
Current section
Files
Jump to
Current section
Files
lib/calculations/source_label.ex
defmodule AshDispatch.Calculations.SourceLabel do
@moduledoc """
Calculates a human-readable label for the source resource type.
Uses UrlBuilder.resource_label/1 if available, else derives from module name.
"""
use Ash.Resource.Calculation
alias AshDispatch.{Config, EventResolver}
@impl true
def load(_query, _opts, _context), do: [:event_id, :source_type]
@impl true
def calculate(records, _opts, _context) do
url_builder = Config.url_builder()
Enum.map(records, &compute_source_label(&1, url_builder))
end
defp compute_source_label(record, url_builder) do
# Use EventResolver for consistent event lookup and callback execution
case get_data_key_from_event(record.event_id) do
{:ok, data_key} ->
get_label_from_url_builder(data_key, url_builder) ||
derive_from_source_type(record.source_type)
:error ->
derive_from_source_type(record.source_type)
end
end
# Use EventResolver for safe data_key callback execution
defp get_data_key_from_event(event_id) do
case EventResolver.find_module(event_id) do
{:ok, module} ->
case EventResolver.data_key(module) do
key when is_atom(key) and not is_nil(key) -> {:ok, key}
_ -> :error
end
{:error, :not_found} ->
:error
end
end
defp get_label_from_url_builder(_data_key, nil), do: nil
defp get_label_from_url_builder(data_key, url_builder) do
# url_builder is an app-specific module, not an event module
# Keep using function_exported? for external modules
if Code.ensure_loaded?(url_builder) && function_exported?(url_builder, :resource_label, 1) do
try do
url_builder.resource_label(data_key)
rescue
_ -> nil
end
end
end
defp derive_from_source_type(nil), do: nil
defp derive_from_source_type(source_type) when is_binary(source_type) do
source_type |> String.split(".") |> List.last()
end
end