# `Bandera`

Runtime-configured feature flags, API-compatible with fun_with_flags.

The active store is resolved at runtime (`Bandera.Store.active/0`), so nothing
about persistence or caching is fixed at compile time.

# `all_flag_names`

```elixir
@spec all_flag_names() :: {:ok, [atom()]} | {:error, term()}
```

Returns `{:ok, names}` with every known flag name, or `{:error, reason}`.

## Examples

    iex> Bandera.enable(:checkout)
    iex> Bandera.all_flag_names()
    {:ok, [:checkout]}

# `all_flags`

```elixir
@spec all_flags() :: {:ok, [Bandera.Flag.t()]} | {:error, term()}
```

Returns `{:ok, flags}` with every stored `Bandera.Flag`, or `{:error, reason}`.

## Examples

    iex> Bandera.enable(:checkout)
    iex> {:ok, flags} = Bandera.all_flags()
    iex> Enum.map(flags, & &1.name)
    [:checkout]

# `clear`

```elixir
@spec clear(
  atom(),
  keyword()
) :: :ok | {:error, term()}
```

Removes gates from `flag_name`, returning `:ok`.

With no options the whole flag (all its gates) is deleted. A scope removes just
that gate, letting evaluation fall through to whatever remains:

  * `boolean: true` — clear the boolean gate
  * `for_actor: actor` — clear one actor gate
  * `for_group: group` — clear one group gate
  * `for_percentage: true` — clear the percentage gate

Returns `{:error, reason}` if the store delete fails.

## Examples

    iex> Bandera.enable(:checkout)
    iex> Bandera.clear(:checkout)
    :ok
    iex> Bandera.enabled?(:checkout)
    false

# `disable`

```elixir
@spec disable(
  atom(),
  keyword()
) :: {:ok, boolean()} | {:error, term()}
```

Disables `flag_name`, optionally scoped by an option, and returns `{:ok, enabled?}`.

Accepts the same scopes as `enable/2` (`for_actor:`, `for_group:`,
`for_percentage_of:`). For a percentage scope, disabling for `ratio` is equivalent
to enabling for `1.0 - ratio`. Returns `{:error, reason}` on a store write failure.

## Examples

    iex> Bandera.disable(:checkout)
    {:ok, false}

    iex> Bandera.enable(:beta)
    iex> Bandera.disable(:beta)
    {:ok, false}

# `enable`

```elixir
@spec enable(
  atom(),
  keyword()
) :: {:ok, boolean()} | {:error, term()}
```

Enables `flag_name`, optionally scoped by an option, and returns `{:ok, enabled?}`.

With no options the boolean gate is turned on. Supported scopes:

  * `for_actor: actor` — enable for one actor
  * `for_group: group` — enable for a named group
  * `for_percentage_of: {:time, ratio}` — enable for a ratio of calls
  * `for_percentage_of: {:actors, ratio}` — enable for a ratio of actors

`ratio` is a float in `0.0 < r < 1.0`. The write goes to the persistent store and
busts/refreshes the cache; returns `{:error, reason}` if the store write fails.

## Examples

    iex> Bandera.enable(:checkout)
    {:ok, true}

    iex> Bandera.enable(:beta, for_actor: "user-1")
    {:ok, true}

    iex> Bandera.enable(:gradual, for_percentage_of: {:actors, 0.25})
    {:ok, true}

# `enabled?`

```elixir
@spec enabled?(
  atom(),
  keyword()
) :: boolean()
```

Returns whether `flag_name` is enabled.

Pass `for: actor` to evaluate actor, group, and percentage-of-actors gates against
a specific subject (the actor is identified via the `Bandera.Actor`/`Bandera.Group`
protocols). The flag is read through the active store (cache included). A missing
flag, or a store lookup error, resolves to `false` (the error is logged).

## Examples

    iex> Bandera.enabled?(:unknown_flag)
    false

    iex> Bandera.enable(:checkout)
    iex> Bandera.enabled?(:checkout)
    true

    iex> Bandera.enable(:beta, for_actor: "user-1")
    iex> Bandera.enabled?(:beta, for: "user-1")
    true
    iex> Bandera.enabled?(:beta, for: "user-2")
    false

# `get_flag`

```elixir
@spec get_flag(atom()) :: {:ok, Bandera.Flag.t()} | {:error, term()}
```

Looks up a single flag, returning `{:ok, %Bandera.Flag{}}` or `{:error, reason}`.

An unknown flag still returns `{:ok, flag}` with an empty gate list (a disabled
flag), not an error.

## Examples

    iex> Bandera.enable(:checkout)
    iex> {:ok, flag} = Bandera.get_flag(:checkout)
    iex> flag.gates
    [%Bandera.Gate{type: :boolean, for: nil, enabled: true}]

    iex> {:ok, flag} = Bandera.get_flag(:unknown_flag)
    iex> flag.gates
    []

# `reload_config`

```elixir
@spec reload_config() :: :ok
```

Re-read application env into the runtime config snapshot.

---

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