froodi

Crates.iofroodi
lib.rsfroodi
version1.0.0-beta.6
created_at2025-08-02 08:51:43.3106+00
updated_at2025-09-18 03:16:58.294461+00
descriptionAn ergonomic Rust IoC container
homepage
repositoryhttps://github.com/Desiders/froodi
max_upload_size
id1778553
size291,058
(Desiders)

documentation

README

Froodi - an ergonomic Rust IoC container

Crates.io

Froodi is a lightweight, ergonomic Inversion of Control (IoC) container for Rust that helps manage dependencies with clear scoping and lifecycle management in a simple manner

Features

  • Scoping: Any object can have a lifespan for the entire app, a single request, or even more fractionally
  • Finalization: Some dependencies, like database connections, need not only to be created but also carefully released. Many frameworks lack this essential feature.
  • Ergonomic: Simple API
  • Speed: Dependency resolving as fast as the speed of light thanks to the Rust
  • Integration: The popular frameworks for building applications is supported out of the box (axum, dptree)
  • Safe: 100% safe Rust (no unsafe used)
  • Thread safe: Thread safety enabled by default (thread_safe feature) and can be disabled to use Rc instead of Arc and off Send/Sync requirements

Quickstart

use froodi::{
    Container,
    DefaultScope::{App, Request},
    Inject, InjectTransient, InstantiatorResult, RegistryBuilder, instance,
};

#[derive(Default, Clone)]
struct Config {
    _host: &'static str,
    _port: i16,
    _user: &'static str,
    _password: &'static str,
    _db: &'static str,
}

trait UserRepo {
    fn create_user(&self);
}

struct PostgresUserRepo;

impl UserRepo for PostgresUserRepo {
    fn create_user(&self) {
        todo!()
    }
}

struct CreateUser<R> {
    repo: R,
}

impl<R: UserRepo> CreateUser<R> {
    fn handle(&self) {
        self.repo.create_user();
    }
}

fn init_container(config: Config) -> Container {
    #[allow(clippy::unnecessary_wraps)]
    fn create_user<R>(InjectTransient(repo): InjectTransient<R>) -> InstantiatorResult<CreateUser<R>> {
        Ok(CreateUser { repo })
    }

    let registry = RegistryBuilder::new()
        .provide(instance(config), App)
        .provide(|_config: Inject<Config>| Ok(PostgresUserRepo), Request)
        .provide(create_user::<PostgresUserRepo>, Request);
    Container::new(registry)
}

fn main() {
    let app_container = init_container(Config::default());
    let request_container = app_container.clone().enter_build().unwrap();

    let interactor = request_container.get_transient::<CreateUser<PostgresUserRepo>>().unwrap();
    interactor.handle();

    let _config = request_container.get::<Config>().unwrap();

    request_container.close();
    app_container.close();
}

Examples

  • Sync provide. This example shows how to provide sync dependencies.
  • Async provide. This example shows how to provide async sync dependencies.
  • Sync finalizer. This example shows how to add sync finalizers.
  • Async finalizer. This example shows how to add async finalizers.
  • Boxed dyn provide. This example shows how to provide boxed dyn dependencies.
  • Axum. This example shows how to integrate the framework with Axum library.
  • Dptree. This example shows how to integrate the framework with Dptree library.

You may consider checking out this directory for examples.

Contributing

Contributions are welcome!

License

Apache License, Version 2.0

Commit count: 166

cargo fmt