<!--
This file was generated by Spark. Do not edit it by hand.
-->
# AshPhoenixGenApi.Domain

Ash Domain extension for PhoenixGenApi configuration.

This extension provides domain-level configuration for PhoenixGenApi,
including default service settings and automatic generation of a
"supporter" module that aggregates FunConfigs from all resources
in the domain.

The generated supporter module implements the `PhoenixGenApi` client
config interface (`get_config/1`, `get_config_version/1`), allowing
gateway nodes to pull API configurations from service nodes.

## Usage

Add the extension to your Ash domain:

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

      gen_api do
        service "chat"
        nodes {ClusterHelper, :get_nodes, [:chat]}
        choose_node_mode :random
        timeout 5_000
        response_type :async
        request_info true
        version "0.0.1"

        supporter_module MyApp.Chat.GenApiSupporter
      end

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

This will generate `MyApp.Chat.GenApiSupporter` with:

    defmodule MyApp.Chat.GenApiSupporter do
      @moduledoc """
      Auto-generated PhoenixGenApi supporter module for MyApp.Chat.
      Aggregates FunConfigs from all resources in the domain.
      """

      alias PhoenixGenApi.Structs.FunConfig

      def get_config(remote_id) do
        {:ok, fun_configs()}
      end

      def get_config_version(remote_id) do
        {:ok, "0.0.1"}
      end

      def fun_configs do
        MyApp.Chat.DirectMessage.__ash_phoenix_gen_api_fun_configs__() ++
          MyApp.Chat.GroupMessage.__ash_phoenix_gen_api_fun_configs__()
      end

      def list_request_types do
        fun_configs() |> Enum.map(& &1.request_type)
      end

      def get_fun_config(request_type) do
        fun_configs() |> Enum.find(&(&1.request_type == request_type))
      end
    end

## Domain-Level Defaults

Domain-level settings serve as defaults for all resources in the domain
that use `AshPhoenixGenApi.Resource`. Each resource can override these
defaults in its own `gen_api` section.

Resolution order for any setting:
1. Resource action-level (e.g., `action :foo do timeout 10_000 end`)
2. Resource section-level (e.g., `gen_api do timeout 5_000 end`)
3. Domain section-level (this extension, e.g., `gen_api do timeout 5_000 end`)
4. Built-in defaults (e.g., timeout defaults to 5000)

## Gateway Node Configuration

On the Phoenix gateway node, configure the supporter module in `config.exs`:

    config :phoenix_gen_api, :gen_api,
      service_configs: [
        %{
          service: "chat",
          nodes: {ClusterHelper, :get_nodes, [:chat]},
          module: MyApp.Chat.GenApiSupporter,
          function: :get_config,
          args: [:gateway_1]
        }
      ]

## Active Push Configuration

In addition to the pull-based model (where the gateway pulls config from
service nodes), you can configure the supporter module to **actively push**
its configuration to gateway nodes.

Set `push_nodes` to specify which gateway nodes to push to:

    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:

- `build_push_config/0` - Builds a `PushConfig` struct from the domain config
- `push_to_gateway/2` - Pushes config to a specific gateway node
- `push_on_startup/2` - Pushes config on application startup
- `verify_on_gateway/2` - Verifies config version on a gateway node
- `resolve_push_nodes/0` - Resolves `push_nodes` at runtime
- `push_to_configured_nodes/1` - Pushes to all configured push_nodes

Example usage during application startup:

    def start(_type, _args) do
      # ... start supervision tree, then:
      MyApp.Chat.GenApiSupporter.push_to_configured_nodes()
      # Or push to a specific node:
      MyApp.Chat.GenApiSupporter.push_on_startup(:"gateway1@host")
    end


## gen_api
Configure PhoenixGenApi at the domain level.

Domain-level settings serve as defaults for all resources in the domain
that use `AshPhoenixGenApi.Resource`. Each resource can override these
defaults in its own `gen_api` section.

The `supporter_module` option defines the name of the module that will
be auto-generated to aggregate FunConfigs from all resources. This module
implements the PhoenixGenApi client config interface.




### Examples
```
gen_api do
  service "chat"
  nodes {ClusterHelper, :get_nodes, [:chat]}
  choose_node_mode :random
  timeout 5_000
  response_type :async
  request_info true
  version "0.0.1"
  supporter_module MyApp.Chat.GenApiSupporter
end

```

```
# Minimal configuration
gen_api do
  service "chat"
  supporter_module MyApp.Chat.GenApiSupporter
end

```




### Options

