1use crate::{Container, LifecycleRunner, Module, ModuleDefinition, ModuleGraph, Result};
4
5pub struct Application {
7 container: Container,
8 modules: ModuleGraph,
9 lifecycle: LifecycleRunner,
10}
11
12impl Application {
13 pub fn new(container: Container, modules: ModuleGraph) -> Self {
15 Self {
16 container,
17 modules,
18 lifecycle: LifecycleRunner::empty(),
19 }
20 }
21
22 pub fn with_lifecycle(
24 container: Container,
25 modules: ModuleGraph,
26 lifecycle: LifecycleRunner,
27 ) -> Self {
28 Self {
29 container,
30 modules,
31 lifecycle,
32 }
33 }
34
35 pub fn container(&self) -> &Container {
37 &self.container
38 }
39
40 pub fn modules(&self) -> &ModuleGraph {
42 &self.modules
43 }
44
45 pub async fn shutdown(&self) -> Result<()> {
50 self.lifecycle.shutdown().await
51 }
52}
53
54pub struct Nidus;
56
57impl Nidus {
58 pub fn bootstrap<M: Module>() -> Result<Application> {
66 let graph = ModuleGraph::from_root::<M>()?;
67 let mut container = Container::new();
68 register_module_providers(&mut container, &graph)?;
69 Ok(Application::new(container, graph))
70 }
71
72 pub fn bootstrap_with_modules<M, I>(modules: I) -> Result<Application>
78 where
79 M: Module,
80 I: IntoIterator<Item = ModuleDefinition>,
81 {
82 let graph = ModuleGraph::from_root_and_modules::<M, I>(modules)?;
83 let mut container = Container::new();
84 register_module_providers(&mut container, &graph)?;
85 Ok(Application::new(container, graph))
86 }
87
88 pub async fn bootstrap_with_lifecycle<M: Module>(
93 lifecycle: LifecycleRunner,
94 ) -> Result<Application> {
95 let graph = ModuleGraph::from_root::<M>()?;
96 let mut container = Container::new();
97 register_module_providers(&mut container, &graph)?;
98 initialize_module_providers(&mut container, &graph).await?;
99 lifecycle.startup().await?;
100 Ok(Application::with_lifecycle(container, graph, lifecycle))
101 }
102
103 pub async fn bootstrap_with_modules_and_lifecycle<M, I>(
108 modules: I,
109 lifecycle: LifecycleRunner,
110 ) -> Result<Application>
111 where
112 M: Module,
113 I: IntoIterator<Item = ModuleDefinition>,
114 {
115 let graph = ModuleGraph::from_root_and_modules::<M, I>(modules)?;
116 let mut container = Container::new();
117 register_module_providers(&mut container, &graph)?;
118 initialize_module_providers(&mut container, &graph).await?;
119 lifecycle.startup().await?;
120 Ok(Application::with_lifecycle(container, graph, lifecycle))
121 }
122}
123
124fn register_module_providers(container: &mut Container, graph: &ModuleGraph) -> Result<()> {
125 for module in graph.modules() {
126 for registrar in module.provider_registrars() {
127 registrar(container)?;
128 }
129 }
130 Ok(())
131}
132
133async fn initialize_module_providers(container: &mut Container, graph: &ModuleGraph) -> Result<()> {
134 for module in graph.modules() {
135 for initializer in module.async_initializers() {
136 initializer(container).await?;
137 }
138 }
139 Ok(())
140}