### Full Froodi Example Source: https://github.com/desiders/froodi/blob/master/README.md A complete example demonstrating the setup, registration, and resolution of dependencies within different scopes in a Rust application using Froodi. ```rust use froodi::{ Container, DefaultScope::{App, Request}, Inject, boxed, instance, registry, }; use std::sync::Arc; trait Greeter: Send + Sync { fn greet(&self, name: &str) -> String; } #[derive(Clone)] struct Config { greeting: String, } struct GreetingService { greeting: String, } impl Greeter for GreetingService { fn greet(&self, name: &str) -> String { format!("{}, {name}!", self.greeting) } } struct WelcomeHandler { greeter: Arc>, } impl WelcomeHandler { fn handle(&self, name: &str) { println!("{}", self.greeter.greet(name)); } } fn build_container(cfg: Config) -> Container { Container::new(registry! { provide(App, instance(cfg)), scope(Request) [ provide(|Inject(cfg): Inject| { Ok(boxed!(GreetingService { greeting: cfg.greeting.clone() }; Greeter)) }), provide(|Inject(greeter)| { Ok(WelcomeHandler { greeter }) }), ], }) } fn main() { let app_container = build_container(Config { greeting: "Hello".to_owned(), }); let request_container = app_container.clone().enter_build().unwrap(); let handler = request_container.get_transient::().unwrap(); handler.handle("froodi"); let config = request_container.get::().unwrap(); assert_eq!(config.greeting, "Hello"); request_container.close(); app_container.close(); } ``` -------------------------------- ### Full Froodi Example Source: https://github.com/desiders/froodi/blob/master/froodi/README.md A complete example demonstrating the integration of type definitions, container building, dependency resolution, and cleanup within a Rust application using Froodi. ```rust use froodi::{ Container, DefaultScope::{App, Request}, Inject, boxed, instance, registry, }; use std::sync::Arc; trait Greeter: Send + Sync { fn greet(&self, name: &str) -> String; } #[derive(Clone)] struct Config { greeting: String, } struct GreetingService { greeting: String, } impl Greeter for GreetingService { fn greet(&self, name: &str) -> String { format!("{}, {name}!", self.greeting) } } struct WelcomeHandler { greeter: Arc>, } impl WelcomeHandler { fn handle(&self, name: &str) { println!("{}", self.greeter.greet(name)); } } fn build_container(cfg: Config) -> Container { Container::new(registry! { provide(App, instance(cfg)), scope(Request) [ provide(|Inject(cfg): Inject| { Ok(boxed!(GreetingService { greeting: cfg.greeting.clone() }; Greeter)) }), provide(|Inject(greeter)| { Ok(WelcomeHandler { greeter }) }), ], }) } fn main() { let app_container = build_container(Config { greeting: "Hello".to_owned(), }); let request_container = app_container.clone().enter_build().unwrap(); let handler = request_container.get_transient::().unwrap(); handler.handle("froodi"); let config = request_container.get::().unwrap(); assert_eq!(config.greeting, "Hello"); request_container.close(); app_container.close(); } ``` -------------------------------- ### Custom Framework Integration Example Source: https://github.com/desiders/froodi/blob/master/_autodocs/framework-integrations.md Illustrates how to create extractors for a custom framework to retrieve injected dependencies from request-local storage. This example assumes a hypothetical framework with request extensions. ```rust use froodi::{Container, Inject, InjectTransient, ResolveErrorKind}; struct RequestContext { container: Container, } // Pseudo-code for extractor impl FromRequest for Inject where T: Send + Sync + 'static, { type Rejection = InjectError; async fn from_request(req: &mut Request) -> Result { let context = req.extensions() .get::() .ok_or(InjectError::ContainerNotFound)?; context.container.get::() .map_err(|e| InjectError::Resolve(e)) } } ``` -------------------------------- ### Basic Sync Auto-Registration Example Source: https://github.com/desiders/froodi/blob/master/_autodocs/auto-registration.md Demonstrates basic synchronous auto-registration of `Database` and `UserRepository` using the `#[injectable]` macro and `provide_auto_registries()`. ```rust use froodi::{registry, DefaultScope, Inject, Container}; use froodi_auto::injectable; #[injectable] pub struct Database { connection: String, } #[injectable] pub struct UserRepository { db: std::sync::Arc, } fn main() -> Result<(), Box> { let registry = registry!() .provide_auto_registries(); let container = Container::new(registry); let repo = container.get::()?; Ok(()) } ``` -------------------------------- ### Basic Froodi Setup Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Demonstrates the fundamental steps of creating a registry, building a container, resolving dependencies, and cleaning up resources in froodi. ```rust use froodi::{Container, DefaultScope, Inject, instance, registry}; // 1. Create a registry let reg = registry! { scope(DefaultScope::App) [ provide(instance("config")), provide(|| Ok(42i32)), ] }; // 2. Create a container let container = Container::new(reg); // 3. Resolve dependencies let config = container.get::<&str>().unwrap(); let number = container.get::().unwrap(); // 4. Clean up container.close(); ``` -------------------------------- ### Example Usage of `boxed!` Macro Source: https://github.com/desiders/froodi/blob/master/_autodocs/registry-and-factories.md Demonstrates creating a boxed trait object for `PostgresRepository` with `Repository`, `Send`, and `Sync` traits within a Froodi registry. ```rust use froodi::{boxed, registry, DefaultScope, Inject}; trait Repository { fn find(&self) -> String; } struct PostgresRepository; impl Repository for PostgresRepository { fn find(&self) -> String { "from postgres".to_string() } } let reg = registry! { scope(DefaultScope::App) [ provide(|| { Ok::<_, froodi::InstantiateErrorKind>( boxed!(PostgresRepository; Repository + Send + Sync) ) }), provide(|Inject(repo): Inject>| { Ok(repo.find()) }), ]; }; ``` -------------------------------- ### Dptree Setup with Dependency Injection Source: https://github.com/desiders/froodi/blob/master/_autodocs/framework-integrations.md Set up a handler factory for Dptree integration by creating a container with registered dependencies. The `provide` function is used to register values that can be injected. ```rust use froodi::{Container, DefaultScope, dptree::handler_factory, registry}; let container = Container::new(registry! { scope(DefaultScope::App) [ provide(|| Ok("bot_token")), ] }); let factory = handler_factory(container, DefaultScope::Request); ``` -------------------------------- ### Container::new_with_start_scope Source: https://github.com/desiders/froodi/blob/master/_autodocs/container.md Creates a new container with an explicitly specified start scope, allowing you to initialize at optional scopes like `Runtime` or `Session`. ```APIDOC ## Container::new_with_start_scope ### Description Creates a new container with an explicitly specified start scope, allowing you to initialize at optional scopes like `Runtime` or `Session`. ### Method `Container::new_with_start_scope(registry: Registry, scope: S) -> Container` ### Parameters #### Path Parameters - **registry** (Registry) - Required - The dependency registry - **scope** (S) - Required - The scope to start at, implementing the `Scope` trait ### Returns `Container` - A new container initialized at the specified scope. ### Panics - If the registry is empty - If the specified scope is not found in the registry ### Example ```rust use froodi::{Container, DefaultScope, registry}; let container = Container::new_with_start_scope( registry! { scope(DefaultScope::Runtime) [ provide(|| Ok(())) ], scope(DefaultScope::App) [ provide(|| Ok(())) ], }, DefaultScope::Runtime, ); ``` ``` -------------------------------- ### Async Container Error Handling Example Source: https://github.com/desiders/froodi/blob/master/_autodocs/async-containers.md Demonstrates how to safely get a value from an async container and handle potential ResolveErrorKind, specifically the NoInstantiator error. ```rust use froodi::{ResolveErrorKind, async_impl::Container}; async fn safe_get(container: &Container) -> Result { match container.get::().await { Ok(val) => Ok(*val), Err(ResolveErrorKind::NoInstantiator { .. }) => { eprintln!("Type not registered"); Err(ResolveErrorKind::NoInstantiator { type_info: froodi::TypeInfo::of::() }) } Err(e) => Err(e), } } ``` -------------------------------- ### Create Async Container with Sync Registry Source: https://github.com/desiders/froodi/blob/master/_autodocs/async-containers.md Instantiate an async container using a combined sync and async registry. This constructor starts from the first non-skipped scope. ```rust use froodi::{async_impl::Registry, DefaultScope, registry}; let async_reg = Registry::new_with_default_entries(); let container = froodi::async_impl::Container::new( froodi::async_impl::RegistryWithSync { registry: async_reg, sync: registry!(), } ); ``` -------------------------------- ### Telers Setup with Dependency Injection Source: https://github.com/desiders/froodi/blob/master/_autodocs/framework-integrations.md Set up a handler factory for Telers integration by creating a container with registered dependencies. The `provide` function is used to register values that can be injected. ```rust use froodi::{Container, DefaultScope, telers::handler_factory, registry}; let container = Container::new(registry! { scope(DefaultScope::App) [ provide(|| Ok("bot_config")), ] }); let factory = handler_factory(container, DefaultScope::Request); ``` -------------------------------- ### Injecting Multiple Dependencies Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Example of a closure that accepts multiple dependencies injected by froodi. ```rust |Inject(a): Inject, Inject(b): Inject| { Ok((a, b)) } ``` -------------------------------- ### Create a new Container with a specific start scope Source: https://github.com/desiders/froodi/blob/master/_autodocs/container.md Use `Container::new_with_start_scope` to initialize the container at an explicitly chosen scope, such as `Runtime` or `Session`. The specified scope must exist within the provided registry. ```rust use froodi::{Container, DefaultScope, registry}; let container = Container::new_with_start_scope( registry! { scope(DefaultScope::Runtime) [ provide(|| Ok(())) ], scope(DefaultScope::App) [ provide(|| Ok(())) ], }, DefaultScope::Runtime, ); ``` -------------------------------- ### Context::new() Source: https://github.com/desiders/froodi/blob/master/_autodocs/finalizers-and-context.md Creates a new, empty context instance. This is the starting point for building request-specific data structures. ```APIDOC ## Context::new() ### Description Creates an empty context. ### Method `Context::new() -> Context` ### Example ```rust use froodi::Context; let ctx = Context::new(); assert_eq!(ctx.map.len(), 0); ``` ``` -------------------------------- ### Container::new Source: https://github.com/desiders/froodi/blob/master/_autodocs/async-containers.md Creates an async container starting at the first non-skipped scope. It combines both synchronous and asynchronous registries. ```APIDOC ## Container::new ### Description Creates an async container starting at the first non-skipped scope. It combines both synchronous and asynchronous registries. ### Signature ```rust pub fn new(registry: RegistryWithSync) -> Self ``` ### Parameters #### Path Parameters - **registry** (RegistryWithSync) - Required - Combined sync + async registry ### Example ```rust use froodi::{async_impl::Registry, DefaultScope, registry}; let async_reg = Registry::new_with_default_entries(); let container = froodi::async_impl::Container::new( froodi::async_impl::RegistryWithSync { registry: async_reg, sync: registry!(), } ); ``` ``` -------------------------------- ### Axum Dependency Injection Setup Source: https://github.com/desiders/froodi/blob/master/_autodocs/framework-integrations.md Configure Axum middleware to inject a request-scoped container. Ensure the 'axum' feature is enabled for Froodi. ```rust use froodi::{Container, DefaultScope, axum::middleware, registry}; use axum::{Router, routing::get}; let app_container = Container::new(registry! { scope(DefaultScope::App) [ provide(|| Ok("app_config")), ] }); let middleware = middleware::container_layer( app_container, DefaultScope::Request, // HTTP scope DefaultScope::Request, // WebSocket scope ); let router = Router::new() .route("/", get(handler)) .layer(middleware); ``` -------------------------------- ### Return InstantiateErrorKind from Factory Source: https://github.com/desiders/froodi/blob/master/_autodocs/errors.md Example of a factory function returning a Result with `InstantiateErrorKind`, demonstrating error creation using `anyhow::anyhow`. ```rust use froodi::{registry, DefaultScope, InstantiateErrorKind}; let reg = registry! { scope(DefaultScope::App) [ provide(|| { Err::( anyhow::anyhow!("Database connection failed").into() ) }), ] }; ``` -------------------------------- ### Async Auto-Registration with Sync Trait Source: https://github.com/desiders/froodi/blob/master/_autodocs/auto-registration.md Provides an example of the `AutoRegistriesWithSync` trait and its implementation for combining synchronous and asynchronous registries. ```rust pub trait AutoRegistriesWithSync { fn provide_auto_registries_with_sync(self) -> Self; } impl AutoRegistriesWithSync for RegistryWithSync { fn provide_auto_registries_with_sync(self) -> Self { let registry = self.registry.provide_auto_registries(); let sync = self.sync.provide_auto_registries(); Self { registry, sync } } } ``` -------------------------------- ### Explicitly Defining Scopes in Froodi Source: https://github.com/desiders/froodi/blob/master/README.md Demonstrates how to create a container with specific starting scopes like Runtime, Session, and Request. Use `Container::new_with_start_scope` to specify the initial scope and `enter().with_scope().build()` for subsequent scope manipulation. ```rust use froodi::{Container, DefaultScope::{Request, Runtime, Session}, registry}; let runtime_container = Container::new_with_start_scope(registry! { scope(Runtime) [ provide(|| Ok(()))], scope(Session) [ provide(|| Ok(((), ())))], scope(Request) [ provide(|| Ok(((), (), ()))), ], }, Runtime); let session_container = runtime_container.clone().enter().with_scope(Session).build().unwrap(); ``` -------------------------------- ### Container::new Source: https://github.com/desiders/froodi/blob/master/_autodocs/container.md Creates a new container starting at the first non-skipped scope in the registry hierarchy. For the default scope chain, this typically begins at `App` scope, automatically skipping the optional `Runtime` scope. ```APIDOC ## Container::new ### Description Creates a new container starting at the first non-skipped scope in the registry hierarchy. For the default scope chain, this typically begins at `App` scope, automatically skipping the optional `Runtime` scope. ### Method `Container::new(registry: Registry) -> Container` ### Parameters #### Path Parameters - **registry** (Registry) - Required - The dependency registry containing all instantiator definitions and scope mappings ### Returns `Container` - A new container initialized at the first non-skipped scope with full access to its scope and child scopes. ### Panics - If the registry contains no scopes - If there are no child scopes after the root - If all scopes except the first are skipped by default ### Example ```rust use froodi::{Container, DefaultScope, Inject, instance, registry}; let container = Container::new(registry! { scope(DefaultScope::App) [ provide(instance("app_config")), ] }); let config = container.get::<&str>().unwrap(); ``` ``` -------------------------------- ### Create a new Container with default scope Source: https://github.com/desiders/froodi/blob/master/_autodocs/container.md Use `Container::new` to create a container starting at the first non-skipped scope in the registry, typically `App` scope. Ensure the registry is valid and contains necessary scopes. ```rust use froodi::{Container, DefaultScope, Inject, instance, registry}; let container = Container::new(registry! { scope(DefaultScope::App) [ provide(instance("app_config")), ] }); let config = container.get::<&str>().unwrap(); ``` -------------------------------- ### Auto-Registering Dependencies with froodi-auto Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Illustrates how to use the `froodi-auto` crate to automatically register dependencies marked with the `#[injectable]` attribute. This simplifies the setup of your dependency injection container. ```rust use froodi::{Container, registry}; use froodi_auto::{injectable, AutoRegistries}; #[injectable] struct Database { connection: String, } #[injectable] struct Service { db: std::sync::Arc, } fn build() -> Container { let registry = registry!() .provide_auto_registries(); Container::new(registry) } ``` -------------------------------- ### Test Handlers with Dependency Injection Source: https://github.com/desiders/froodi/blob/master/_autodocs/framework-integrations.md Write tests for handlers that utilize dependency injection. This example demonstrates setting up a container with a registered instance and simulating a handler call to verify the injected dependency. ```rust #[tokio::test] async fn test_handler_with_injection() -> Result<(), Box> { use froodi::{Container, DefaultScope, instance, registry}; let container = Container::new(registry! { scope(DefaultScope::Request) [ provide(instance("test_token".to_string())), ] }); // Simulate handler call let request = container.clone().enter_build()?; let token = request.get::()?; assert_eq!(*token, "test_token"); Ok(()) } ``` -------------------------------- ### Froodi Scope Access Pattern Example Source: https://github.com/desiders/froodi/blob/master/_autodocs/scopes.md Demonstrates how a child scope can access dependencies from a parent scope, and how a parent scope cannot access dependencies from a child scope. Ensure the `froodi` crate is included in your project. ```rust use froodi::{Container, DefaultScope, Inject, registry, ResolveErrorKind}; let app = Container::new(registry! { scope(DefaultScope::App) [ provide(|| Ok(42i32)) ], scope(DefaultScope::Request) [ provide(|| Ok("request_str")) ], }); let request = app.clone().enter_build()?; // ✓ Request can access App-scoped int let int = request.get::()?; // ✗ App cannot access Request-scoped string let result = app.get::<&str>(); assert!(matches!(result, Err(ResolveErrorKind::NoAccessible { .. }))); ``` -------------------------------- ### Test with Fresh Configuration State Source: https://github.com/desiders/froodi/blob/master/_autodocs/configuration.md Use this snippet to create a test-specific configuration with caching disabled for provides. This ensures that each test starts with a clean state, preventing interference between tests. ```rust #[cfg(test)] mod tests { use froodi::{Container, DefaultScope, Config, instance, registry}; #[test] fn test_with_fresh_state() { let test_config = registry! { scope(DefaultScope::App) [ provide( instance(TestCounter(0)), config = Config { cache_provides: false }, // Fresh state ), ] }; let container = Container::new(test_config); // Each test gets fresh state } } ``` -------------------------------- ### Using Inject in Factory Functions Source: https://github.com/desiders/froodi/blob/master/_autodocs/dependency-injection.md Demonstrates how to use the Inject wrapper within factory functions to declare and provide dependencies to the Froodi container. This example shows providing a Database instance and then a UserService that depends on the Database. ```rust use froodi::{Container, DefaultScope, Inject, instance, registry}; struct Database { connection_string: String, } struct UserService { db: std::sync::Arc, } let container = Container::new(registry! { scope(DefaultScope::App) [ provide(instance(Database { connection_string: "postgres://...".to_string(), })), provide(|Inject(db): Inject| { Ok(UserService { db }) }), ] }); let service = container.get::().unwrap(); ``` -------------------------------- ### Registering Dependencies with Finalizers in Froodi Source: https://github.com/desiders/froodi/blob/master/README.md Shows how to register a dependency with a finalizer function that executes when the owning scope is closed. The `finalizer` argument in `provide` is used for this purpose. The example uses `AppState` and prints a message upon finalization. ```rust use froodi::{ Container, DefaultScope::App, instance, registry, }; #[derive(Clone)] struct AppState; let container = Container::new_with_start_scope( registry! { provide(App, instance(AppState), finalizer = |_dep| println!("AppState finalized")), }, App, ); let _state = container.get::().unwrap(); container.close(); ``` -------------------------------- ### Provide Full Syntax Source: https://github.com/desiders/froodi/blob/master/_autodocs/registry-and-factories.md Demonstrates the full syntax of the `provide` function, showing optional parameters. ```rust provide( factory, config = Config { cache_provides: true }, finalizer = |dependency| { /* cleanup */ }, ) ``` -------------------------------- ### Resolve and Cache Dependency with get() Source: https://github.com/desiders/froodi/blob/master/_autodocs/container.md Use `get()` to resolve a dependency that will be cached within the current scope. Suitable for singleton-like behavior per scope. Ensure the dependency type implements `SendSafety`, `SyncSafety`, and `'static`. ```rust pub fn get( &self, ) -> Result, ResolveErrorKind> ``` ```rust use froodi::{Container, DefaultScope, Inject, instance, registry}; let container = Container::new(registry! { scope(DefaultScope::App) [ provide(instance(42i32)), ] }); let value = container.get::().unwrap(); assert_eq!(*value, 42); ``` -------------------------------- ### Create Container and Enter Request Scope Source: https://github.com/desiders/froodi/blob/master/README.md Instantiate the container with your configuration and use `enter_build()` to move into the next scope, typically the request scope. ```rust let app_container = build_container(Config { greeting: "Hello".to_owned(), }); let request_container = app_container.clone().enter_build().unwrap(); ``` -------------------------------- ### Mocking Dependencies for Testing Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Demonstrates how to set up a test container with mock dependencies using `instance` and `provide`. This allows for isolated testing of components without relying on actual external services. ```rust #[cfg(test)] mod tests { use froodi::{Container, DefaultScope, instance, registry}; struct MockDatabase; #[test] fn test_service() { let test_container = Container::new(registry! { scope(DefaultScope::App) [ provide(instance(MockDatabase)), ] }); let _mock = test_container.get::().unwrap(); } } ``` -------------------------------- ### Create Container and Enter Scope Source: https://github.com/desiders/froodi/blob/master/froodi/README.md Instantiate the container with your configuration and enter the next available scope, typically the `Request` scope, using `enter_build()`. ```rust let app_container = build_container(Config { greeting: "Hello".to_owned(), }); let request_container = app_container.clone().enter_build().unwrap(); ``` -------------------------------- ### async_impl::Container Source: https://github.com/desiders/froodi/blob/master/_autodocs/types-reference.md Async-compatible container with an embedded sync container. Its `get()` and `get_transient()` methods return futures. ```APIDOC ## async_impl::Container ### Description Async-compatible container with embedded sync container. Its `get()` and `get_transient()` methods return futures. ### Available with `async` feature ### Source `froodi/src/async_impl/container.rs:25-30` ``` -------------------------------- ### Resolve Dependencies Source: https://github.com/desiders/froodi/blob/master/README.md Use `get_transient::()` to resolve a new instance of a dependency and `get::()` for a scoped shared dependency. ```rust let handler = request_container.get_transient::().unwrap(); handler.handle("froodi"); let config = request_container.get::().unwrap(); assert_eq!(config.greeting, "Hello"); ``` -------------------------------- ### Provide with Configuration Options Source: https://github.com/desiders/froodi/blob/master/_autodocs/registry-and-factories.md Shows how to use the `config` parameter with `provide` to control caching behavior. Set `cache_provides` to `false` for fresh instances each time. ```rust use froodi::{Config, registry, DefaultScope, instance}; let reg = registry! { scope(DefaultScope::App) [ // Cached (default) provide(instance(42)), // Explicitly cached provide( instance(42), config = Config { cache_provides: true } ), // Not cached (fresh instance each time) provide( || Ok::(rand::random()), config = Config { cache_provides: false } ), ] }; ``` -------------------------------- ### Create Basic Async Factory Source: https://github.com/desiders/froodi/blob/master/_autodocs/async-containers.md Demonstrates the creation of a simple asynchronous factory that returns a string. Ensure the `froodi::async_impl::Registry` is imported. ```rust use froodi::{async_impl::Registry, DefaultScope}; let registry = Registry::new_with_default_entries(); // Async factory let async_factory = |async move | -> Result { Ok("async value".to_string()) }; ``` -------------------------------- ### Creating and Populating Context Source: https://github.com/desiders/froodi/blob/master/_autodocs/finalizers-and-context.md Demonstrates how to create a new Context and insert various data types into it. ```rust use froodi::Context; let mut context = Context::new(); context.insert("request_id".to_string()); context.insert(42i32); context.insert(vec![1, 2, 3]); ``` -------------------------------- ### Create Registry with Default Entries Source: https://github.com/desiders/froodi/blob/master/_autodocs/registry-and-factories.md Initializes a new `Registry` with standard scopes (Runtime to Step) and no custom entries. Requires the `froodi::Registry` import. ```rust use froodi::Registry; let registry = Registry::new_with_default_entries(); ``` -------------------------------- ### Instance Helper for Pre-constructed Values Source: https://github.com/desiders/froodi/blob/master/_autodocs/registry-and-factories.md Demonstrates using the `instance()` helper to convert a pre-constructed value into a factory. This is useful for providing values that are already initialized. ```rust use froodi::{instance, registry, DefaultScope}; struct Config { db_url: String, } let config = Config { db_url: "postgres://...".to_string(), }; let reg = registry! { scope(DefaultScope::App) [ provide(instance(config)), ] }; ``` -------------------------------- ### Configuration with Finalizers Source: https://github.com/desiders/froodi/blob/master/_autodocs/configuration.md Shows how to combine `Config` with a `finalizer` function in the `provide` macro. The finalizer is executed when the provided value is dropped. ```rust use froodi::{registry, DefaultScope, Config}; let reg = registry! { scope(DefaultScope::App) [ provide( || Ok(vec![1, 2, 3]), config = Config { cache_provides: true }, finalizer = |vec| { println!("Vector dropped: {} items", vec.len()); }, ), ] }; ``` -------------------------------- ### Async Handler for Request Processing Source: https://github.com/desiders/froodi/blob/master/_autodocs/async-containers.md An example of an asynchronous handler function that uses the `Container` to resolve dependencies and perform operations. Dependencies are resolved using `.await`. ```rust use froodi::async_impl::Container; async fn handle_request(container: Container) -> Result> { let database = container.get::().await?; let user_id = container.get::().await?; let user = database.find_user(*user_id).await?; Ok(format!("Found user: {:?}", user)) } struct Database; struct UserId(u32); ``` -------------------------------- ### Create and Build Child Container with enter_build() Source: https://github.com/desiders/froodi/blob/master/_autodocs/container.md Use `enter_build()` as a shortcut to create and build a child container for the next non-skipped scope. This method combines the functionality of `enter()` and `build()`. ```rust pub fn enter_build(self) -> Result ``` ```rust let app = Container::new(registry); let request = app.clone().enter_build()?; ``` -------------------------------- ### Combining Sync and Async Registries Source: https://github.com/desiders/froodi/blob/master/_autodocs/async-containers.md Demonstrates how to create a combined registry that includes both synchronous and asynchronous dependencies. The `Container` can then resolve from both. ```rust use froodi::{async_impl, DefaultScope, Inject, instance, registry}; // Sync registry let sync_registry = registry! { scope(DefaultScope::App) [ provide(instance(42i32)), ] }; // Async registry (would be built similarly) let async_registry = async_impl::Registry::new_with_default_entries(); // Combined let combined = async_impl::RegistryWithSync { registry: async_registry, sync: sync_registry, }; let container = async_impl::Container::new(combined); // Both sync and async dependencies available let sync_val = container.get::().await?; ``` -------------------------------- ### Moving Between Scopes Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Demonstrates how to navigate and create new containers within different scopes, including the default application and request scopes. ```rust use froodi::{Container, DefaultScope, registry}; let app = Container::new(registry! { scope(DefaultScope::App) [ provide(|| Ok("app")) ], scope(DefaultScope::Request) [ provide(|| Ok("request")) ], }); // Enter next scope let request = app.clone().enter_build().unwrap(); // Enter specific scope let specific = app.clone() .enter() .with_scope(DefaultScope::Request) .build() .unwrap(); request.close(); ``` -------------------------------- ### Handling Instantiator Error in Rust Source: https://github.com/desiders/froodi/blob/master/_autodocs/errors.md Shows how to catch `ResolveErrorKind::Instantiator` errors, which occur when dependency resolution or factory execution fails. This example demonstrates a scenario where a factory returns an error. ```rust use froodi::{Container, DefaultScope, Inject, registry}; let container = Container::new(registry! { scope(DefaultScope::App) [ provide(|| Err::(anyhow::anyhow!("Factory failed"))), provide(|Inject(_num): Inject| { Ok("never reached".to_string()) }), ] }); match container.get::() { Err(ResolveErrorKind::Instantiator(_)) => { println!("Instantiation error"); } _ => {} } ``` -------------------------------- ### Combine Auto-Registration with Manual Registration Source: https://github.com/desiders/froodi/blob/master/_autodocs/auto-registration.md Demonstrates how to mix automatic component registration with manual configuration within a single registry. The `provide_auto_registries()` method is called after defining manual providers. ```rust use froodi::{registry, DefaultScope, instance, Inject}; use froodi_auto::AutoRegistries; #[froodi_auto::injectable] struct AutoComponent; struct ManualComponent { auto: std::sync::Arc, } let combined = registry! { scope(DefaultScope::App) [ provide(instance("manual_config")), provide(|Inject(auto): Inject>| { Ok(ManualComponent { auto }) }), ] } .provide_auto_registries(); let container = froodi::Container::new(combined); ``` -------------------------------- ### Create Empty Registry Source: https://github.com/desiders/froodi/blob/master/_autodocs/registry-and-factories.md Initializes an empty `Registry` using the `registry!` macro with no arguments. ```rust let reg = registry!(); ``` -------------------------------- ### Define Registry with Direct Provide Statements Source: https://github.com/desiders/froodi/blob/master/_autodocs/registry-and-factories.md Creates a registry by directly specifying the scope and instance for each `provide` statement, without using explicit scope blocks. ```rust let reg = registry! { provide(DefaultScope::App, instance(42)), provide(DefaultScope::Request, instance("hello")), }; ``` -------------------------------- ### Implementing Custom Scope Enum Source: https://github.com/desiders/froodi/blob/master/_autodocs/scopes.md Example of implementing the Scope trait for a custom enum. This includes deriving necessary traits and implementing the required `name` and `priority` methods, as well as the `From` trait for `ScopeData` conversion. ```rust use froodi::{Scope, ScopeData}; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] enum CustomScope { Global, Tenant, Request, } impl Scope for CustomScope { fn name(&self) -> &'static str { match self { Self::Global => "global", Self::Tenant => "tenant", Self::Request => "request", } } fn priority(&self) -> u8 { match self { Self::Global => 0, Self::Tenant => 1, Self::Request => 2, } } } impl From for ScopeData { fn from(scope: CustomScope) -> Self { ScopeData { priority: scope.priority(), name: scope.name(), is_skipped_by_default: false, } } } ``` -------------------------------- ### Explicitly Setting Cache Provides Source: https://github.com/desiders/froodi/blob/master/_autodocs/configuration.md Demonstrates setting `cache_provides` to `true` and `false` explicitly within the `provide` macro. ```rust use froodi::{registry, DefaultScope, Config}; let reg = registry! { scope(DefaultScope::App) [ // Explicit cache_provides true provide( || Ok(42i32), config = Config { cache_provides: true } ), // Explicit cache_provides false provide( || Ok("fresh"), config = Config { cache_provides: false } ), ] }; ``` -------------------------------- ### Closure-Based Factories with Multiple Dependencies Source: https://github.com/desiders/froodi/blob/master/_autodocs/registry-and-factories.md Illustrates a closure-based factory that takes both an i32 and a String dependency and returns them as a tuple. ```rust provide(|Inject(num): Inject, Inject(str): Inject| { Ok((num, str)) }) ``` -------------------------------- ### Define Application and Request Types Source: https://github.com/desiders/froodi/blob/master/README.md Define your application's configuration, services, and handlers. Ensure types that need to be shared across requests implement `Clone` and `Send + Sync` if necessary. ```rust use std::sync::Arc; trait Greeter: Send + Sync { fn greet(&self, name: &str) -> String; } #[derive(Clone)] struct Config { greeting: String, } struct GreetingService { greeting: String, } impl Greeter for GreetingService { fn greet(&self, name: &str) -> String { format!("{}, {name}!", self.greeting) } } struct WelcomeHandler { greeter: Arc>, } impl WelcomeHandler { fn handle(&self, name: &str) { println!("{}", self.greeter.greet(name)); } } ``` -------------------------------- ### Async Support Configuration Source: https://github.com/desiders/froodi/blob/master/_autodocs/INDEX.md Enables async factories, async containers, and async dependency resolution for asynchronous operations. ```toml froodi = { version = "1", features = ["async"] } ``` -------------------------------- ### container.enter_build() Source: https://github.com/desiders/froodi/blob/master/_autodocs/container.md Convenience method combining `enter()` and `build()`. Creates a child container at the next non-skipped scope. ```APIDOC ## container.enter_build() ### Description Convenience method combining `enter()` and `build()`. Creates a child container at the next non-skipped scope. ### Method POST (conceptual) ### Endpoint N/A (Instance Method) ### Returns `Result` - A new child container or an error if scope creation fails. ### Errors - `ScopeErrorKind::NoChildRegistries`: No child scopes exist - `ScopeErrorKind::NoNonSkippedRegistries`: No non-skipped child scopes exist ### Example ```rust let app = Container::new(registry); let request = app.clone().enter_build()?; ``` ``` -------------------------------- ### Froodi Inject Error Type Source: https://github.com/desiders/froodi/blob/master/_autodocs/framework-integrations.md Defines the standard error type used by froodi for injection failures. It includes variants for container not found and resolution errors, and provides methods to get the status code and error body. ```rust #[derive(Debug, thiserror::Error)] pub enum InjectErrorKind { #[error("Container not found in extensions")] ContainerNotFound, #[error(transparent)] Resolve(ResolveErrorKind), } impl InjectErrorKind { fn status(&self) -> StatusCode { StatusCode::INTERNAL_SERVER_ERROR } fn body(&self) -> String { self.to_string() } } ``` -------------------------------- ### Auto-registering Services in Large Applications Source: https://github.com/desiders/froodi/blob/master/_autodocs/auto-registration.md Use the `#[injectable]` macro to mark types for automatic registration. This approach scales well for applications with many services. ```rust // src/services/mod.rs use froodi_auto::injectable; #[injectable] pub struct UserService { ... } #[injectable] pub struct OrderService { ... } #[injectable] pub struct PaymentService { ... } ``` ```rust // src/main.rs use froodi::Container; use froodi_auto::AutoRegistries; fn build_container() -> Container { let registry = froodi::registry!() .provide_auto_registries(); Container::new(registry) } ``` -------------------------------- ### Handling NoAccessible Scope Error in Rust Source: https://github.com/desiders/froodi/blob/master/_autodocs/errors.md Illustrates handling the `ResolveErrorKind::NoAccessible` error, which arises when attempting to access a dependency from a scope narrower than its registration scope. This example shows accessing a `Request` scoped dependency from `App` scope. ```rust use froodi::{Container, DefaultScope, registry, ResolveErrorKind}; let container = Container::new(registry! { scope(DefaultScope::App) [], scope(DefaultScope::Request) [ provide(|| Ok(42i32)), ] }); match container.get::() { Err(ResolveErrorKind::NoAccessible { expected_scope_data, actual_scope_data }) => { println!("Can't access {} from {}", expected_scope_data.name, actual_scope_data.name); } _ => {} } ``` -------------------------------- ### Handling Optional Dependencies in Froodi Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Shows how to register and retrieve optional dependencies using Froodi. This allows for flexibility when a dependency might not always be present. ```rust use froodi::{Container, DefaultScope, registry}; let container = Container::new(registry! { scope(DefaultScope::App) [ provide(|| Ok::, _>(None)), provide(|| Ok::, _>(Some(42))), ] }); let maybe_str = container.get::>().unwrap(); let maybe_int = container.get::>().unwrap(); ``` -------------------------------- ### Web Handler Pattern with Request Scopes in Rust Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Shows how to set up application and request scopes for a web handler pattern. Dependencies like `RequestId` are scoped to individual requests, while `app_config` is available globally. ```rust use froodi::{Container, DefaultScope, Inject, registry}; struct RequestId(String); struct Handler; fn build_container() -> Container { Container::new(registry! { scope(DefaultScope::App) [ provide(instance("app_config")), ], scope(DefaultScope::Request) [ provide(|| Ok(RequestId("123".to_string()))), provide(|Inject(id): Inject| { Ok(Handler) }), ] }) } fn handle_request(app_container: Container) { let request_container = app_container.clone().enter_build().unwrap(); let handler = request_container.get::().unwrap(); request_container.close(); } ``` -------------------------------- ### Using Trait Objects with `boxed!` in Froodi Source: https://github.com/desiders/froodi/blob/master/README.md Illustrates how to provide a dependency as a trait object using the `boxed!` macro. This is useful when you need to abstract over concrete types. The example registers a `GreetingService` as a `Greeter` trait object within the `Request` scope. ```rust use froodi::{Inject, boxed, registry}; use froodi::DefaultScope::Request; trait Greeter { fn greet(&self) -> &'static str; } struct GreetingService; impl Greeter for GreetingService { fn greet(&self) -> &'static str { "hello" } } struct Handler { greeter: std::sync::Arc>, } let registry = registry! { scope(Request) [ provide(|| Ok(boxed!(GreetingService; Greeter))), provide(|Inject(greeter)| Ok(Handler { greeter })), ]; }; ``` -------------------------------- ### Usage of InjectTransient in Factory Functions Source: https://github.com/desiders/froodi/blob/master/_autodocs/dependency-injection.md Demonstrates how to use `InjectTransient` within factory functions in a Froodi container. This example shows providing a `Logger` at the app scope and `RequestId` and `Handler` at the request scope, with `Handler` depending on transient `Logger` and `RequestId` instances. ```rust use froodi::{Container, DefaultScope, Inject, InjectTransient, registry}; struct Logger; struct RequestId; struct Handler { logger: Logger, request_id: RequestId, } let container = Container::new(registry! { scope(DefaultScope::App) [ provide(|| Ok(Logger)), ], scope(DefaultScope::Request) [ provide(|| Ok(RequestId)), provide(|InjectTransient(logger): InjectTransient, InjectTransient(req_id): InjectTransient| { Ok(Handler { logger, request_id: req_id }) }), ] }); ``` -------------------------------- ### Registering Pre-created Values Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Use `provide(instance(value))` to register a pre-created value with the dependency injection container. ```rust provide(instance(value)) // for pre-created values ``` -------------------------------- ### Registering Computed Values Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Use `provide(|| Ok(value))` to register a value that is computed when requested. ```rust provide(|| Ok(value)) // for computed values ``` -------------------------------- ### Async Container Usage with Mixed Registries Source: https://github.com/desiders/froodi/blob/master/_autodocs/auto-registration.md Demonstrates building an asynchronous container that combines both async and sync registries using `RegistryWithSync`. ```rust use froodi_auto::injectable; use froodi::async_impl::{Container, RegistryWithSync, Registry}; #[injectable] pub struct AsyncDatabase { pool: String, } fn build_container() -> Container { let async_registry = Registry::new_with_default_entries() .provide_auto_registries(); let sync_registry = froodi::registry!() .provide_auto_registries(); let combined = RegistryWithSync { registry: async_registry, sync: sync_registry, }; Container::new(combined) } ``` -------------------------------- ### Create Child Container Builder with enter() Source: https://github.com/desiders/froodi/blob/master/_autodocs/container.md Use `enter()` to initiate the creation of a child container at the next scope level. This method returns a `ChildContainerBuilder` which can be further configured before building the child container. ```rust pub fn enter(self) -> ChildContainerBuilder ``` ```rust use froodi::{Container, DefaultScope, registry}; let app = Container::new(registry! { scope(DefaultScope::App) [ provide(|| Ok(())) ], scope(DefaultScope::Request) [ provide(|| Ok(())) ], }); let request = app.enter().build().unwrap(); ``` -------------------------------- ### Handling Unreachable Dependencies During Registry Creation Source: https://github.com/desiders/froodi/blob/master/_autodocs/errors.md Demonstrates a situation that results in an `UnreachableDependency` error due to a scope mismatch. This code is commented out as it would panic. ```rust // This panics during registry! due to automatic validation // let reg = registry! { // scope(DefaultScope::Request) [ // provide(|Inject(step): Inject| Ok(RequestType(step))), // ], // scope(DefaultScope::Step) [ // provide(|| Ok(StepType)), // ] // }; // error: Unreachable dependency: RequestType (scope Request, priority 3) // depends on StepType (scope Step, priority 5) ``` -------------------------------- ### Provide with Finalizer Source: https://github.com/desiders/froodi/blob/master/_autodocs/registry-and-factories.md Illustrates using the `finalizer` parameter with `provide` to specify cleanup logic. Finalizers execute in LIFO order when the scope closes. ```rust use froodi::{registry, DefaultScope, instance}; use std::sync::Arc; struct Connection { id: u32, } let reg = registry! { scope(DefaultScope::App) [ provide( instance(Connection { id: 1 }), finalizer = |conn| { println!("Closing connection {}", conn.id); }, ), ] }; ``` -------------------------------- ### Register Factories with Froodi Registry Source: https://github.com/desiders/froodi/blob/master/README.md Use the `registry!` macro to define how dependencies are provided for different scopes. `App` scope is for application-wide singletons, and `Request` scope is for dependencies created per request. ```rust use froodi::{ Container, DefaultScope::{App, Request}, Inject, boxed, instance, registry, }; fn build_container(cfg: Config) -> Container { Container::new(registry! { provide(App, instance(cfg)), scope(Request) [ provide(|Inject(cfg): Inject| { Ok(boxed!(GreetingService { greeting: cfg.greeting.clone() }; Greeter)) }), provide(|Inject(greeter)| { Ok(WelcomeHandler { greeter }) }), ], }) } ``` -------------------------------- ### Creating an Async Container Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Shows how to construct an asynchronous container by combining asynchronous and synchronous registries. This is essential for applications that perform I/O operations within their dependency resolution. ```rust use froodi::async_impl::{Container, RegistryWithSync, Registry}; use froodi::DefaultScope; let async_registry = Registry::new_with_default_entries(); let sync_registry = froodi::registry!(); let container = Container::new(RegistryWithSync { registry: async_registry, sync: sync_registry, }); async fn get_value(c: &Container) -> Result { match c.get::().await { Ok(v) => Ok(*v), Err(e) => Err(e), } } ``` -------------------------------- ### Closure-Based Factories with No Dependencies Source: https://github.com/desiders/froodi/blob/master/_autodocs/registry-and-factories.md Demonstrates a simple closure-based factory that provides an i32 value without any external dependencies. ```rust provide(|| Ok::(42)) ``` -------------------------------- ### Async Factory with Dependency Injection Source: https://github.com/desiders/froodi/blob/master/_autodocs/async-containers.md Shows how to use `Inject` and `InjectTransient` within an async factory to access dependencies. Async operations and computations can be awaited within the factory. ```rust use froodi::{Inject, InjectTransient}; // Async factory with dependencies let async_factory = |Inject(value): Inject| async move { // Can await async operations here let result = async_computation(*value).await?; Ok(result) }; async fn async_computation(n: i32) -> Result { Ok(format!("computed {}", n)) } ``` -------------------------------- ### Synchronously Enter Child Container Builder Source: https://github.com/desiders/froodi/blob/master/_autodocs/async-containers.md Initiates the creation of a child container using a synchronous builder pattern. ```rust pub fn enter(self) -> ChildContainerBuilder ``` -------------------------------- ### Async Feature Enablement Source: https://github.com/desiders/froodi/blob/master/_autodocs/auto-registration.md Shows how to enable the `async` feature for `froodi-auto` in your `Cargo.toml` file. ```toml [dependencies] froodi-auto = { version = "1", features = ["macros", "async"] } ``` -------------------------------- ### Passing Request Data to Context Source: https://github.com/desiders/froodi/blob/master/_autodocs/quick-start.md Demonstrates how to create a context and insert data into it for use within a request scope. This is useful for passing request-specific information to your application's dependency injection system. ```rust use froodi::{Container, Context, DefaultScope, registry}; let mut context = Context::new(); context.insert("request_id".to_string()); context.insert(42i32); let app = Container::new(registry! { scope(DefaultScope::Request) [ provide(|| Ok(())) ] }); let request = app .enter() .with_context(context) .build() .unwrap(); ```