extended-notify 0.1.3

extended cross-platform filesystem notifications
Documentation
# extended-notify

A filesystem watcher built on [notify](https://crates.io/crates/notify) that adds support for watching paths that don't yet exist, interest-based event filtering, and automatic cleanup via RAII handles.

## Features

- **Watch non-existent paths**: Subscribe to paths before they exist. When the path is created, you'll receive events.
- **Interest filtering**: Specify exactly which event types you care about with fine-grained or coarse-grained filters.
- **RAII handles**: Watches automatically stop when the `Watched` handle is dropped.
- **Polling fallback**: Configurable polling covers edge cases that native filesystem notifications miss.
- **Batched async delivery**: Events are batched and delivered through an async `EventHandler` trait.

## Example

```rust
use extended_notify::{ArcPath, EventBatch, EventHandler, Interest, Watcher};
use anyhow::Result;
use enumflags2::make_bitflags;

struct MyHandler;

impl EventHandler for MyHandler {
    async fn handle_event(&mut self, batch: EventBatch) -> Result<()> {
        for (id, event) in batch.iter() {
            println!("{:?}: {:?}", id, event);
        }
        Ok(())
    }
}

#[tokio::main]
async fn main() -> Result<()> {
    let watcher = WatcherConfigBuilder::default()
        .event_handler(MyHandler)
        .build()?
        .start()?;

    // Watch a path that may or may not exist
    let interest = make_bitflags!(Interest::{Create | Delete | Modify});
    let handle = watcher.add(ArcPath::from("/tmp/watched-file"), interest)?;

    // ... do work ...

    // Watch stops automatically when handle is dropped
    drop(handle);
    Ok(())
}
```

## Interest Filtering

Interests are hierarchical. Subscribing to a parent interest matches all child events:

- `Delete` matches `DeleteFile`, `DeleteFolder`, `DeleteOther`
- `Modify` matches all modification types (data, metadata, rename)
- `Any` matches everything

Special interests:
- `Established`: Synthetic event fired when a watch is first set up
- `Any`: Matches all event types

## How It Works

When you watch a path:

1. If the path exists, it's watched directly via notify
2. If not, the nearest existing ancestor is watched, and polling checks for the path's creation

When a watched path is deleted or renamed away, the watcher automatically transitions back to watching the ancestor and polling. Synthetic `Create` and `Delete` events are generated for these transitions if you've subscribed to them.

## Configuration

```rust
// Adjust polling interval (default: 1s, minimum: 100ms)
watcher.set_poll_interval(Duration::from_secs(5))?;

// Adjust poll batch size (default: 100, 0 disables polling)
watcher.set_poll_batch(50)?;
```

## License

MIT