1pub mod config_manager;
6pub mod dependency_resolver;
7pub mod service_discovery;
8pub use actr_config::Config;
9pub use config_manager::TomlConfigManager;
10pub use dependency_resolver::DefaultDependencyResolver;
11pub use service_discovery::NetworkServiceDiscovery;
12
13use anyhow::Result;
14use async_trait::async_trait;
15use serde::{Deserialize, Serialize};
16use std::path::{Path, PathBuf};
17
18#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
24pub struct DependencySpec {
25 pub name: String,
26 pub uri: String,
27 pub version: Option<String>,
28 pub fingerprint: Option<String>,
29}
30
31#[derive(Debug, Clone)]
33pub struct ResolvedDependency {
34 pub spec: DependencySpec,
35 pub uri: String,
36 pub resolved_version: String,
37 pub fingerprint: String,
38 pub proto_files: Vec<ProtoFile>,
39}
40
41#[derive(Debug, Clone)]
43pub struct ProtoFile {
44 pub name: String,
45 pub path: PathBuf,
46 pub content: String,
47 pub services: Vec<ServiceDefinition>,
48}
49
50#[derive(Debug, Clone)]
52pub struct ServiceDefinition {
53 pub name: String,
54 pub methods: Vec<MethodDefinition>,
55}
56
57#[derive(Debug, Clone)]
59pub struct MethodDefinition {
60 pub name: String,
61 pub input_type: String,
62 pub output_type: String,
63}
64
65#[derive(Debug, Clone)]
67pub struct ServiceInfo {
68 pub name: String,
69 pub uri: String,
70 pub version: String,
71 pub fingerprint: String,
72 pub description: Option<String>,
73 pub methods: Vec<MethodDefinition>,
74}
75
76#[derive(Debug, Clone)]
78pub struct ServiceDetails {
79 pub info: ServiceInfo,
80 pub proto_files: Vec<ProtoFile>,
81 pub dependencies: Vec<String>,
82}
83
84#[derive(Debug, Clone, PartialEq)]
86pub struct Fingerprint {
87 pub algorithm: String,
88 pub value: String,
89}
90
91#[derive(Debug, Clone)]
93pub struct ValidationReport {
94 pub is_valid: bool,
95 pub config_validation: ConfigValidation,
96 pub dependency_validation: Vec<DependencyValidation>,
97 pub network_validation: Vec<NetworkValidation>,
98 pub fingerprint_validation: Vec<FingerprintValidation>,
99 pub conflicts: Vec<ConflictReport>,
100}
101
102#[derive(Debug, Clone)]
103pub struct ConfigValidation {
104 pub is_valid: bool,
105 pub errors: Vec<String>,
106 pub warnings: Vec<String>,
107}
108
109#[derive(Debug, Clone)]
110pub struct DependencyValidation {
111 pub dependency: String,
112 pub is_available: bool,
113 pub resolved_uri: Option<String>,
114 pub error: Option<String>,
115}
116
117#[derive(Debug, Clone)]
118pub struct NetworkValidation {
119 pub uri: String,
120 pub is_reachable: bool,
121 pub latency_ms: Option<u64>,
122 pub error: Option<String>,
123}
124
125#[derive(Debug, Clone)]
126pub struct FingerprintValidation {
127 pub dependency: String,
128 pub expected: Fingerprint,
129 pub actual: Option<Fingerprint>,
130 pub is_valid: bool,
131 pub error: Option<String>,
132}
133
134#[derive(Debug, Clone)]
135pub struct ConflictReport {
136 pub dependency_a: String,
137 pub dependency_b: String,
138 pub conflict_type: ConflictType,
139 pub description: String,
140}
141
142#[derive(Debug, Clone)]
143pub enum ConflictType {
144 VersionConflict,
145 FingerprintMismatch,
146 CircularDependency,
147}
148
149impl ValidationReport {
150 pub fn is_success(&self) -> bool {
151 self.is_valid
152 && self.config_validation.is_valid
153 && self.dependency_validation.iter().all(|d| d.is_available)
154 && self.network_validation.iter().all(|n| n.is_reachable)
155 && self.fingerprint_validation.iter().all(|f| f.is_valid)
156 && self.conflicts.is_empty()
157 }
158}
159
160#[async_trait]
166pub trait ConfigManager: Send + Sync {
167 async fn load_config(&self, path: &Path) -> Result<Config>;
169
170 async fn save_config(&self, config: &Config, path: &Path) -> Result<()>;
172
173 async fn update_dependency(&self, spec: &DependencySpec) -> Result<()>;
175
176 async fn validate_config(&self) -> Result<ConfigValidation>;
178
179 fn get_project_root(&self) -> &Path;
181
182 async fn backup_config(&self) -> Result<ConfigBackup>;
184
185 async fn restore_backup(&self, backup: ConfigBackup) -> Result<()>;
187
188 async fn remove_backup(&self, backup: ConfigBackup) -> Result<()>;
190}
191
192#[derive(Debug, Clone, Serialize, Deserialize)]
193pub struct PackageConfig {
194 pub name: String,
195 pub version: String,
196 #[serde(rename = "type")]
197 pub package_type: Option<String>,
198}
199
200#[derive(Debug, Clone)]
202pub struct ConfigBackup {
203 pub original_path: PathBuf,
204 pub backup_path: PathBuf,
205 pub timestamp: std::time::SystemTime,
206}
207
208#[async_trait]
214pub trait DependencyResolver: Send + Sync {
215 async fn resolve_spec(&self, spec: &str) -> Result<DependencySpec>;
217
218 async fn resolve_dependencies(
220 &self,
221 specs: &[DependencySpec],
222 ) -> Result<Vec<ResolvedDependency>>;
223
224 async fn check_conflicts(&self, deps: &[ResolvedDependency]) -> Result<Vec<ConflictReport>>;
226
227 async fn build_dependency_graph(&self, deps: &[ResolvedDependency]) -> Result<DependencyGraph>;
229}
230
231#[derive(Debug, Clone)]
232pub struct DependencyGraph {
233 pub nodes: Vec<String>,
234 pub edges: Vec<(String, String)>,
235 pub has_cycles: bool,
236}
237
238#[async_trait]
244pub trait ServiceDiscovery: Send + Sync {
245 async fn discover_services(&self, filter: Option<&ServiceFilter>) -> Result<Vec<ServiceInfo>>;
247
248 async fn get_service_details(&self, uri: &str) -> Result<ServiceDetails>;
250
251 async fn check_service_availability(&self, uri: &str) -> Result<AvailabilityStatus>;
253
254 async fn get_service_proto(&self, uri: &str) -> Result<Vec<ProtoFile>>;
256}
257
258#[derive(Debug, Clone)]
259pub struct ServiceFilter {
260 pub name_pattern: Option<String>,
261 pub version_range: Option<String>,
262 pub tags: Option<Vec<String>>,
263}
264
265#[derive(Debug, Clone)]
266pub struct AvailabilityStatus {
267 pub is_available: bool,
268 pub last_seen: Option<std::time::SystemTime>,
269 pub health: HealthStatus,
270}
271
272#[derive(Debug, Clone)]
273pub enum HealthStatus {
274 Healthy,
275 Degraded,
276 Unhealthy,
277 Unknown,
278}
279
280#[async_trait]
286pub trait NetworkValidator: Send + Sync {
287 async fn check_connectivity(&self, uri: &str) -> Result<ConnectivityStatus>;
289
290 async fn verify_service_health(&self, uri: &str) -> Result<HealthStatus>;
292
293 async fn test_latency(&self, uri: &str) -> Result<LatencyInfo>;
295
296 async fn batch_check(&self, uris: &[String]) -> Result<Vec<NetworkCheckResult>>;
298}
299
300#[derive(Debug, Clone)]
301pub struct ConnectivityStatus {
302 pub is_reachable: bool,
303 pub response_time_ms: Option<u64>,
304 pub error: Option<String>,
305}
306
307#[derive(Debug, Clone)]
308pub struct LatencyInfo {
309 pub min_ms: u64,
310 pub max_ms: u64,
311 pub avg_ms: u64,
312 pub samples: u32,
313}
314
315#[derive(Debug, Clone)]
316pub struct NetworkCheckResult {
317 pub uri: String,
318 pub connectivity: ConnectivityStatus,
319 pub health: HealthStatus,
320 pub latency: Option<LatencyInfo>,
321}
322
323#[async_trait]
329pub trait FingerprintValidator: Send + Sync {
330 async fn compute_service_fingerprint(&self, service: &ServiceInfo) -> Result<Fingerprint>;
332
333 async fn verify_fingerprint(
335 &self,
336 expected: &Fingerprint,
337 actual: &Fingerprint,
338 ) -> Result<bool>;
339
340 async fn compute_project_fingerprint(&self, project_path: &Path) -> Result<Fingerprint>;
342
343 async fn generate_lock_fingerprint(&self, deps: &[ResolvedDependency]) -> Result<Fingerprint>;
345}
346
347#[async_trait]
353pub trait ProtoProcessor: Send + Sync {
354 async fn discover_proto_files(&self, path: &Path) -> Result<Vec<ProtoFile>>;
356
357 async fn parse_proto_services(&self, files: &[ProtoFile]) -> Result<Vec<ServiceDefinition>>;
359
360 async fn generate_code(&self, input: &Path, output: &Path) -> Result<GenerationResult>;
362
363 async fn validate_proto_syntax(&self, files: &[ProtoFile]) -> Result<ValidationReport>;
365}
366
367#[derive(Debug, Clone)]
368pub struct GenerationResult {
369 pub generated_files: Vec<PathBuf>,
370 pub warnings: Vec<String>,
371 pub errors: Vec<String>,
372}
373
374#[async_trait]
380pub trait CacheManager: Send + Sync {
381 async fn get_cached_proto(&self, uri: &str) -> Result<Option<CachedProto>>;
383
384 async fn cache_proto(&self, uri: &str, proto: &[ProtoFile]) -> Result<()>;
386
387 async fn invalidate_cache(&self, uri: &str) -> Result<()>;
389
390 async fn clear_cache(&self) -> Result<()>;
392
393 async fn get_cache_stats(&self) -> Result<CacheStats>;
395}
396
397#[derive(Debug, Clone)]
398pub struct CachedProto {
399 pub uri: String,
400 pub files: Vec<ProtoFile>,
401 pub fingerprint: Fingerprint,
402 pub cached_at: std::time::SystemTime,
403 pub expires_at: Option<std::time::SystemTime>,
404}
405
406#[derive(Debug, Clone)]
407pub struct CacheStats {
408 pub total_entries: usize,
409 pub total_size_bytes: u64,
410 pub hit_rate: f64,
411 pub miss_rate: f64,
412}
413
414#[async_trait]
420pub trait UserInterface: Send + Sync {
421 async fn prompt_input(&self, prompt: &str) -> Result<String>;
423
424 async fn confirm(&self, message: &str) -> Result<bool>;
426
427 async fn select_service_from_list(
429 &self,
430 items: &[ServiceInfo],
431 formatter: fn(&ServiceInfo) -> String,
432 ) -> Result<usize>;
433
434 async fn select_string_from_list(
436 &self,
437 items: &[String],
438 formatter: fn(&String) -> String,
439 ) -> Result<usize>;
440
441 async fn display_service_table(
443 &self,
444 items: &[ServiceInfo],
445 headers: &[&str],
446 formatter: fn(&ServiceInfo) -> Vec<String>,
447 );
448
449 async fn show_progress(&self, message: &str) -> Result<Box<dyn ProgressBar>>;
451}
452
453pub trait ProgressBar: Send + Sync {
455 fn update(&self, progress: f64);
456 fn set_message(&self, message: &str);
457 fn finish(&self);
458}