### Full integration example Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_axum.md A complete example demonstrating module definition, state setup, and handler injection. ```rust use axum::{routing::get, Router}; use axum::extract::FromRef; use shaku::{module, Component, Interface}; use shaku_axum::Inject; use std::net::SocketAddr; use std::sync::Arc; use tokio::net::TcpListener; trait HelloWorld: Interface { fn greet(&self) -> String; } #[derive(Component)] #[shaku(interface = HelloWorld)] struct HelloWorldImpl; impl HelloWorld for HelloWorldImpl { fn greet(&self) -> String { "Hello, world!".to_owned() } } module! { HelloModule { components = [HelloWorldImpl], providers = [] } } #[derive(Clone)] struct AppState { module: Arc, } impl FromRef for Arc { fn from_ref(app_state: &AppState) -> Arc { app_state.module.clone() } } async fn hello(hello_world: Inject) -> String { hello_world.greet() } #[tokio::main] async fn main() { let module = Arc::new(HelloModule::builder().build()); let state = AppState { module }; let app = Router::new() .route("/", get(hello)) .with_state(state); let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap(); axum::serve(listener, app.into_make_service_with_connect_info::()) .await .unwrap(); } ``` -------------------------------- ### Full InjectProvided Example Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_axum.md A complete example demonstrating module definition, state setup, and usage in an Axum router. ```rust use axum::{routing::get, Router}; use axum::extract::FromRef; use shaku::{module, Provider}; use shaku_axum::InjectProvided; use std::sync::Arc; use tokio::net::TcpListener; trait HelloWorld { fn greet(&self) -> String; } #[derive(Provider)] #[shaku(interface = HelloWorld)] struct HelloWorldImpl; impl HelloWorld for HelloWorldImpl { fn greet(&self) -> String { "Hello, world!".to_owned() } } module! { HelloModule { components = [], providers = [HelloWorldImpl] } } #[derive(Clone)] struct AppState { module: Arc, } impl FromRef for Arc { fn from_ref(app_state: &AppState) -> Arc { app_state.module.clone() } } async fn hello(hello_world: InjectProvided) -> String { hello_world.greet() } #[tokio::main] async fn main() { let module = Arc::new(HelloModule::builder().build()); let state = AppState { module }; let app = Router::new() .route("/", get(hello)) .with_state(state); let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap(); axum::serve(listener, app.into_make_service_with_connect_info::()) .await .unwrap(); } ``` -------------------------------- ### Full InjectProvided example Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_rocket.md A complete example demonstrating module definition, provider registration, and usage in a Rocket route. ```rust #[macro_use] extern crate rocket; use shaku::{module, Provider}; use shaku_rocket::InjectProvided; trait HelloWorld { fn greet(&self) -> String; } #[derive(Provider)] #[shaku(interface = HelloWorld)] struct HelloWorldImpl; impl HelloWorld for HelloWorldImpl { fn greet(&self) -> String { "Hello, world!".to_owned() } } module! { HelloModule { components = [], providers = [HelloWorldImpl] } } #[get("/")] fn hello(hello_world: InjectProvided) -> String { hello_world.greet() } #[rocket::launch] fn rocket() -> _ { let module = HelloModule::builder().build(); rocket::build() .manage(Box::new(module)) .mount("/", routes![hello]) } ``` -------------------------------- ### Complete Inject Example Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_actix.md A full example demonstrating module definition, registration, and usage in an Actix-web application. ```rust use actix_web::{App, HttpServer, web}; use shaku::{module, Component, Interface}; use shaku_actix::Inject; use std::sync::Arc; trait HelloWorld: Interface { fn greet(&self) -> String; } #[derive(Component)] #[shaku(interface = HelloWorld)] struct HelloWorldImpl; impl HelloWorld for HelloWorldImpl { fn greet(&self) -> String { "Hello, world!".to_owned() } } module! { HelloModule { components = [HelloWorldImpl], providers = [] } } async fn hello(hello_world: Inject) -> String { hello_world.greet() } #[actix_web::main] async fn main() -> std::io::Result<()> { let module = Arc::new(HelloModule::builder().build()); HttpServer::new(move || { App::new() .app_data(module.clone()) .route("/", web::get().to(hello)) }) .bind("127.0.0.1:8080")? .run() .await } ``` -------------------------------- ### Complete shaku_rocket integration example Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_rocket.md A full example demonstrating module definition, Rocket state management, and handler injection. ```rust #[macro_use] extern crate rocket; use shaku::{module, Component, Interface}; use shaku_rocket::Inject; trait HelloWorld: Interface { fn greet(&self) -> String; } #[derive(Component)] #[shaku(interface = HelloWorld)] struct HelloWorldImpl; impl HelloWorld for HelloWorldImpl { fn greet(&self) -> String { "Hello, world!".to_owned() } } module! { HelloModule { components = [HelloWorldImpl], providers = [] } } #[get("/")] fn hello(hello_world: Inject) -> String { hello_world.greet() } #[rocket::launch] fn rocket() -> _ { let module = HelloModule::builder().build(); rocket::build() .manage(Box::new(module)) .mount("/", routes![hello]) } ``` -------------------------------- ### Module Implementation Example Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md Demonstrates defining a module using the module! macro and building it. ```rust use shaku::{module, Component, Interface}; trait Service: Interface {} #[derive(Component)] #[shaku(interface = Service)] struct ServiceImpl; impl Service for ServiceImpl {} module! { MyModule { components = [ServiceImpl], providers = [] } } let module = MyModule::builder().build(); ``` -------------------------------- ### Setup shaku module Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_rocket.md Define components and the module structure for use with shaku_rocket. ```rust use shaku::{module, Component, Interface}; trait Logger: Interface { fn log(&self, msg: &str); } #[derive(Component)] #[shaku(interface = Logger)] struct LoggerImpl; impl Logger for LoggerImpl { fn log(&self, msg: &str) { println!("{}", msg); } } module! { AppModule { components = [LoggerImpl], providers = [] } } ``` -------------------------------- ### Build module with component parameters Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/component.md Example of providing parameters to a component during module construction. ```rust let module = MyModule::builder() .with_component_parameters::(LoggerImplParameters { name: "MyLogger".to_string(), }) .build(); ``` -------------------------------- ### Implementing a Custom Provider Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/provider.md Example implementation of the Provider trait for a connection service. ```rust use shaku::{Provider, Module}; use std::error::Error; trait Connection {} struct Conn; impl Connection for Conn {} struct ConnectionProvider; impl Provider for ConnectionProvider { type Interface = dyn Connection; fn provide(module: &M) -> Result, Box> { Ok(Box::new(Conn)) } } ``` -------------------------------- ### Implementing a Component Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/component.md Example showing how to implement a component using the #[derive(Component)] macro and a custom interface. ```rust use shaku::{Component, Interface, HasComponent, Module, ModuleBuildContext}; use std::sync::Arc; trait Logger: Interface { fn log(&self, msg: &str); } #[derive(Component)] #[shaku(interface = Logger)] struct LoggerImpl; impl Logger for LoggerImpl { fn log(&self, msg: &str) { println!("{}", msg); } } ``` -------------------------------- ### Implement Component with dependencies Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/component.md Full example of a component implementation using the Component derive macro. ```rust use shaku::{Component, Interface, HasComponent, Module}; use std::sync::Arc; trait Logger: Interface { fn log(&self, msg: &str); } trait Config: Interface { fn get_debug(&self) -> bool; } #[derive(Component)] #[shaku(interface = Logger)] struct LoggerImpl { #[shaku(inject)] config: Arc, #[shaku(default)] enabled: bool, name: String, // parameter } impl Logger for LoggerImpl { fn log(&self, msg: &str) { if self.enabled { println!("[{}] {}", self.name, msg); } } } ``` -------------------------------- ### Setup Shaku module with providers Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_rocket.md Define a trait, its implementation, and a module to house the provider. ```rust use shaku::{module, Provider}; trait Database {} #[derive(Provider)] #[shaku(interface = Database)] struct DatabaseImpl; impl Database for DatabaseImpl {} module! { AppModule { components = [], providers = [DatabaseImpl] } } ``` -------------------------------- ### Implement and Use Provider Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/provider.md Demonstrates using the Provider derive macro and calling provide to get fresh instances. ```rust use shaku::{module, Provider}; use std::sync::Arc; trait Connection {} #[derive(Provider)] #[shaku(interface = Connection)] struct ConnectionImpl; impl Connection for ConnectionImpl {} module! { MyModule { components = [], providers = [ConnectionImpl] } } fn main() { let module = MyModule::builder().build(); let conn1: Box = module.provide().unwrap(); let conn2: Box = module.provide().unwrap(); // conn1 and conn2 are different instances } ``` -------------------------------- ### Rust Example: Basic Dependency Injection with Components Source: https://github.com/azuremarker/shaku/blob/master/shaku/README.md Demonstrates how to define and use components with dependency injection in Rust using Shaku. Includes trait definitions, component implementations, module declaration, and runtime resolution. ```rust use shaku::{module, Component, Interface, HasComponent}; use std::sync::Arc; trait Logger: Interface { fn log(&self, content: &str); } trait DateLogger: Interface { fn log_date(&self); } #[derive(Component)] #[shaku(interface = Logger)] struct LoggerImpl; impl Logger for LoggerImpl { fn log(&self, content: &str) { println!("{}", content); } } #[derive(Component)] #[shaku(interface = DateLogger)] struct DateLoggerImpl { #[shaku(inject)] logger: Arc, today: String, year: usize, } impl DateLogger for DateLoggerImpl { fn log_date(&self) { self.logger.log(&format!("Today is {}, {}", self.today, self.year)); } } module! { MyModule { components = [LoggerImpl, DateLoggerImpl], providers = [] } } fn main() { let module = MyModule::builder() .with_component_parameters::(DateLoggerImplParameters { today: "Jan 26".to_string(), year: 2020 }) .build(); let date_logger: &dyn DateLogger = module.resolve_ref(); date_logger.log_date(); } ``` -------------------------------- ### Define Generic Modules Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md Example of defining a module with generic type parameters. ```rust use shaku::{module, Component, Interface}; trait Service: Interface {} #[derive(Component)] #[shaku(interface = Service)] struct ServiceImpl { value: T, } impl Service for ServiceImpl {} module! { MyModule { components = [ServiceImpl], providers = [] } } let module = MyModule::::builder().build(); ``` -------------------------------- ### Use Component derive macro Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/component.md Example of using the Component derive macro with dependency injection and parameters. ```rust #[derive(Component)] #[shaku(interface = MyInterface)] struct MyComponentImpl { #[shaku(inject)] dependency: Arc, #[shaku(default)] count: i32, field: String, // Constructor parameter } ``` -------------------------------- ### Implement a Custom Provider Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/provider.md A complete example showing the definition of a provider and the manual implementation of the Provider trait for a module. ```rust use shaku::{Provider, Module, HasComponent, Interface}; use std::error::Error; use std::sync::Arc; trait Logger: Interface {} struct LoggerImpl; impl Logger for LoggerImpl {} impl Interface for LoggerImpl {} trait Connection {} struct Conn; impl Connection for Conn {} #[derive(Provider)] #[shaku(interface = Connection)] struct ConnectionProvider { #[shaku(inject)] logger: Arc, #[shaku(default)] timeout_secs: u64, } impl> Provider for ConnectionProvider { type Interface = dyn Connection; fn provide(module: &M) -> Result, Box> { let logger = module.resolve::>(); // Create a new connection Ok(Box::new(Conn)) } } ``` -------------------------------- ### Implement ComponentFn override Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/component.md Example of creating a factory function for component overrides. ```rust use shaku::{ComponentFn, HasComponent, ModuleBuildContext, Module}; use std::sync::Arc; trait Service {} struct ServiceImpl; impl Service for ServiceImpl {} fn create_override_fn>( ) -> ComponentFn { Box::new(|_ctx| Box::new(ServiceImpl)) } ``` -------------------------------- ### Rocket Integration Configuration Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/configuration.md Setup dependencies and manage the module within a Rocket application. ```toml [dependencies] shaku_rocket = "0.7" rocket = "0.5" ``` ```rust #[rocket::launch] fn rocket() -> _ { let module = MyModule::builder().build(); rocket::build() .manage(Box::new(module)) // Store as Box .mount("/", routes![handler]) } #[get("/")] fn handler(service: Inject) -> String { // Service automatically injected "OK".to_string() } ``` -------------------------------- ### Create Provider Factory Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/types.md Example of defining a factory function for a provider using ProviderFn. ```rust let factory: ProviderFn = Box::new(|module| { let logger = module.resolve_ref::(); Ok(Box::new(DatabaseImpl::new(logger))) }); ``` -------------------------------- ### Implementing Keyed for a Component Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/component.md Example showing how to implement the Keyed trait for a component to register it with a specific key. ```rust use shaku::{Component, Interface, Keyed}; trait Handler: Interface {} #[derive(Component)] #[shaku(interface = Handler)] struct DefaultHandler; impl Handler for DefaultHandler {} impl Keyed for DefaultHandler { fn key() -> &'static str { "default" } } ``` -------------------------------- ### Create Component Factory Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/types.md Example of defining a factory function for a component using ComponentFn. ```rust let factory: ComponentFn = Box::new(|context| { Box::new(LoggerImpl::new()) }); ``` -------------------------------- ### Handle Module State Errors in Rocket Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md Demonstrates the handler and the required rocket::launch setup to manage module state. ```rust #[get("/")] fn handler(service: Inject) -> String { // If module not in Rocket state: 400 error "OK".to_string() } // Correct setup: #[rocket::launch] fn rocket() -> _ { let module = MyModule::builder().build(); rocket::build() .manage(Box::new(module)) // Must add module to state .mount("/", routes![handler]) } ``` -------------------------------- ### Circular Dependency Example Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md Demonstrates a circular dependency between two components that triggers a panic during module resolution. ```rust #[derive(Component)] #[shaku(interface = ServiceA)] struct ServiceAImpl { #[shaku(inject)] b: Arc, } #[derive(Component)] #[shaku(interface = ServiceB)] struct ServiceBImpl { #[shaku(inject)] a: Arc, // Circular! } module! { MyModule { components = [ServiceAImpl, ServiceBImpl], providers = [] } } // Panic during: let module = MyModule::builder().build(); ``` -------------------------------- ### Rocket Framework Integration Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md Example of how provider errors are handled automatically in a Rocket web handler. ```rust #[get("/")] fn handler(service: InjectProvided) -> String { // If service.provide() returns Err, Rocket returns 500 "OK".to_string() } ``` -------------------------------- ### Create Provider Override Function Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/provider.md Example of creating a factory function for use with ModuleBuilder::with_provider_override. ```rust use shaku::{ProviderFn, HasProvider, Module}; trait Database {} struct Db; impl Database for Db {} fn create_override_fn>( ) -> ProviderFn { Box::new(|_module| Ok(Box::new(Db))) } ``` -------------------------------- ### Define a Component Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/README.md Example of a component struct using the Component derive macro and dependency injection attributes. ```rust #[derive(Component)] #[shaku(interface = Service)] struct ServiceImpl { #[shaku(inject)] logger: Arc, #[shaku(default)] enabled: bool, name: String, // Parameter } ``` -------------------------------- ### Handle missing provider registration error in Rust Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md This example shows the runtime error triggered when attempting to provide an interface that was not registered in the module. ```rust let module = MyModule::builder().build(); let service: Box = module.provide().unwrap(); // ERROR ``` -------------------------------- ### Handle missing component registration error in Rust Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md This example demonstrates a compile-time error caused by attempting to inject a component that has not been registered in the module. ```rust use shaku::{module, Component, Interface, HasComponent}; use std::sync::Arc; trait Logger: Interface {} struct LoggerImpl; impl Logger for LoggerImpl {} trait Service: Interface { #[shaku(inject)] logger: Arc, // ERROR: Logger not in module } module! { MyModule { components = [ServiceImpl], // Logger not registered! providers = [] } } ``` ```rust #[derive(Component)] #[shaku(interface = Logger)] struct LoggerImpl; impl Logger for LoggerImpl {} module! { MyModule { components = [ServiceImpl, LoggerImpl], // Fixed providers = [] } } ``` -------------------------------- ### Resolving Circular Dependencies Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md Examples of restructuring dependencies, using lazy components, or using providers to break circular references. ```rust // Original (circular): // ServiceA -> ServiceB -> ServiceA // Fixed (no cycle): // Create a new service: #[derive(Component)] #[shaku(interface = SharedService)] struct SharedServiceImpl; #[derive(Component)] #[shaku(interface = ServiceA)] struct ServiceAImpl { #[shaku(inject)] shared: Arc, } #[derive(Component)] #[shaku(interface = ServiceB)] struct ServiceBImpl { #[shaku(inject)] shared: Arc, // Both depend on shared, no cycle } ``` ```rust module! { MyModule { components = [ ServiceAImpl, #[lazy] ServiceBImpl // Lazy initialization breaks the cycle ], providers = [] } } ``` ```rust #[derive(Provider)] #[shaku(interface = ServiceB)] struct ServiceBProvider; module! { MyModule { components = [ServiceAImpl], providers = [ServiceBProvider] } } ``` -------------------------------- ### Resolve provider dependency constraint errors in Rust Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md This example illustrates the restriction that providers cannot depend on other providers, requiring the dependency to be a component instead. ```rust use shaku::Provider; use std::sync::Arc; #[derive(Provider)] #[shaku(interface = Service)] struct ServiceImpl { #[shaku(inject)] connection: Arc, // ERROR if Connection is a Provider } ``` ```rust #[derive(Component)] #[shaku(interface = Connection)] struct ConnectionImpl; #[derive(Provider)] #[shaku(interface = Service)] struct ServiceImpl { #[shaku(inject)] connection: Arc, // OK - Component } ``` -------------------------------- ### Configure Submodules Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md Demonstrates how to import components from one module into another using submodules. ```rust use shaku::{module, Component, Interface, HasComponent}; trait Logger: Interface { fn log(&self, msg: &str); } #[derive(Component)] #[shaku(interface = Logger)] struct LoggerImpl; impl Logger for LoggerImpl {} module! { LoggingModule { components = [LoggerImpl], providers = [] } } module! { AppModule { components = [], providers = [], use LoggingModule { components = [Logger], providers = [] } } } let logging = LoggingModule::builder().build(); let app = AppModule::builder() .with_submodules(AppModuleSubmodules { logging_module: Box::new(logging), }) .build(); ``` -------------------------------- ### build Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md Finalizes the configuration and returns the initialized module. ```APIDOC ## pub fn build(self) -> M ### Description Constructs and returns the fully initialized module. ### Returns - **M** - The fully initialized module. ``` -------------------------------- ### Configure Actix-web with Shaku Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_actix.md Initializes a Shaku module and registers it as application data within an Actix-web server. ```rust #[actix_web::main] async fn main() -> std::io::Result<()> { let module = Arc::new(MyModule::builder() .with_component_parameters::(params) .build()); HttpServer::new(move || { App::new() .app_data(module.clone()) .route("/", web::get().to(handler)) }) .workers(4) .bind("127.0.0.1:8080")? .run() .await } ``` -------------------------------- ### Define provide Method Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/provider.md Method signature for creating a new instance of a provided service. ```rust fn provide(&self) -> Result, Box> ``` -------------------------------- ### Implement Logger Interface Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/types.md Example of using the Interface trait alias as a bound for a custom trait. ```rust trait Logger: Interface { fn log(&self, msg: &str); } ``` -------------------------------- ### Load Configuration from Files Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/configuration.md Load and parse external configuration files within a component's build method. ```rust use shaku::Component; use std::fs; #[derive(Component)] #[shaku(interface = Settings)] struct SettingsImpl { database_url: String, log_level: String, } impl Component for SettingsImpl { type Interface = dyn Settings; type Parameters = (); fn build( _context: &mut ModuleBuildContext, _params: Self::Parameters, ) -> Box { let config_text = fs::read_to_string("config.toml") .expect("Failed to read config"); // Parse and create settings Box::new(SettingsImpl { database_url: "...".to_string(), log_level: "info".to_string(), }) } } ``` -------------------------------- ### Configure Axum router Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_axum.md Initialize the module and provide it to the Axum router via state. ```rust use axum::{routing::get, Router}; use std::sync::Arc; let module = Arc::new(AppModule::builder().build()); let state = AppState { module }; let app = Router::new() .route("/", get(hello)) .with_state(state); ``` -------------------------------- ### Finalize module construction with build Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md Completes the configuration and returns the fully initialized module. ```rust let module = MyModule::builder() .with_component_parameters::(ServiceImplParameters { ... }) .build(); ``` -------------------------------- ### Handle Nested State Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_axum.md Configuring multiple modules within a single application state using FromRef. ```rust #[derive(Clone)] struct AppState { core: Arc, services: Arc, } impl FromRef for Arc { fn from_ref(state: &AppState) -> Arc { state.core.clone() } } impl FromRef for Arc { fn from_ref(state: &AppState) -> Arc { state.services.clone() } } // Now you can use both: async fn handler( core: Inject, service: Inject, ) -> String { format!("OK") } ``` -------------------------------- ### Project File Structure Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/MANIFEST.md Visual representation of the documentation directory layout and file contents. ```text /workspace/home/output/ ├── README.md (379 lines) │ └─ Overview, quick start, navigation ├── INDEX.md (~400 lines) │ └─ Navigation guide and quick links ├── EXPORTS.md (355 lines) │ └─ Complete API export list ├── MANIFEST.md (this file) │ └─ Documentation scope and quality metrics ├── types.md (349 lines) │ └─ Type reference ├── errors.md (443 lines) │ └─ Error handling and diagnostics ├── configuration.md (524 lines) │ └─ Setup and features └── api-reference/ ├── component.md (389 lines) │ └─ Component trait and derive ├── provider.md (258 lines) │ └─ Provider trait and derive ├── module.md (520 lines) │ └─ Module definition and building ├── shaku_rocket.md (351 lines) │ └─ Rocket 0.5 integration ├── shaku_axum.md (449 lines) │ └─ Axum 0.8 integration └── shaku_actix.md (419 lines) └─ Actix-web 4 integration ``` -------------------------------- ### Provider::provide Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/provider.md Creates a new instance of the service defined by the provider. This method can resolve dependencies from the provided module. ```APIDOC ## fn provide(module: &M) -> Result, Box> ### Description Creates a new instance of the service. This method may resolve other components and providers from the module. Unlike components, providers are called each time a service is requested. ### Parameters - **module** (&M) - Required - Reference to the module. Used to resolve dependencies via module.resolve(), module.resolve_ref(), or module.provide(). ### Returns - **Result, Box>** - A new instance of the service, or an error if provision fails. ``` -------------------------------- ### ModuleBuildContext Implementation Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/EXPORTS.md Context provided during the module build process. ```rust impl ModuleBuildContext { pub fn submodules(&self) -> &M::Submodules; pub fn build_component>(&mut self) -> Arc; } ``` -------------------------------- ### ModuleBuilder Implementation Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/EXPORTS.md Methods for configuring and building a module instance. ```rust impl ModuleBuilder { pub fn with_submodules(submodules: M::Submodules) -> Self; pub fn with_component_parameters>(mut self, params: C::Parameters) -> Self where M: HasComponent; pub fn with_component_override(mut self, component: Box) -> Self where M: HasComponent; pub fn with_component_override_fn( mut self, component_fn: ComponentFn, ) -> Self where M: HasComponent; pub fn with_provider_override( mut self, provider_fn: ProviderFn, ) -> Self where M: HasProvider; pub fn build(self) -> M; } ``` -------------------------------- ### Module Builder Configuration Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md Shows the method chaining pattern used to configure component parameters and overrides before building the module. ```rust let module = MyModule::builder() .with_component_parameters::(params1) .with_component_parameters::(params2) .with_component_override::(Box::new(mock)) .build(); ``` -------------------------------- ### Initialize modules in framework state Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md Ensure modules are stored in the framework state before any handlers are executed. ```rust #[rocket::launch] fn rocket() -> _ { let module = MyModule::builder().build(); rocket::build().manage(Box::new(module)) // Essential } ``` -------------------------------- ### Macros Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/EXPORTS.md Macros provided by Shaku to simplify the implementation of dependency injection patterns. ```APIDOC ## Macros - **#[derive(Component)]**: Derives the Component trait for a struct, enabling it to be managed as a singleton. - **#[derive(Provider)]**: Derives the Provider trait for a struct, enabling it to be managed as a transient factory. - **module!()**: Macro used to declare a module, specifying its components and providers. ### Attributes - **#[shaku(interface = Type)]**: Required attribute for Component/Provider to specify the implemented interface. - **#[shaku(inject)]**: Marks a field for dependency injection. - **#[shaku(default)]**: Uses Default::default() for a field. - **#[lazy]**: Used within module! to defer component initialization. ``` -------------------------------- ### Configure Submodules Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/configuration.md Define modules and submodules using the module! macro and inject them during the build process. ```rust use shaku::{module, HasComponent}; trait CoreServices: HasComponent {} module! { CoreModule: CoreServices { components = [LoggerImpl], providers = [] } } module! { AppModule { components = [], providers = [], use CoreModule { components = [Logger], providers = [] } } } // Building with submodules: let core = CoreModule::builder().build(); let app = AppModule::builder() .with_submodules(AppModuleSubmodules { core_module: Box::new(core), }) .build(); ``` -------------------------------- ### Module Build Method Signature Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md The build method signature used for module initialization. ```rust fn build(context: ModuleBuildContext) -> Self where Self: Sized ``` -------------------------------- ### Actix Integration Configuration Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/configuration.md Register the Shaku module as application data in an Actix-web server. ```toml [dependencies] shaku_actix = "0.2" actix-web = "4" ``` ```rust use std::sync::Arc; #[actix_web::main] async fn main() -> std::io::Result<()> { let module = Arc::new(MyModule::builder().build()); HttpServer::new(move || { App::new() .app_data(module.clone()) .route("/", web::get().to(handler)) }) .bind("127.0.0.1:8080")? .run() .await } async fn handler(service: Inject) -> String { "OK".to_string() } ``` -------------------------------- ### Building Components Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md Resolves and builds a component, returning a cached instance if available and detecting circular dependencies. ```rust pub fn build_component>(&mut self) -> Arc ``` ```rust #[derive(Component)] #[shaku(interface = Database)] struct DatabaseImpl { #[shaku(inject)] logger: Arc, } impl Database for DatabaseImpl { // ... } // In another component's build method: fn build(context: &mut ModuleBuildContext, params: Self::Parameters) -> Box where M: HasComponent { let db: Arc = context.build_component::(); Box::new(ServiceImpl { database: db }) } ``` -------------------------------- ### HasProvider::provide Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/provider.md The provide method is used to create a new instance of a service provided by a module. Each invocation returns a fresh instance of the requested interface. ```APIDOC ## fn provide ### Description Creates a new instance of the provided service. Each call to this method produces a fresh instance. ### Signature `fn provide(&self) -> Result, Box>` ### Returns `Result, Box>` — A new instance of the service, or an error if the provision fails. ``` -------------------------------- ### Manage module in Rocket state Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_rocket.md Build the module and register it within the Rocket application state. ```rust #[rocket::launch] fn rocket() -> _ { let module = AppModule::builder().build(); rocket::build() .manage(Box::new(module)) .mount("/", routes![hello]) } ``` -------------------------------- ### Configure Custom State Type Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_axum.md Implementing FromRef to allow Shaku modules to be part of a larger application state struct. ```rust #[derive(Clone)] struct AppState { module: Arc, config: Config, } impl FromRef for Arc { fn from_ref(state: &AppState) -> Arc { state.module.clone() } } ``` -------------------------------- ### Component Parameter Generation Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/types.md Demonstrates how the Component derive macro generates a parameter struct for components with fields. ```rust use shaku::Component; use std::sync::Arc; trait Service {} #[derive(Component)] #[shaku(interface = Service)] struct ServiceImpl { timeout: u32, retries: u32, } // Generated type: struct ServiceImplParameters { timeout: u32, retries: u32, } ``` -------------------------------- ### Registering Module in Actix App Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_actix.md Build the module and register it as application data within the Actix HttpServer. ```rust use actix_web::{App, HttpServer}; use std::sync::Arc; #[actix_web::main] async fn main() -> std::io::Result<()> { let module = Arc::new(AppModule::builder().build()); HttpServer::new(move || { App::new() .app_data(module.clone()) .route("/", web::get().to(hello)) }) .bind("127.0.0.1:8080")? .run() .await } ``` -------------------------------- ### Component::build Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/component.md The build method is responsible for constructing a singleton service instance within the module build context. ```APIDOC ## fn build ### Description Constructs a singleton service instance. This method is typically invoked by the dependency injection container during module initialization. ### Signature `fn build(context: &mut ModuleBuildContext, params: Self::Parameters) -> Box` ### Parameters - **context** (`&mut ModuleBuildContext`) - Required - The module build context used to resolve dependencies. - **params** (`Self::Parameters`) - Required - Configuration parameters for the component instance. ### Returns - `Box` - A boxed instance of the component implementing the specified interface. ``` -------------------------------- ### Module Macro Syntax Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md General syntax structure for the module! macro. ```rust module! { ModuleName [: TraitName] [where Generics] { components = [Comp1, Comp2, ...], providers = [Prov1, Prov2, ...], use Submodule { components = [Interface1], providers = [Interface2] } } } ``` -------------------------------- ### Configure Lazy Components in Shaku Modules Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/configuration.md Use the #[lazy] attribute within the module! macro to defer component initialization until the first access. ```rust module! { MyModule { components = [ #[lazy] ExpensiveComponent, QuickComponent, ], providers = [QuickProvider] } } ``` -------------------------------- ### Handle provider results Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md Always use the question mark operator to handle the Result returned by the provide method. ```rust let service = module.provide::()?; ``` -------------------------------- ### Store module in Rocket state Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_rocket.md Initialize the module and register it within the Rocket application state. ```rust #[rocket::launch] fn rocket() -> _ { let module = AppModule::builder().build(); rocket::build() .manage(Box::new(module)) .mount("/", routes![query]) } ``` -------------------------------- ### Configure Cargo dependencies for Shaku Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/configuration.md Include these dependencies in your Cargo.toml to use Shaku and its framework integrations. ```toml [dependencies] shaku = "0.6" # Core DI library shaku_rocket = "0.7" # Rocket framework integration shaku_axum = "0.6" # Axum framework integration shaku_actix = "0.2" # Actix framework integration # Transitive dependencies anymap2 = "0.13" # Type-safe map for components once_cell = "1.5" # Lazy initialization support ``` -------------------------------- ### Axum Integration Configuration Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/configuration.md Configure Axum state to hold the Shaku module and inject services into handlers. ```toml [dependencies] shaku_axum = "0.6" axum = "0.8" tokio = { version = "1", features = ["full"] } ``` ```rust use axum::extract::FromRef; use std::sync::Arc; #[derive(Clone)] struct AppState { module: Arc, } impl FromRef for Arc { fn from_ref(state: &AppState) -> Arc { state.module.clone() } } #[tokio::main] async fn main() { let module = Arc::new(MyModule::builder().build()); let state = AppState { module }; let app = Router::new() .route("/", get(handler)) .with_state(state); let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap(); axum::serve(listener, app.into_make_service()).await.unwrap(); } async fn handler(service: Inject) -> String { "OK".to_string() } ``` -------------------------------- ### Provide Method Signature Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/provider.md The signature for the provide method used to instantiate services. ```rust fn provide(module: &M) -> Result, Box> ``` -------------------------------- ### Actix: InjectProvided Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/types.md Actix-web extractor for creating transient services via providers. ```APIDOC ## Actix: InjectProvided ### Description Actix-web extractor for creating transient services via providers. ### Type Parameters - **M** (ModuleInterface + HasProvider + ?Sized) - Module type - **I** (?Sized) - Service interface type ``` -------------------------------- ### Configure Modules with the Builder Pattern Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/configuration.md Use the module builder to inject parameters and override components or providers at runtime. ```rust let module = MyModule::builder() .with_component_parameters::(params1) .with_component_parameters::(params2) .with_component_override::(Box::new(mock_logger)) .with_provider_override::(Box::new(|_| { Ok(Box::new(mock_db)) })) .build(); ``` -------------------------------- ### build_component() Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md Resolves and builds a component of the specified type, utilizing caching and circular dependency detection. ```APIDOC ## fn build_component>() ### Description Resolves and builds a component. If the component is already built, returns the cached instance. Detects circular dependencies and panics if found. ### Signature `pub fn build_component>(&mut self) -> Arc` ### Parameters - **C** (Component) - The component type to build. ### Returns - **Arc** - An Arc-wrapped component instance. ``` -------------------------------- ### Build Method Signature Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/component.md The signature for the build method used to construct component instances. ```rust fn build(context: &mut ModuleBuildContext, params: Self::Parameters) -> Box ``` -------------------------------- ### Handle Module State Errors in Actix Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md Illustrates the handler and the required app_data registration within the HttpServer configuration. ```rust async fn handler(service: Inject) -> String { // If module not in app data: 500 error "OK".to_string() } // Correct setup: let module = Arc::new(MyModule::builder().build()); HttpServer::new(move || { App::new() .app_data(module.clone()) // Must add module to app data .route("/", web::get().to(handler)) }) ``` -------------------------------- ### Display Shaku File Hierarchy Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/INDEX.md Visual representation of the documentation directory structure for the Shaku project. ```text output/ ├── README.md # Main entry point and overview ├── INDEX.md # This file ├── EXPORTS.md # Complete exported API surface ├── types.md # Type reference ├── errors.md # Error handling and diagnostics ├── configuration.md # Features and setup └── api-reference/ ├── component.md # Component trait and derive ├── provider.md # Provider trait and derive ├── module.md # Module definition and building ├── shaku_rocket.md # Rocket integration ├── shaku_axum.md # Axum integration └── shaku_actix.md # Actix integration ``` -------------------------------- ### with_submodules Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md Configures the submodules for the module being built. ```APIDOC ## pub fn with_submodules(submodules: M::Submodules) -> Self ### Description Sets the submodules struct for this module. ### Parameters - **submodules** (M::Submodules) - Required - The submodules struct for this module. ### Returns - **ModuleBuilder** - The builder for method chaining. ``` -------------------------------- ### submodules() Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/module.md Retrieves a reference to the submodules associated with the current module build context. ```APIDOC ## fn submodules() ### Description Returns a reference to the submodules defined within the module build context. ### Signature `pub fn submodules(&self) -> &M::Submodules` ### Returns - **&M::Submodules** - A reference to the submodules. ``` -------------------------------- ### Combining Components and Providers Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/shaku_rocket.md Using both standard component injection and provider-based injection in a route. ```rust #[get("/data")] fn handler( logger: Inject, connection: InjectProvided, ) -> String { logger.log("Opening connection"); // Use component and fresh provider format!("Data: {:?}", connection) } ``` -------------------------------- ### Axum: InjectProvided Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/types.md Axum extractor for creating transient services via providers. ```APIDOC ## Axum: InjectProvided ### Description Axum extractor for creating transient services via providers. ### Type Parameters - **M** (ModuleInterface + HasProvider + ?Sized) - Module type - **I** (?Sized) - Service interface type ``` -------------------------------- ### Define a Component with Parameters Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/configuration.md Use the Component derive macro to define a struct and specify parameters with the shaku attribute. ```rust use shaku::Component; #[derive(Component)] #[shaku(interface = Logger)] struct LoggerImpl { name: String, level: u8, #[shaku(inject)] config: Arc, #[shaku(default)] enabled: bool, } ``` -------------------------------- ### Handle Module State Errors in Axum Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/errors.md Shows the handler and the necessary FromRef implementation and router state configuration. ```rust async fn handler(service: Inject) -> String { // If Arc not in state: 500 error "OK".to_string() } // Correct setup: impl FromRef for Arc { fn from_ref(state: &AppState) -> Arc { state.module.clone() } } let module = Arc::new(MyModule::builder().build()); let state = AppState { module }; let app = Router::new() .route("/", get(handler)) .with_state(state); ``` -------------------------------- ### Actix: Inject Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/types.md Actix-web extractor for resolving singleton components. ```APIDOC ## Actix: Inject ### Description Actix-web extractor for resolving singleton components. ### Type Parameters - **M** (ModuleInterface + HasComponent + ?Sized) - Module type - **I** (Interface + ?Sized) - Component interface type ``` -------------------------------- ### Resolving Components with HasComponents Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/component.md Demonstrates retrieving all registered components from a module and iterating over them. ```rust let module = MyModule::builder().build(); let middlewares: &[Arc] = module.resolve_all(); for middleware in middlewares { middleware.process(); } ``` -------------------------------- ### Share Module in Web Server Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/README.md Wrap a module in an Arc to share it across multiple web server worker threads. ```rust let module = Arc::new(MyModule::builder().build()); HttpServer::new(move || { App::new() .app_data(module.clone()) // Shared across workers }) ``` -------------------------------- ### Generic Component Definition Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/types.md Illustrates how to define a component that implements a generic trait. ```rust use shaku::Component; trait Repository {} #[derive(Component)] #[shaku(interface = Repository)] struct StringRepository; impl Repository for StringRepository {} ``` -------------------------------- ### Implement a Provider in Rust Source: https://github.com/azuremarker/shaku/blob/master/_autodocs/api-reference/provider.md Defines a custom provider that returns a Result, allowing for error handling during service instantiation. ```rust use shaku::{Provider, Module}; use std::error::Error; trait Database {} #[derive(Provider)] #[shaku(interface = Database)] struct DatabaseProvider; impl Provider for DatabaseProvider { type Interface = dyn Database; fn provide(_module: &M) -> Result, Box> { // If connection fails, return error Err("Failed to connect to database".into()) } } ```