baobao_codegen/traits.rs
1//! Language-agnostic code generation traits.
2
3use std::path::Path;
4
5use baobao_core::{ArgType, ContextFieldType};
6use eyre::Result;
7
8/// Trait for language-specific code generators.
9///
10/// Implement this trait to add support for generating CLI code in a new language.
11pub trait LanguageCodegen {
12 /// Language identifier (e.g., "rust", "typescript", "go")
13 fn language(&self) -> &'static str;
14
15 /// File extension for generated source files (e.g., "rs", "ts", "go")
16 fn file_extension(&self) -> &'static str;
17
18 /// Preview generated files without writing to disk
19 fn preview(&self) -> Vec<PreviewFile>;
20
21 /// Generate all files into the specified output directory
22 fn generate(&self, output_dir: &Path) -> Result<GenerateResult>;
23}
24
25/// Result of code generation
26#[derive(Debug, Default)]
27pub struct GenerateResult {
28 /// Handler files that were created (stubs for new commands)
29 pub created_handlers: Vec<String>,
30 /// Handler files that exist but are no longer used
31 pub orphan_handlers: Vec<String>,
32}
33
34/// Result of cleaning orphaned files
35#[derive(Debug, Default)]
36pub struct CleanResult {
37 /// Generated command files that were deleted
38 pub deleted_commands: Vec<String>,
39 /// Handler files that were deleted (unmodified stubs)
40 pub deleted_handlers: Vec<String>,
41 /// Handler files that were skipped (modified by user)
42 pub skipped_handlers: Vec<String>,
43}
44
45/// A generated file for preview
46#[derive(Debug)]
47pub struct PreviewFile {
48 /// Relative path from output directory
49 pub path: String,
50 /// File content
51 pub content: String,
52}
53
54/// Trait for mapping schema types to language-specific type strings.
55///
56/// Implement this trait for each target language to provide type mappings.
57pub trait TypeMapper {
58 /// The target language name
59 fn language(&self) -> &'static str;
60
61 /// Map an argument type to a language-specific type string
62 fn map_arg_type(&self, arg_type: ArgType) -> &'static str;
63
64 /// Map an optional argument type (e.g., `Option<String>` in Rust, `string | undefined` in TS)
65 fn map_optional_arg_type(&self, arg_type: ArgType) -> String {
66 // Default implementation - languages can override
67 format!("Option<{}>", self.map_arg_type(arg_type))
68 }
69
70 /// Map a context field type to a language-specific type string
71 fn map_context_type(&self, field_type: &ContextFieldType) -> &'static str;
72}