# Premortem Examples

This directory contains runnable examples demonstrating premortem's features.

## Running Examples

Each example is a standalone Rust project. To run an example:

```bash
cd examples/basic
cargo run
```

Or from the workspace root:

```bash
cargo run --example basic
```

## Examples Overview

### [basic](./basic/)

**Minimal configuration loading**

Demonstrates the simplest use case: loading configuration from a TOML file with environment variable overrides and basic validation.

```bash
cd examples/basic
cargo run

# With environment override:
APP_PORT=9000 cargo run
```

### [validation](./validation/)

**Comprehensive validation patterns**

Shows all built-in validators and custom validation patterns including:
- String validators (non_empty, email, url, pattern, length)
- Numeric validators (range, positive, non_zero)
- Collection validators (non_empty_collection, min_items, each)
- Custom validators and cross-field validation

```bash
cd examples/validation
cargo run
```

### [testing](./testing/)

**Configuration testing patterns with MockEnv**

Demonstrates how to test configuration loading without real files or environment variables using the `MockEnv` type.

```bash
cd examples/testing
cargo test
```

### [layered](./layered/)

**Multi-source configuration layering**

Shows environment-specific configuration with multiple layers:
1. Hardcoded defaults (lowest priority)
2. Base configuration file
3. Environment-specific file (development/production)
4. Environment variables (highest priority)

```bash
cd examples/layered

# Development mode (default)
cargo run

# Production mode
APP_ENV=production cargo run
```

### [tracing](./tracing/)

**Value origin debugging**

Demonstrates value tracing to debug where configuration values came from and their override history across sources.

```bash
cd examples/tracing
cargo run
```

### [watch](./watch/)

**Hot reload with file watching**

Demonstrates automatic configuration reloading when files change. Shows:
- Building watched configuration with `build_watched()`
- Subscribing to change events (`Reloaded`, `ReloadFailed`, `SourceChanged`)
- Thread-safe config access via `WatchedConfig<T>`
- Graceful handling of invalid config changes (old config preserved)

```bash
# From workspace root (requires watch feature)
cargo run --example watch --features watch

# Then edit examples/watch/config.toml while running!
# Try setting port = 0 to see validation rejection
```

### [web-server](./web-server/)

**Axum web server integration**

Demonstrates how to use premortem to validate web server configuration before starting an Axum server. Shows:
- Web server configuration patterns (host, port, TLS, timeouts)
- Validation of network-related settings
- Cross-field validation (TLS cert requires TLS key)
- Integration with async runtime
- Graceful error reporting before server startup

```bash
cd examples/web-server
cargo run

# Override with environment variables:
SERVER_PORT=8080 SERVER_HOST=0.0.0.0 cargo run
```

### [yaml](./yaml/)

**YAML configuration file loading**

Demonstrates loading configuration from YAML files. Shows:
- YAML file parsing with nested structures
- Environment variable overrides
- Validation with error accumulation

```bash
# From workspace root (requires yaml feature)
cargo run --example yaml --features yaml

# Override with environment variables:
APP_PORT=9000 cargo run --example yaml --features yaml
```

## Key Concepts Demonstrated

### Error Accumulation

All examples demonstrate premortem's core feature: collecting ALL configuration errors instead of stopping at the first one.

### Source Layering

Later sources override earlier ones:
```rust
Config::<AppConfig>::builder()
    .source(Defaults::from(AppConfig::default()))  // Lowest priority
    .source(Toml::file("config.toml"))
    .source(Env::prefix("APP_"))                   // Highest priority
    .build()
```

### Testable I/O

All I/O is abstracted through `ConfigEnv`, enabling testing with `MockEnv`:
```rust
let env = MockEnv::new()
    .with_file("config.toml", "port = 8080")
    .with_env("APP_HOST", "localhost");

let config = Config::<AppConfig>::builder()
    .source(Toml::file("config.toml"))
    .source(Env::prefix("APP_"))
    .build_with_env(&env)?;
```

### Validation

Use the `Validate` trait or derive macro for validation:
```rust
#[derive(Deserialize, Validate)]
struct Config {
    #[validate(non_empty)]
    host: String,

    #[validate(range(1..=65535))]
    port: u16,
}
```