| Name | Type | Default | Docs |
|------|------|---------|------|
| [`supporter_module`](#gen_api-supporter_module){: #gen_api-supporter_module .spark-required} | `any` |  | The name of the module to generate that will serve as the PhoenixGenApi supporter for this domain. This module will be auto-generated with 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 Example: `MyApp.Chat.GenApiSupporter` |
| [`service`](#gen_api-service){: #gen_api-service } | `any` |  | The service name for this domain's API endpoints. This serves as the default for all resources in the domain. Accepts a string or atom. Example: `"chat"`, `"user_service"`, `:notification` |
| [`nodes`](#gen_api-nodes){: #gen_api-nodes } | `any` | `:local` | Default target nodes for all resources in this domain. Can be: - A list of node atoms: `[:"node1@host", :"node2@host"]` - An MFA tuple that returns a node list at runtime: `{ClusterHelper, :get_nodes, [:chat]}` - `:local` - Execute on the local node (default) |
| [`choose_node_mode`](#gen_api-choose_node_mode){: #gen_api-choose_node_mode } | `any` | `:random` | Default node selection strategy for all resources in this domain. - `:random` - Select a random node (default) - `:hash` - Hash-based selection using request_type - `{:hash, key}` - Hash-based selection using the specified argument key - `:round_robin` - Round-robin across nodes |
| [`timeout`](#gen_api-timeout){: #gen_api-timeout } | `any` | `5000` | Default timeout in milliseconds for all resources in this domain. Individual resources and actions can override this. Accepts a positive integer or `:infinity`. |
| [`response_type`](#gen_api-response_type){: #gen_api-response_type } | `atom` | `:async` | Default response mode for all resources in this domain. - `:sync` - Client waits for the result - `:async` - Client receives an ack, then the result later (default) - `:stream` - Client receives streamed chunks - `:none` - Fire and forget |
| [`request_info`](#gen_api-request_info){: #gen_api-request_info } | `boolean` | `true` | Default for whether to pass request info (user_id, device_id, request_id) as the last argument to the MFA function for all resources in this domain. |
| [`check_permission`](#gen_api-check_permission){: #gen_api-check_permission } | `any` | `false` | Default permission check mode for all resources in this domain. - `false` - No permission check (default) - `:any_authenticated` - Requires a valid user_id - `{:arg, "arg_name"}` - The specified argument must match user_id - `{:role, ["admin"]}` - User must have one of the listed roles |
| [`permission_callback`](#gen_api-permission_callback){: #gen_api-permission_callback } | `any` |  | Default permission callback MFA for all resources in this domain. When set, takes precedence over `check_permission`. Accepts `{Module, :function, []}` or `nil`. The callback function receives `request_type` (string) and `args` (map) as arguments and returns `true` (continue) or `false` (permission denied). The callback function signature:     @callback check_permission(request_type :: String.t(), args :: map()) :: boolean() Example callback:     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 When both `permission_callback` and `check_permission` are set, `permission_callback` takes precedence and is stored in the FunConfig's `permission_callback` field. Defaults to `nil`. |
| [`version`](#gen_api-version){: #gen_api-version } | `String.t` | `"0.0.1"` | Default version string for all resources in this domain. Used for PhoenixGenApi API versioning. **Format**: Should follow [Semantic Versioning](https://semver.org) (e.g., `"1.0.0"`). Each resource can set its own `version` in its `gen_api` section, but it is recommended to keep versions consistent across resources in the same domain. The domain-level version is returned by `get_config_version/1` on the generated supporter module. |
| [`retry`](#gen_api-retry){: #gen_api-retry } | `any` |  | Default retry configuration for all resources in this domain. - `nil` - No retry (default) - A positive number `n` - Equivalent to `{:all_nodes, n}` - `{:same_node, n}` - Retry on the same node(s) - `{:all_nodes, n}` - Retry across all available nodes |
| [`define_supporter?`](#gen_api-define_supporter?){: #gen_api-define_supporter? } | `boolean` | `true` | Whether to auto-generate the supporter module. Set to `false` if you want to define the supporter module manually. When `false`, the extension will still collect FunConfigs from resources but will not generate the supporter module. You can use `AshPhoenixGenApi.Domain.Info.fun_configs/1` to get the aggregated FunConfigs and build your own supporter module. |
| [`push_nodes`](#gen_api-push_nodes){: #gen_api-push_nodes } | `any` |  | Target gateway nodes to push config to. Can be: - A list of node atoms: `[:"gateway1@host", :"gateway2@host"]` - An MFA tuple that returns a node list at runtime: `{ClusterHelper, :get_gateway_nodes, []}` - `nil` - No push nodes configured (default) When set, the generated supporter module will include functions to actively push its configuration to the specified gateway nodes. |
| [`push_on_startup`](#gen_api-push_on_startup){: #gen_api-push_on_startup } | `boolean` | `false` | Whether to automatically push config to the configured `push_nodes` on application startup. When `true`, the supporter module's `push_on_startup/2` function can be called during application startup to push the config to gateway nodes. Note: you still need to hook this into your application's supervision tree or startup sequence manually. **Failure behavior**: If a gateway node is unreachable when `push_on_startup/2` is called, the function will return `{:error, reason}` (e.g., `{:error, :node_down}`). It does **not** crash the calling process. The caller is responsible for deciding whether to retry or log the failure. For automatic retry with backoff, consider wrapping the call in a `Task` with retry logic:     Task.start(fn ->       case MyApp.Chat.GenApiSupporter.push_on_startup(node) do         :ok -> :ok         {:error, _reason} ->           # Implement retry with backoff           :timer.sleep(1000)           MyApp.Chat.GenApiSupporter.push_on_startup(node)       end     end) |
| [`result_encoder`](#gen_api-result_encoder){: #gen_api-result_encoder } | `any` | `:struct` | Default result encoding mode for all resources in this domain. Determines how the result returned from the action MFA call is encoded before being returned to the caller. - `:struct` — Return the Ash resource struct as-is (default) - `: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. Individual resources and actions can override this with their own `result_encoder` option. For `:map` encoding, Ash resource structs are converted to maps containing only their public fields (attributes, calculations, aggregates, relationships). Lists of structs are mapped accordingly. Non-Ash-resource structs fall back to `Map.from_struct/1`. For custom MFA encoders, the function receives the result and must return the encoded value. Defaults to `:struct`. |







<style type="text/css">.spark-required::after { content: "*"; color: red !important; }</style>
