allsource_core/infrastructure/di/
builder.rs1use super::ServiceContainer;
7use crate::{
8 domain::repositories::{
9 AccessTokenRepository, ArticleRepository, AuditEventRepository, CreatorRepository,
10 EventStreamRepository, ForkRepository, TenantRepository, TransactionRepository,
11 },
12 infrastructure::{
13 persistence::{SystemMetadataStore, SystemRepositories},
14 repositories::{
15 EventSourcedConfigRepository, InMemoryAccessTokenRepository, InMemoryArticleRepository,
16 InMemoryCreatorRepository, InMemoryEventStreamRepository, InMemoryForkRepository,
17 InMemoryTransactionRepository,
18 },
19 },
20};
21use std::sync::Arc;
22
23#[derive(Default)]
44pub struct ContainerBuilder {
45 creator_repository: Option<Arc<dyn CreatorRepository>>,
46 article_repository: Option<Arc<dyn ArticleRepository>>,
47 transaction_repository: Option<Arc<dyn TransactionRepository>>,
48 access_token_repository: Option<Arc<dyn AccessTokenRepository>>,
49 fork_repository: Option<Arc<dyn ForkRepository>>,
50 event_stream_repository: Option<Arc<dyn EventStreamRepository>>,
51
52 tenant_repository: Option<Arc<dyn TenantRepository>>,
54 audit_repository: Option<Arc<dyn AuditEventRepository>>,
55 config_repository: Option<Arc<EventSourcedConfigRepository>>,
56 system_store: Option<Arc<SystemMetadataStore>>,
57}
58
59impl ContainerBuilder {
60 pub fn new() -> Self {
62 Self::default()
63 }
64
65 pub fn with_in_memory_repositories(mut self) -> Self {
70 self.creator_repository = Some(Arc::new(InMemoryCreatorRepository::new()));
71 self.article_repository = Some(Arc::new(InMemoryArticleRepository::new()));
72 self.transaction_repository = Some(Arc::new(InMemoryTransactionRepository::new()));
73 self.access_token_repository = Some(Arc::new(InMemoryAccessTokenRepository::new()));
74 self.fork_repository = Some(Arc::new(InMemoryForkRepository::new()));
75 self.event_stream_repository = Some(Arc::new(InMemoryEventStreamRepository::new()));
76 self
77 }
78
79 pub fn with_creator_repository(mut self, repository: Arc<dyn CreatorRepository>) -> Self {
81 self.creator_repository = Some(repository);
82 self
83 }
84
85 pub fn with_article_repository(mut self, repository: Arc<dyn ArticleRepository>) -> Self {
87 self.article_repository = Some(repository);
88 self
89 }
90
91 pub fn with_transaction_repository(
93 mut self,
94 repository: Arc<dyn TransactionRepository>,
95 ) -> Self {
96 self.transaction_repository = Some(repository);
97 self
98 }
99
100 pub fn with_access_token_repository(
102 mut self,
103 repository: Arc<dyn AccessTokenRepository>,
104 ) -> Self {
105 self.access_token_repository = Some(repository);
106 self
107 }
108
109 pub fn with_fork_repository(mut self, repository: Arc<dyn ForkRepository>) -> Self {
111 self.fork_repository = Some(repository);
112 self
113 }
114
115 pub fn with_event_stream_repository(
117 mut self,
118 repository: Arc<dyn EventStreamRepository>,
119 ) -> Self {
120 self.event_stream_repository = Some(repository);
121 self
122 }
123
124 pub fn with_system_repositories(mut self, repos: SystemRepositories) -> Self {
132 self.system_store = Some(repos.system_store);
133 self.tenant_repository = Some(repos.tenant_repository);
134 self.audit_repository = Some(repos.audit_repository);
135 self.config_repository = Some(repos.config_repository);
136 self
137 }
138
139 pub fn with_tenant_repository(mut self, repository: Arc<dyn TenantRepository>) -> Self {
141 self.tenant_repository = Some(repository);
142 self
143 }
144
145 pub fn with_audit_repository(mut self, repository: Arc<dyn AuditEventRepository>) -> Self {
147 self.audit_repository = Some(repository);
148 self
149 }
150
151 pub fn build(self) -> ServiceContainer {
159 let mut container = ServiceContainer::new(
160 self.creator_repository
161 .expect("CreatorRepository not configured. Use with_in_memory_repositories() or with_creator_repository()"),
162 self.article_repository
163 .expect("ArticleRepository not configured. Use with_in_memory_repositories() or with_article_repository()"),
164 self.transaction_repository
165 .expect("TransactionRepository not configured. Use with_in_memory_repositories() or with_transaction_repository()"),
166 self.access_token_repository
167 .expect("AccessTokenRepository not configured. Use with_in_memory_repositories() or with_access_token_repository()"),
168 self.fork_repository
169 .expect("ForkRepository not configured. Use with_in_memory_repositories() or with_fork_repository()"),
170 self.event_stream_repository
171 .expect("EventStreamRepository not configured. Use with_in_memory_repositories() or with_event_stream_repository()"),
172 );
173
174 container.tenant_repository = self.tenant_repository;
175 container.audit_repository = self.audit_repository;
176 container.config_repository = self.config_repository;
177 container.system_store = self.system_store;
178
179 container
180 }
181
182 pub fn try_build(self) -> Result<ServiceContainer, ContainerBuilderError> {
186 let mut container = ServiceContainer::new(
187 self.creator_repository
188 .ok_or(ContainerBuilderError::MissingRepository(
189 "CreatorRepository",
190 ))?,
191 self.article_repository
192 .ok_or(ContainerBuilderError::MissingRepository(
193 "ArticleRepository",
194 ))?,
195 self.transaction_repository
196 .ok_or(ContainerBuilderError::MissingRepository(
197 "TransactionRepository",
198 ))?,
199 self.access_token_repository
200 .ok_or(ContainerBuilderError::MissingRepository(
201 "AccessTokenRepository",
202 ))?,
203 self.fork_repository
204 .ok_or(ContainerBuilderError::MissingRepository("ForkRepository"))?,
205 self.event_stream_repository
206 .ok_or(ContainerBuilderError::MissingRepository(
207 "EventStreamRepository",
208 ))?,
209 );
210
211 container.tenant_repository = self.tenant_repository;
212 container.audit_repository = self.audit_repository;
213 container.config_repository = self.config_repository;
214 container.system_store = self.system_store;
215
216 Ok(container)
217 }
218}
219
220#[derive(Debug, Clone)]
222pub enum ContainerBuilderError {
223 MissingRepository(&'static str),
225}
226
227impl std::fmt::Display for ContainerBuilderError {
228 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229 match self {
230 ContainerBuilderError::MissingRepository(name) => {
231 write!(f, "{} not configured", name)
232 }
233 }
234 }
235}
236
237impl std::error::Error for ContainerBuilderError {}