use crate::generator::compose::types::AgentType;
use crate::generator::{compose::memory::MemoryScope, context::GeneratorContext};
use crate::i18n::TargetLanguage;
use anyhow::Result;
use std::collections::HashMap;
use std::fs;
pub mod summary_generator;
pub mod summary_outlet;
pub mod fixer;
pub use summary_outlet::SummaryOutlet;
pub use fixer::MermaidFixer;
pub trait Outlet {
async fn save(&self, context: &GeneratorContext) -> Result<()>;
}
pub struct DocTree {
structure: HashMap<String, String>,
}
impl DocTree {
pub fn new(target_language: &TargetLanguage) -> Self {
let structure = HashMap::from([
(
AgentType::Overview.to_string(),
target_language.get_doc_filename("overview"),
),
(
AgentType::Architecture.to_string(),
target_language.get_doc_filename("architecture"),
),
(
AgentType::Workflow.to_string(),
target_language.get_doc_filename("workflow"),
),
(
AgentType::Boundary.to_string(),
target_language.get_doc_filename("boundary"),
),
]);
Self { structure }
}
pub fn insert(&mut self, scoped_key: &str, relative_path: &str) {
self.structure
.insert(scoped_key.to_string(), relative_path.to_string());
}
}
impl Default for DocTree {
fn default() -> Self {
Self::new(&TargetLanguage::English)
}
}
pub struct DiskOutlet {
doc_tree: DocTree,
}
impl DiskOutlet {
pub fn new(doc_tree: DocTree) -> Self {
Self { doc_tree }
}
}
impl Outlet for DiskOutlet {
async fn save(&self, context: &GeneratorContext) -> Result<()> {
println!("\n🖊️ Saving documentation...");
let output_dir = &context.config.output_path;
if output_dir.exists() {
fs::remove_dir_all(output_dir)?;
}
fs::create_dir_all(output_dir)?;
for (scoped_key, relative_path) in &self.doc_tree.structure {
if let Some(doc_markdown) = context
.get_from_memory::<String>(MemoryScope::DOCUMENTATION, scoped_key)
.await
{
let output_file_path = output_dir.join(relative_path);
if let Some(parent_dir) = output_file_path.parent() {
if !parent_dir.exists() {
fs::create_dir_all(parent_dir)?;
}
}
fs::write(&output_file_path, doc_markdown)?;
println!("💾 Document saved: {}", output_file_path.display());
} else {
let msg = context.config.target_language.msg_doc_not_found();
eprintln!("{}", msg.replace("{}", scoped_key));
}
}
println!("💾 Document save completed, output directory: {}", output_dir.display());
if let Err(e) = MermaidFixer::auto_fix_after_output(context).await {
let msg = context.config.target_language.msg_mermaid_error();
eprintln!("{}", msg.replace("{}", &e.to_string()));
eprintln!("💡 This will not affect the main documentation generation process");
}
Ok(())
}
}