# cfgmatic-reactive

[![Crates.io](https://img.shields.io/crates/v/cfgmatic-reactive.svg)](https://crates.io/crates/cfgmatic-reactive)
[![Documentation](https://docs.rs/cfgmatic-reactive/badge.svg)](https://docs.rs/cfgmatic-reactive)
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](LICENSE)

Reactive configuration management with subscriptions and change handlers.

## Overview

`cfgmatic-reactive` provides a reactive layer on top of configuration sources,
enabling real-time responses to configuration changes. It implements the
Observer pattern with type-safe handlers and composable queries.

## Features

- **ChangeHandler** - React to configuration changes with custom handlers
- **Subscription** - Subscribe to specific paths, files, or directories
- **Query System** - Filter changes with composable queries (by kind, path, field)
- **Dispatcher** - Event routing to registered handlers
- **ConfigManager** - High-level API for managing reactive configuration

## Installation

Add to your `Cargo.toml`:

```toml
[dependencies]
cfgmatic-reactive = "2.1"
```

### Feature Flags

| Feature   | Description                 | Default |
|-----------|-----------------------------|---------|
| `default` | Basic reactive features     | Yes     |
| `tokio`   | Tokio-based async runtime   | No      |

## Quick Start

### Basic Setup

```rust
use cfgmatic_reactive::prelude::*;

// Create a configuration manager
let manager = ConfigManager::new();

// Subscribe to file changes
manager.subscribe_file("config.toml")?;

// Register a handler
struct LogHandler;
impl Handler for LogHandler {
    fn id(&self) -> &HandlerId {
        static ID: HandlerId = HandlerId::new("log-handler");
        &ID
    }

    fn handle(&self, event: &Event) -> Result<()> {
        println!("Config changed: {:?}", event.path);
        Ok(())
    }
}

manager.register_handler(LogHandler)?;
```

### Using Queries

```rust
use cfgmatic_reactive::prelude::*;

// Create queries to filter events
let mod_query = KindQuery::modifications_only();
let path_query = PathQuery::new("/server/.*");

// Combine queries
let combined = mod_query.and(path_query);
```

### Subscriptions

```rust
use cfgmatic_reactive::prelude::*;

// File subscription
let sub = Subscription::file("/etc/myapp/config.toml");

// Directory subscription
let sub = Subscription::directory("/etc/myapp/config.d");

// Custom subscription with builder
let sub = Subscription::builder()
    .path("/etc/myapp")
    .recursive(true)
    .active(true)
    .build();
```

### Event Dispatching

```rust
use cfgmatic_reactive::prelude::*;

let manager = ConfigManager::new();

// Manually dispatch events
manager.notify_change("/etc/myapp/config.toml")?;
manager.notify_update("/etc/myapp/config.toml")?;
manager.notify_reload("/etc/myapp/config.toml")?;
```

## Architecture

```text
+-------------------------------------------------+
|                 ConfigManager                    |
|          (High-level reactive API)               |
+-------------------------------------------------+
                       |
+-------------------------------------------------+
|                  Dispatcher                      |
|        (Event routing to handlers)               |
+-------------------------------------------------+
                       |
+-------------------+-----------------------------+
|    Handlers       |      Subscriptions          |
| (ChangeHandler)   |   (File, Directory, etc.)   |
+-------------------+-----------------------------+
                       |
+-------------------------------------------------+
|              Query System                        |
|   (KindQuery, PathQuery, FieldQuery, etc.)      |
+-------------------------------------------------+
```

## Event Types

| Event Kind | Description                        |
|------------|------------------------------------|
| `Change`   | Generic configuration change       |
| `Create`   | New configuration created          |
| `Update`   | Existing configuration modified    |
| `Delete`   | Configuration deleted              |
| `Reload`   | Full configuration reload requested|

## Query Combinators

```rust
use cfgmatic_reactive::prelude::*;

// AND combinator - both must match
let query = KindQuery::modifications_only()
    .and(PathQuery::new("/server"));

// OR combinator - either must match
let query = PathQuery::new("/server")
    .or(PathQuery::new("/database"));

// NOT combinator - negates the query
let query = KindQuery::creations_only().not();
```

## API Reference

See the [API documentation](https://docs.rs/cfgmatic-reactive) for full details.

## License

Licensed under either of Apache License, Version 2.0 or MIT license at your
option.
