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<()> {
47 self.lifecycle.shutdown().await
48 }
49}
50
51pub struct Nidus;
53
54impl Nidus {
55 pub fn bootstrap<M: Module>() -> Result<Application> {
63 let graph = ModuleGraph::from_root::<M>()?;
64 let mut container = Container::new();
65 register_module_providers(&mut container, &graph)?;
66 Ok(Application::new(container, graph))
67 }
68
69 pub fn bootstrap_with_modules<M, I>(modules: I) -> Result<Application>
75 where
76 M: Module,
77 I: IntoIterator<Item = ModuleDefinition>,
78 {
79 let graph = ModuleGraph::from_root_and_modules::<M, I>(modules)?;
80 let mut container = Container::new();
81 register_module_providers(&mut container, &graph)?;
82 Ok(Application::new(container, graph))
83 }
84
85 pub async fn bootstrap_with_lifecycle<M: Module>(
90 lifecycle: LifecycleRunner,
91 ) -> Result<Application> {
92 let graph = ModuleGraph::from_root::<M>()?;
93 let mut container = Container::new();
94 register_module_providers(&mut container, &graph)?;
95 initialize_module_providers(&mut container, &graph).await?;
96 lifecycle.startup().await?;
97 Ok(Application::with_lifecycle(container, graph, lifecycle))
98 }
99
100 pub async fn bootstrap_with_modules_and_lifecycle<M, I>(
105 modules: I,
106 lifecycle: LifecycleRunner,
107 ) -> Result<Application>
108 where
109 M: Module,
110 I: IntoIterator<Item = ModuleDefinition>,
111 {
112 let graph = ModuleGraph::from_root_and_modules::<M, I>(modules)?;
113 let mut container = Container::new();
114 register_module_providers(&mut container, &graph)?;
115 initialize_module_providers(&mut container, &graph).await?;
116 lifecycle.startup().await?;
117 Ok(Application::with_lifecycle(container, graph, lifecycle))
118 }
119}
120
121fn register_module_providers(container: &mut Container, graph: &ModuleGraph) -> Result<()> {
122 for module in graph.modules() {
123 for registrar in module.provider_registrars() {
124 registrar(container)?;
125 }
126 }
127 Ok(())
128}
129
130async fn initialize_module_providers(container: &mut Container, graph: &ModuleGraph) -> Result<()> {
131 for module in graph.modules() {
132 for initializer in module.async_initializers() {
133 initializer(container).await?;
134 }
135 }
136 Ok(())
137}