# `AshPhoenixGenApi.Transformers.DefineFunConfigs`
[🔗](https://github.com/ohhi-vn/ash_phoenix_gen_api/blob/v1.0.3/lib/ash_phoenix_gen_api/transformers/define_fun_configs.ex#L1)

Transformer that generates PhoenixGenApi FunConfig structs and code interface
functions from Ash resource actions.

This transformer reads the `gen_api` DSL section configuration and:

1. Generates `PhoenixGenApi.Structs.FunConfig` structs for each configured action,
   stored in a `__ash_phoenix_gen_api_fun_configs__/0` function on the resource module.

2. Generates code interface functions for each enabled action (when `code_interface?`
   is `true`), allowing developers to call Ash actions directly as Elixir functions
   on the resource module.

## Resolution Order

For each FunConfig field, values are resolved in this order:

1. **Action-level explicit config** — e.g., `action :foo do timeout 10_000 end`
2. **Resource 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
   using `AshPhoenixGenApi.TypeMapper`

For `mfa`:

1. **Explicit `mfa`** on the action entity
2. **Auto-generated** as `{ResourceModule, :action_name, []}`

For `code_interface?`:

1. **Action-level `code_interface?`** on the action entity
2. **Section-level `code_interface?`** — e.g., `gen_api do code_interface? true end`
3. **Built-in default** — defaults to `true`

## Generated Functions

After this transformer runs, the resource module will have:

    def __ash_phoenix_gen_api_fun_configs__ do
      [
        %PhoenixGenApi.Structs.FunConfig{
          request_type: "send_direct_message",
          service: "chat",
          nodes: {ClusterHelper, :get_nodes, [:chat]},
          # ...
        },
        # ...
      ]
    end

This function is used by `AshPhoenixGenApi.Resource.Info.fun_configs/1` and
by the domain-level supporter module to aggregate FunConfigs.

Additionally, for each action with `code_interface?` enabled, the following
functions are generated. All functions use `CodeInterface.params_and_opts/2`
to properly disambiguate between args maps and opts keyword lists, allowing
callers to pass just opts (e.g., `action(actor: user)`) without wrapping
them in a second argument.

### Create actions

    def create_action(params_or_opts \\ [], opts \\ []) do
      {args, opts} = CodeInterface.params_and_opts(params_or_opts, opts)
      Changeset.for_create(__MODULE__, :create_action, args, opts)
      |> Ash.create(opts)
    end

    def create_action!(params_or_opts \\ [], opts \\ []) do
      {args, opts} = CodeInterface.params_and_opts(params_or_opts, opts)
      Changeset.for_create(__MODULE__, :create_action, args, opts)
      |> Ash.create!(opts)
    end

### Read actions

    def read_action(params_or_opts \\ [], opts \\ []) do
      {args, opts} = CodeInterface.params_and_opts(params_or_opts, opts)
      Query.for_read(__MODULE__, :read_action, args, opts)
      |> Ash.read(opts)
    end

    def read_action!(params_or_opts \\ [], opts \\ []) do
      {args, opts} = CodeInterface.params_and_opts(params_or_opts, opts)
      Query.for_read(__MODULE__, :read_action, args, opts)
      |> Ash.read!(opts)
    end

### Update actions (require a record as first argument)

    def update_action(record, params_or_opts \\ [], opts \\ []) do
      {args, opts} = CodeInterface.params_and_opts(params_or_opts, opts)
      Changeset.for_update(record, :update_action, args, opts)
      |> Ash.update(opts)
    end

    def update_action!(record, params_or_opts \\ [], opts \\ []) do
      {args, opts} = CodeInterface.params_and_opts(params_or_opts, opts)
      Changeset.for_update(record, :update_action, args, opts)
      |> Ash.update!(opts)
    end

### Destroy actions (require a record as first argument)

    def destroy_action(record, params_or_opts \\ [], opts \\ []) do
      {args, opts} = CodeInterface.params_and_opts(params_or_opts, opts)
      Changeset.for_destroy(record, :destroy_action, args, opts)
      |> Ash.destroy(opts)
    end

    def destroy_action!(record, params_or_opts \\ [], opts \\ []) do
      {args, opts} = CodeInterface.params_and_opts(params_or_opts, opts)
      Changeset.for_destroy(record, :destroy_action, args, opts)
      |> Ash.destroy!(opts)
    end

### Generic actions

    def generic_action(params_or_opts \\ [], opts \\ []) do
      {args, opts} = CodeInterface.params_and_opts(params_or_opts, opts)
      ActionInput.for_action(__MODULE__, :generic_action, args, opts)
      |> Ash.run_action(opts)
    end

    def generic_action!(params_or_opts \\ [], opts \\ []) do
      {args, opts} = CodeInterface.params_and_opts(params_or_opts, opts)
      ActionInput.for_action(__MODULE__, :generic_action, args, opts)
      |> Ash.run_action!(opts)
    end

# `after?`

Runs after all other transformers so that Ash action info is fully available.

# `after_compile?`

# `before?`

Does not need to run before any specific transformer.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
