# Configuration Deep Dive

Kurier's `Configurator` is designed for extreme flexibility, allowing you to define your messaging topology in the format that best fits your project—be it JSON, YAML, TOML, XML, or even traditional INI files.

## Table of Contents

- [1. Multi-Format Support](#1-multi-format-support)
- [2. Environment Variable Interpolation](#2-environment-variable-interpolation)
- [3. Section Structures](#3-section-structures)
- [4. Lazy Loading & Extras](#4-lazy-loading--extras)
- [5. Programmatic Registration](#5-programmatic-registration)

---

## 1. Multi-Format Support

The `Configurator` automatically detects the format of your configuration source. You can provide a file path or a raw string content.

### JSON (Modern Default)
```json
{
  "rabbitmq": {
    "orders_line": {
      "host": "localhost",
      "port": 5672,
      "username": "guest",
      "password": "guest",
      "virtual_host": "/",
      "queue_name": "orders_queue"
    }
  }
}
```

### TOML (Python Standard)
```toml
[rabbitmq.orders_line]
host = "localhost"
port = 5672
username = "guest"
password = "guest"
virtual_host = "/"
queue_name = "orders_queue"
```

### YAML (Concise)
```yaml
rabbitmq:
  orders_line:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual_host: /
    queue_name: orders_queue
```

---

## 2. Environment Variable Interpolation

Kurier supports native environment variable resolution using the `${VAR}` syntax. You can also provide a default value if the variable is not set:

```yaml
rabbitmq:
  orders_line:
    host: "${RABBITMQ_HOST:-localhost}"
    port: 5672
    username: "${RABBITMQ_USER}"
    password: "${RABBITMQ_PASS}"
    virtual_host: "${RABBITMQ_VHOST:-/}"
```

If a variable is missing and no default is provided, the `Configurator` will raise a `ValueError`, preventing the application from starting in an invalid state.

---

## 3. Section Structures

The `Configurator` supports two ways to define your lines:

### Multiple Instances (Nested)
Define a category and multiple named instances beneath it.
```json
"rabbitmq": {
  "line_a": { ... },
  "line_b": { ... }
}
```

### Single Instance (Flat)
If you only need one instance of a transport, you can define it directly under the transport key.
```json
"rabbitmq": {
  "name": "my_only_queue",
  "host": "localhost",
  "port": 5672,
  "virtual_host": "/",
  ...
}
```

---

## 4. Lazy Loading & Extras

To keep the base `kurier-py` package lightweight, transport-specific libraries (like `pika` for RabbitMQ or `kafka-python-ng` for Kafka) are **Optional Dependencies**.

The `Configurator` uses lazy loading:
1.  It registers the *paths* to the transport classes.
2.  It only attempts to import the required libraries when you instantiate a line of that type.
3.  If the library is missing, Kurier provides a helpful error message indicating which "extra" you need to install:
    *   `pip install "kurier-py[rabbitmq]"`
    *   `pip install "kurier-py[kafka]"`
    *   `pip install "kurier-py[azure]"`

---

## 5. Programmatic Registration

While Kurier comes with built-in support for major brokers, you can register custom transports dynamically:

```python
from kurier.configurations.configurator import Configurator
from my_custom_lib import MyCustomLine, MyCustomConfig

Configurator.register_transport(
    name="redis", 
    class_or_path=MyCustomLine, 
    config_class=MyCustomConfig
)
```

Once registered, your custom "redis" transport can be used within any configuration file just like the built-in ones.
