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

Utility for generating JSON function config lists from Ash resources and domains.

Generates configuration maps in the PhoenixGenApi JSON function config format,
where each key is a `"request_type - Description"` string and each value
contains the event/data structure for the gateway.

## Output Formats

The module supports multiple output formats via the `:format` option:

- `:fun_configs` (default) — Returns the original list of
  `PhoenixGenApi.Structs.FunConfig` structs (Ash Resource type)
- `:map` — Returns an Elixir map in the JSON config list format
- `:json` — Returns a JSON-encoded string
- `{Module, :function, args}` — Custom encoder MFA that receives the
  FunConfig list and returns the desired format

## JSON Config List Format

The map format produces a structure like:

    %{
      "send_direct_message - Send direct message to other user" => %{
        "event" => "phoenix_gen_api",
        "data" => %{
          "user_id" => "user_1",
          "device_id" => "device_1",
          "request_type" => "send_direct_message",
          "request_id" => "request_1",
          "service" => "chat",
          "version" => "0.0.1",
          "args" => %{
            "to_user_id" => "",
            "content" => "",
            "reply_to_id" => ""
          }
        }
      }
    }

## Usage

    # Default: returns FunConfig structs (Ash Resource type)
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat)
    #=> [%PhoenixGenApi.Structs.FunConfig{...}, ...]

    # As Elixir map (JSON config list format)
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat, format: :map)
    #=> %{"send_direct_message - ..." => %{...}, ...}

    # As JSON string
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat, format: :json)
    #=> "{\"send_direct_message - ...\": {...}, ...}"

    # Custom encoder MFA
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat, format: {MyEncoder, :encode, []})

    # With custom descriptions
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat,
      format: :map,
      descriptions: %{"send_direct_message" => "Send direct message to other user"}
    )

    # With description function
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat,
      format: :map,
      descriptions: fn fun_config ->
        String.replace(fun_config.request_type, "_", " ")
      end
    )

    # With custom arg values
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat,
      format: :map,
      arg_values: %{
        "send_direct_message" => %{
          "to_user_id" => "user_2",
          "content" => "Hello, how are you?",
          "reply_to_id" => ""
        }
      }
    )

    # With arg values function
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat,
      format: :map,
      arg_values: fn fun_config ->
        # Generate example values based on arg types
        fun_config.arg_types
        |> Enum.map(fn {name, type} -> {name, example_value(type)} end)
        |> Map.new()
      end
    )

# `arg_values`

```elixir
@type arg_values() ::
  %{required(String.t()) =&gt; %{required(String.t()) =&gt; term()}}
  | (map() -&gt; map())
  | nil
```

Source for argument example/default values.

- A map of `%{request_type => %{arg_name => value}}` for static values
- A function `(fun_config -> args_map)` for dynamic values
- `nil` — Uses type-based default values

# `description_source`

```elixir
@type description_source() ::
  %{required(String.t()) =&gt; String.t()} | (map() -&gt; String.t()) | nil
```

Source for description strings used in config keys.

- A map of `%{request_type => description}` for static descriptions
- A function `(fun_config -> description)` for dynamic descriptions
- `nil` — Uses request_type as the key without description

# `format`

```elixir
@type format() :: :fun_configs | :map | :json | {module(), atom(), [any()]}
```

Output format for the generated config.

- `:fun_configs` — Returns `PhoenixGenApi.Structs.FunConfig` structs (Ash Resource type)
- `:map` — Returns Elixir map in JSON config list format
- `:json` — Returns JSON-encoded string
- `{Module, :function, args}` — Custom encoder MFA

# `option`

```elixir
@type option() ::
  {:format, format()}
  | {:user_id, String.t()}
  | {:device_id, String.t()}
  | {:request_id, String.t()}
  | {:descriptions, description_source()}
  | {:event_name, String.t()}
  | {:arg_values, arg_values()}
```

Option for `generate/2`.

- `:format` — Output format (default: `:fun_configs`)
- `:user_id` — Default user_id in data (default: `"user_1"`)
- `:device_id` — Default device_id in data (default: `"device_1"`)
- `:request_id` — Default request_id in data (default: `"request_1"`)
- `:descriptions` — Description source for key names (default: `nil`)
- `:event_name` — Event name string (default: `"phoenix_gen_api"`)
- `:arg_values` — Argument values source (default: `nil`)

# `default_value_for_type`

```elixir
@spec default_value_for_type(atom() | tuple() | keyword()) :: term()
```

Returns a default example value for a PhoenixGenApi argument type.

Useful for generating placeholder values in the args map.

## Examples

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type(:string)
    ""

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type(:num)
    0

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type(:boolean)
    false

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type(:datetime)
    ""

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type(:naive_datetime)
    ""

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type(:map)
    %{}

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type(:list)
    []

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type({:list_string, 100, 50})
    []

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type({:list_num, 100})
    []

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type({:string, 255})
    ""

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type({:map, 100})
    %{}

    iex> AshPhoenixGenApi.JsonConfig.default_value_for_type({:list, 100})
    []

