openapi_nexus/codegen/traits/
file_writer.rs1use std::collections::HashMap;
4use std::fs;
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
8pub enum FileCategory {
9 None,
12 Readme,
14 Apis,
16 Models,
18 ProjectFiles,
20 Runtime,
22}
23
24#[derive(Debug, Clone)]
26pub struct FileInfo {
27 pub filename: String,
28 pub content: String,
29 pub category: FileCategory,
30}
31
32impl FileInfo {
33 pub fn new(filename: String, content: String, category: FileCategory) -> Self {
35 Self {
36 filename,
37 content,
38 category,
39 }
40 }
41
42 pub fn none(filename: String, content: String) -> Self {
44 Self::new(filename, content, FileCategory::None)
45 }
46
47 pub fn readme(filename: String, content: String) -> Self {
49 Self::new(filename, content, FileCategory::Readme)
50 }
51
52 pub fn api(filename: String, content: String) -> Self {
54 Self::new(filename, content, FileCategory::Apis)
55 }
56
57 pub fn model(filename: String, content: String) -> Self {
59 Self::new(filename, content, FileCategory::Models)
60 }
61
62 pub fn project(filename: String, content: String) -> Self {
64 Self::new(filename, content, FileCategory::ProjectFiles)
65 }
66
67 pub fn runtime(filename: String, content: String) -> Self {
69 Self::new(filename, content, FileCategory::Runtime)
70 }
71}
72
73pub trait FileWriter {
75 fn source_dir(&self) -> Option<&str> {
79 None
80 }
81
82 fn write_files(
84 &self,
85 output_dir: &std::path::Path,
86 files: &[FileInfo],
87 ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
88 let mut files_by_category: HashMap<FileCategory, Vec<&FileInfo>> = HashMap::new();
90 for file in files {
91 files_by_category
92 .entry(file.category.clone())
93 .or_default()
94 .push(file);
95 }
96
97 let source_root = self
98 .source_dir()
99 .map(|d| output_dir.join(d))
100 .unwrap_or_else(|| output_dir.to_path_buf());
101
102 for (category, category_files) in files_by_category {
104 let category_dir = match category {
105 FileCategory::None => continue,
106 FileCategory::Readme => output_dir.to_path_buf(),
107 FileCategory::Apis => source_root.join("apis"),
108 FileCategory::Models => source_root.join("models"),
109 FileCategory::ProjectFiles => output_dir.to_path_buf(),
110 FileCategory::Runtime => source_root.join("runtime"),
111 };
112
113 if !category_dir.exists() {
115 fs::create_dir_all(&category_dir)?;
116 }
117
118 for file in category_files {
120 let file_path = category_dir.join(&file.filename);
121
122 if let Some(parent) = file_path.parent() {
124 fs::create_dir_all(parent)?;
125 }
126
127 fs::write(&file_path, &file.content)?;
128 }
129 }
130
131 Ok(())
132 }
133}