async-injector 0.20.0

Reactive dependency injection for Rust.
Documentation
use std::io::{BufRead, BufReader, Write};

use anyhow::{Context, Result};
use async_injector::{Injector, Key, Provider};

#[derive(Provider)]
struct Dependencies {
    #[dependency(tag = "name")]
    name: String,
    #[dependency(tag = "fun")]
    fun: String,
}

async fn greeter(injector: Injector) -> Result<(), Box<dyn std::error::Error>> {
    let mut provider = Dependencies::provider(&injector).await?;
    let Dependencies { name, fun } = provider.wait().await;
    println!("Hi {name}! I see you do \"{fun}\" for fun!");
    Ok(())
}

#[tokio::main]
async fn main() -> Result<()> {
    let injector = Injector::new();
    let greeter = greeter(injector.clone());

    let task = tokio::spawn(async move {
        if let Err(error) = greeter.await {
            println!("Greeter errored: {error}");
        }
    });

    let mut stdout = std::io::stdout();
    let stdin = std::io::stdin();
    let stdin = BufReader::new(stdin.lock());
    let mut lines = stdin.lines();

    let name_key = Key::<String>::tagged("name")?;
    let fun_key = Key::<String>::tagged("fun")?;

    write!(stdout, "What is your name? ")?;
    stdout.flush()?;
    let name = lines.next().context("missing response")??;

    injector.update_key(&name_key, name).await;

    write!(stdout, "What do you do for fun? ")?;
    stdout.flush()?;
    let fun = lines.next().context("missing response")??;
    injector.update_key(&fun_key, fun).await;

    task.await?;

    println!("Bye!");
    Ok(())
}