# `fun_config_to_entry`

```elixir
@spec fun_config_to_entry(map(), [option()]) :: {String.t(), map()}
```

Converts a single FunConfig struct to a map entry tuple.

Returns `{key, value}` where `key` is the config key string and `value`
is the event/data map.

## Parameters

  - `fun_config` — A `PhoenixGenApi.Structs.FunConfig` struct
  - `opts` — Options for building the entry

## Examples

    fun_config = %PhoenixGenApi.Structs.FunConfig{request_type: "send_direct_message", ...}
    {key, value} = AshPhoenixGenApi.JsonConfig.fun_config_to_entry(fun_config)
    #=> {"send_direct_message", %{"event" => "phoenix_gen_api", "data" => %{...}}}

# `generate`

```elixir
@spec generate(module(), [option()]) :: term()
```

Generates a function config list from an Ash domain or resource.

Automatically detects whether the source is a domain or resource and
retrieves the appropriate FunConfig structs.

## Parameters

  - `source` — An Ash domain or resource module
  - `opts` — Options for generation and encoding

## Options

  - `:format` — Output format (default: `:fun_configs`)
    - `:fun_configs` — Returns list of `PhoenixGenApi.Structs.FunConfig` structs
    - `:map` — Returns Elixir map in JSON config list format
    - `:json` — Returns JSON-encoded string
    - `{Module, :function, args}` — Custom encoder MFA
  - `:user_id` — Default user_id in data. Default: `"user_1"`
  - `:device_id` — Default device_id in data. Default: `"device_1"`
  - `:request_id` — Default request_id in data. Default: `"request_1"`
  - `:descriptions` — Description source for key names. Can be:
    - A map of `%{request_type => description}`
    - A function `(fun_config -> description)`
    - `nil` — Uses request_type as key (default)
  - `:event_name` — Event name string. Default: `"phoenix_gen_api"`
  - `:arg_values` — Argument values source. Can be:
    - A map of `%{request_type => %{arg_name => value}}`
    - A function `(fun_config -> args_map)`
    - `nil` — Uses type-based defaults (default)

## Returns

The generated config in the specified format.

## Examples

    # From a domain — default format (FunConfig structs)
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat)
    #=> [%PhoenixGenApi.Structs.FunConfig{request_type: "send_direct_message", ...}, ...]

    # From a domain — map format
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat, format: :map)
    #=> %{"send_direct_message" => %{...}, ...}

    # From a resource — map format
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat.DirectMessage, format: :map)

    # With custom descriptions
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat,
      format: :map,
      descriptions: %{"send_direct_message" => "Send direct message to other user"}
    )

    # With custom encoder MFA
    AshPhoenixGenApi.JsonConfig.generate(MyApp.Chat, format: {MyEncoder, :encode, []})

# `generate_from_domain`

```elixir
@spec generate_from_domain(module(), [option()]) :: term()
```

Generates a function config list from an Ash domain.

Same as `generate/2` but explicitly for domain modules.

## Parameters

  - `domain` — An Ash domain module
  - `opts` — Same options as `generate/2`

## Examples

    AshPhoenixGenApi.JsonConfig.generate_from_domain(MyApp.Chat, format: :map)

# `generate_from_resource`

```elixir
@spec generate_from_resource(module(), [option()]) :: term()
```

Generates a function config list from an Ash resource.

Same as `generate/2` but explicitly for resource modules.

## Parameters

  - `resource` — An Ash resource module
  - `opts` — Same options as `generate/2`

## Examples

    AshPhoenixGenApi.JsonConfig.generate_from_resource(MyApp.Chat.DirectMessage, format: :map)

# `to_json`

```elixir
@spec to_json([map()], [option()]) :: String.t()
```

Converts a list of FunConfig structs to a JSON string.

## Parameters

  - `fun_configs` — A list of `PhoenixGenApi.Structs.FunConfig` structs
  - `opts` — Options (same as `generate/2`, except `:format` is ignored)

## Examples

    fun_configs = AshPhoenixGenApi.Resource.Info.fun_configs(MyApp.Chat.DirectMessage)
    AshPhoenixGenApi.JsonConfig.to_json(fun_configs)
    #=> "{\"send_direct_message\": {...}}"

# `to_map`

```elixir
@spec to_map([map()], [option()]) :: map()
```

Converts a list of FunConfig structs to the JSON config map format.

This is useful when you already have FunConfig structs and want to
convert them to the map format without re-fetching from a domain/resource.

## Parameters

  - `fun_configs` — A list of `PhoenixGenApi.Structs.FunConfig` structs
  - `opts` — Options (same as `generate/2`, except `:format` is ignored)

## Examples

    fun_configs = AshPhoenixGenApi.Resource.Info.fun_configs(MyApp.Chat.DirectMessage)
    AshPhoenixGenApi.JsonConfig.to_map(fun_configs)
    #=> %{"send_direct_message" => %{...}, ...}

    AshPhoenixGenApi.JsonConfig.to_map(fun_configs,
      descriptions: %{"send_direct_message" => "Send direct message"}
    )

---

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