openapi_nexus/
openapi_code_generator.rs1use std::path::Path;
4
5use tracing::{error, info};
6
7use crate::generator_registry::GeneratorRegistry;
8use openapi_nexus_common::GeneratorType;
9use openapi_nexus_config::Config;
10use openapi_nexus_core::traits::{CodeGenerator, FileWriter};
11use openapi_nexus_go::GoHttpCodeGenerator;
12use openapi_nexus_parser::parse_file;
13use openapi_nexus_typescript::TypeScriptFetchCodeGenerator;
14
15pub struct OpenApiCodeGenerator {
17 generator_registry: GeneratorRegistry,
18}
19
20impl OpenApiCodeGenerator {
21 pub fn new(config: &Config) -> Self {
23 let mut generator_registry = GeneratorRegistry::new();
24 generator_registry.register_generator(
25 GeneratorType::TypeScriptFetch,
26 TypeScriptFetchCodeGenerator::new(
27 config
28 .generators
29 .get(&GeneratorType::TypeScriptFetch)
30 .cloned()
31 .unwrap_or_default(),
32 ),
33 );
34 generator_registry.register_generator(
35 GeneratorType::GoHttp,
36 GoHttpCodeGenerator::new(
37 config
38 .generators
39 .get(&GeneratorType::GoHttp)
40 .cloned()
41 .unwrap_or_default(),
42 ),
43 );
44
45 Self { generator_registry }
46 }
47
48 pub fn register_generator<G>(&mut self, generator_type: GeneratorType, generator: G)
50 where
51 G: CodeGenerator + FileWriter + Send + Sync + 'static,
52 {
53 self.generator_registry
54 .register_generator(generator_type, generator)
55 }
56
57 pub fn generate(&self, config: &Config) {
60 info!("Parsing OpenAPI specification from: {}", config.input);
61 let openapi = match parse_file(Path::new(&config.input)) {
62 Ok(openapi) => openapi,
63 Err(e) => {
64 error!(
65 "Failed to parse OpenAPI file {:?}: {}. Skipping code generation.",
66 config.input, e
67 );
68 return;
69 }
70 };
71
72 let generators = config
74 .global
75 .generators
76 .as_ref()
77 .cloned()
78 .unwrap_or_default();
79
80 for generator_type in generators {
82 tracing::info!("Generating code with generator {}", generator_type);
83
84 if !self.generator_registry.has_generator(generator_type) {
86 error!("Generator {} not found. Skipping.", generator_type);
87 continue;
88 }
89
90 let generator = match self.generator_registry.get_generator(generator_type) {
92 Some(generator) => generator,
93 None => {
94 error!(
95 "Generator {} not found in registry. Skipping.",
96 generator_type
97 );
98 continue;
99 }
100 };
101
102 let files = match generator.generate(&openapi) {
103 Ok(files) => files,
104 Err(e) => {
105 error!(
106 "Failed to generate code with generator {}: {}. Continuing to next generator.",
107 generator_type, e
108 );
109 continue;
110 }
111 };
112
113 let output_dir = config.global.output_for_generator(generator_type);
115
116 if let Err(e) = generator.write_files(Path::new(&output_dir), &files) {
118 error!(
119 "Failed to write files for generator {}: {}. Continuing to next generator.",
120 generator_type, e
121 );
122 continue;
123 }
124
125 info!(
126 "Successfully generated {} files with generator {}",
127 files.len(),
128 generator_type
129 );
130 }
131 }
132}