openapi_nexus_core/
openapi_code_generator.rs1use std::path::Path;
4
5use snafu::ResultExt as _;
6use tracing::error;
7
8use crate::error;
9use crate::generator_registry::{GeneratorRegistry, LanguageGenerator};
10use openapi_nexus_common::Language;
11use openapi_nexus_parser::parse_file;
12
13pub struct OpenApiCodeGenerator {
15 generator_registry: GeneratorRegistry,
16}
17
18impl OpenApiCodeGenerator {
19 pub fn new() -> Self {
21 Self {
22 generator_registry: GeneratorRegistry::new(),
23 }
24 }
25
26 pub fn register_language_generator<G>(
28 &mut self,
29 language: Language,
30 generator: G,
31 ) -> Result<(), error::Error>
32 where
33 G: LanguageGenerator + Send + Sync + 'static,
34 {
35 self.generator_registry
36 .register_generator(language, generator)
37 .map_err(|msg| {
38 error!(
39 "Failed to register language generator for {}: {}",
40 language, msg
41 );
42 error::Error::Generate {
43 source: Box::new(std::io::Error::other(msg)),
44 }
45 })
46 }
47
48 pub fn generate_from_file<P: AsRef<Path>>(
50 &self,
51 input_path: P,
52 output_dir: P,
53 language: Language,
54 ) -> Result<(), error::Error> {
55 tracing::info!(
56 "Parsing OpenAPI specification from: {:?}",
57 input_path.as_ref()
58 );
59 let openapi = parse_file(input_path.as_ref())
60 .map_err(|e| {
61 error!(
62 "Failed to parse OpenAPI file {:?}: {}",
63 input_path.as_ref(),
64 e
65 );
66 e
67 })
68 .context(error::ParseSnafu)?;
69
70 tracing::info!("Generating {} code", language);
71
72 if !self.generator_registry.has_generator(language) {
74 let err = error::Error::GeneratorNotFound {
75 language: language.to_string(),
76 };
77 error!("{}", err);
78 return Err(err);
79 }
80
81 let generator = self
83 .generator_registry
84 .get_generator(language)
85 .ok_or_else(|| {
86 let err = error::Error::GeneratorNotFound {
87 language: language.to_string(),
88 };
89 error!("{}", err);
90 err
91 })?;
92
93 let files = generator.generate(&openapi).map_err(|e| {
94 error!("Failed to generate code for {}: {}", language, e);
95 error::Error::Generate { source: e }
96 })?;
97
98 generator
100 .write_files(output_dir.as_ref(), &files)
101 .map_err(|e| {
102 error!("Failed to write files for {}: {}", language, e);
103 error::Error::Generate { source: e }
104 })?;
105
106 tracing::info!(
107 "Successfully generated {} files for {}",
108 files.len(),
109 language
110 );
111
112 Ok(())
113 }
114}
115
116impl Default for OpenApiCodeGenerator {
117 fn default() -> Self {
118 Self::new()
119 }
120}