# `DevPortAllocator`
[🔗](https://github.com/victorbjorklund/dev_port_allocator/blob/v0.1.0/lib/dev_port_allocator.ex#L1)

Resolve development ports dynamically while preserving explicit environment
configuration.

This library is framework-agnostic and can be used from `config/runtime.exs`
in Phoenix (or any Elixir app that needs predictable local port allocation).
WARNING: This library is intended for development servers only.
Do not use it in production deployments.

Typical behavior:

- If a relevant env var is present, explicit values win.
- If no explicit env vars are present, probe from a starting port.
- When the default is busy, return the next available port (or contiguous
  block).

# `block_result`

```elixir
@type block_result() :: %{ports: [pos_integer()], source: source()}
```

# `single_result`

```elixir
@type single_result() :: %{port: pos_integer(), source: source()}
```

# `source`

```elixir
@type source() :: :explicit | :default | :fallback
```

# `port_available?`

```elixir
@spec port_available?(
  pos_integer(),
  keyword()
) :: boolean()
```

Check if a TCP port is available on localhost.

# `resolve_block`

```elixir
@spec resolve_block(
  map(),
  keyword()
) :: block_result()
```

Resolve a contiguous block of ports.

## Options

- `:env_vars` - ordered env var keys for explicit ports
- `:default_port` - default base port for the first entry (default: `4000`)
- `:start_port` - first base port to probe (defaults to `:default_port`)
- `:block_size` - number of contiguous ports to allocate
- `:port_available?` - custom availability function for testing
- `:ip` - bind address for availability checks (default: `{127, 0, 0, 1}`)

If any `:env_vars` key is present, allocation is explicit and probing is
skipped. Missing explicit keys use implied defaults based on the first port.

# `resolve_port`

```elixir
@spec resolve_port(
  map(),
  keyword()
) :: single_result()
```

Resolve a single port.

## Options

- `:env_var` - env var key used for explicit value (default: `"PORT"`)
- `:default_port` - default preferred port (default: `4000`)
- `:start_port` - first port to probe when no explicit env var exists
- `:port_available?` - custom availability function for testing
- `:ip` - bind address for availability checks (default: `{127, 0, 0, 1}`)

## Examples

    iex> DevPortAllocator.resolve_port(%{}, default_port: 4000, port_available?: fn p -> p == 4000 end)
    %{port: 4000, source: :default}

    iex> DevPortAllocator.resolve_port(%{"PORT" => "5050"})
    %{port: 5050, source: :explicit}

---

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