ggen_core/codegen/
mod.rs

1//! Code generation module
2//!
3//! This module provides generators for different target languages and frameworks,
4//! converting OntologySchema into working code for TypeScript, GraphQL, SQL, and more.
5//!
6//! ## Semantic Code Generation (v5)
7//!
8//! The new semantic code generation pipeline transforms RDF ontologies through
9//! CONSTRUCT queries into typed code graphs, which are then rendered via Tera templates.
10//!
11//! ### Pipeline Flow
12//!
13//! ```text
14//! ontology.ttl → Graph → CONSTRUCT rules → Code Graph → Tera → .rs files
15//! ```
16//!
17//! ### Key Types
18//!
19//! - [`GenerationPipeline`] - Orchestrates the full generation flow
20//! - [`CodeGraphBuilder`] - Converts SPARQL results to code entities
21//! - [`AuditTrailBuilder`] - Tracks execution for determinism verification
22
23pub mod audit;
24pub mod code_graph;
25pub mod executor;
26pub mod pipeline;
27pub mod typescript;
28
29// Re-export key types
30pub use audit::{AuditOutput, AuditStep, AuditTrail, AuditTrailBuilder};
31pub use code_graph::{
32    CodeEnum, CodeField, CodeGraphBuilder, CodeImpl, CodeImport, CodeItem, CodeMethod, CodeModule,
33    CodeParam, CodeStruct, CodeTrait, CodeVariant,
34};
35pub use executor::{SyncExecutor, SyncResult, SyncedFileInfo, ValidationCheck};
36pub use pipeline::{
37    ExecutedRule, GeneratedFile, GenerationPipeline, PipelineState, RuleType, ValidationResult,
38    ValidationSeverity,
39};
40pub use typescript::TypeScriptGenerator;
41
42// ============================================================================
43// Sync Options (CLI Configuration for ggen sync)
44// ============================================================================
45
46/// Output format for `ggen sync` command results
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
48pub enum OutputFormat {
49    /// Human-readable text output (default)
50    #[default]
51    Text,
52    /// JSON output for CI/CD and automation
53    Json,
54}
55
56impl std::str::FromStr for OutputFormat {
57    type Err = String;
58
59    fn from_str(s: &str) -> Result<Self, Self::Err> {
60        match s.to_lowercase().as_str() {
61            "text" => Ok(OutputFormat::Text),
62            "json" => Ok(OutputFormat::Json),
63            _ => Err(format!(
64                "Invalid output format: '{}'. Expected 'text' or 'json'",
65                s
66            )),
67        }
68    }
69}
70
71impl std::fmt::Display for OutputFormat {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        match self {
74            OutputFormat::Text => write!(f, "text"),
75            OutputFormat::Json => write!(f, "json"),
76        }
77    }
78}
79
80/// Configuration options for `ggen sync` pipeline execution
81///
82/// These options control the behavior of the code synchronization pipeline,
83/// including dry-run mode, audit trail generation, and timeout limits.
84#[derive(Debug, Clone)]
85pub struct SyncOptions {
86    /// Path to the manifest file (default: ggen.toml)
87    pub manifest_path: std::path::PathBuf,
88
89    /// Override output directory from manifest
90    pub output_dir: Option<std::path::PathBuf>,
91
92    /// Preview changes without writing files
93    pub dry_run: bool,
94
95    /// Force overwrite of protected files
96    pub force: bool,
97
98    /// Generate audit trail (audit.json)
99    pub audit: bool,
100
101    /// Run only specific rules (by name)
102    pub selected_rules: Option<Vec<String>>,
103
104    /// Verbose output during execution
105    pub verbose: bool,
106
107    /// Watch for file changes and auto-regenerate
108    pub watch: bool,
109
110    /// Validate manifest without generating
111    pub validate_only: bool,
112
113    /// Output format for results
114    pub output_format: OutputFormat,
115
116    /// Maximum execution timeout in milliseconds
117    pub timeout_ms: u64,
118}
119
120impl Default for SyncOptions {
121    fn default() -> Self {
122        Self {
123            manifest_path: std::path::PathBuf::from("ggen.toml"),
124            output_dir: None,
125            dry_run: false,
126            force: false,
127            audit: false,
128            selected_rules: None,
129            verbose: false,
130            watch: false,
131            validate_only: false,
132            output_format: OutputFormat::default(),
133            timeout_ms: 30000, // 30 second default
134        }
135    }
136}
137
138impl SyncOptions {
139    /// Create new SyncOptions with default values
140    pub fn new() -> Self {
141        Self::default()
142    }
143
144    /// Create SyncOptions from a manifest path
145    pub fn from_manifest<P: AsRef<std::path::Path>>(path: P) -> Self {
146        Self {
147            manifest_path: path.as_ref().to_path_buf(),
148            ..Self::default()
149        }
150    }
151
152    /// Set dry-run mode
153    pub fn with_dry_run(mut self, dry_run: bool) -> Self {
154        self.dry_run = dry_run;
155        self
156    }
157
158    /// Set verbose output
159    pub fn with_verbose(mut self, verbose: bool) -> Self {
160        self.verbose = verbose;
161        self
162    }
163
164    /// Set audit trail generation
165    pub fn with_audit(mut self, audit: bool) -> Self {
166        self.audit = audit;
167        self
168    }
169
170    /// Set validate-only mode
171    pub fn with_validate_only(mut self, validate_only: bool) -> Self {
172        self.validate_only = validate_only;
173        self
174    }
175
176    /// Set output format
177    pub fn with_output_format(mut self, format: OutputFormat) -> Self {
178        self.output_format = format;
179        self
180    }
181
182    /// Set timeout in milliseconds
183    pub fn with_timeout_ms(mut self, timeout_ms: u64) -> Self {
184        self.timeout_ms = timeout_ms;
185        self
186    }
187
188    /// Set selected rules
189    pub fn with_rules(mut self, rules: Vec<String>) -> Self {
190        self.selected_rules = Some(rules);
191        self
192    }
193
194    /// Set force overwrite
195    pub fn with_force(mut self, force: bool) -> Self {
196        self.force = force;
197        self
198    }
199
200    /// Set output directory override
201    pub fn with_output_dir<P: AsRef<std::path::Path>>(mut self, dir: P) -> Self {
202        self.output_dir = Some(dir.as_ref().to_path_buf());
203        self
204    }
205}