Skip to main content

cuenv_codegen/
lib.rs

1//! # cuenv-codegen
2//!
3//! CUE-powered code generation and project scaffolding from CUE templates.
4//!
5//! This crate provides a code generation system that:
6//! - Uses schema-wrapped code blocks (e.g., `schema.#TypeScript`, `schema.#JSON`)
7//! - Supports managed (always regenerated) and scaffold (generate once) file modes
8//! - Integrates with `cuenv sync codegen` command
9//!
10//! ## How it works
11//!
12//! A Codegen configuration is a CUE-based template that defines multiple
13//! files to generate for a project. Define your files in CUE with type-safe
14//! schemas, then sync them with `cuenv sync codegen`.
15//!
16//! ## Example
17//!
18//! ```cue
19//! schema.#Project & {
20//!     name: "my-service"
21//!     codegen: {
22//!         files: {
23//!             "package.json": schema.#JSON & {
24//!                 mode: "managed"
25//!                 content: """{"name": "my-service"}"""
26//!             }
27//!         }
28//!     }
29//! }
30//! ```
31
32#![warn(missing_docs)]
33#![warn(clippy::all)]
34#![warn(clippy::pedantic)]
35
36pub mod codegen;
37pub mod config;
38pub mod formatter;
39pub mod generator;
40
41pub use codegen::Codegen;
42pub use generator::{GenerateOptions, Generator};
43
44use thiserror::Error;
45
46/// Errors that can occur during code generation
47#[derive(Error, Debug)]
48pub enum CodegenError {
49    /// Error loading or evaluating CUE codegen configuration
50    #[error("Codegen error: {0}")]
51    Codegen(String),
52
53    /// Error during file generation
54    #[error("Generation error: {0}")]
55    Generation(String),
56
57    /// Error during formatting
58    #[error("Formatting error: {0}")]
59    Formatting(String),
60
61    /// IO error
62    #[error("IO error: {0}")]
63    Io(#[from] std::io::Error),
64
65    /// JSON error
66    #[error("JSON error: {0}")]
67    Json(#[from] serde_json::Error),
68}
69
70/// Result type for codegen operations
71pub type Result<T> = std::result::Result<T, CodegenError>;
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn test_codegen_error_codegen_display() {
79        let error = CodegenError::Codegen("test codegen error".to_string());
80        assert_eq!(error.to_string(), "Codegen error: test codegen error");
81    }
82
83    #[test]
84    fn test_codegen_error_generation_display() {
85        let error = CodegenError::Generation("test generation error".to_string());
86        assert_eq!(error.to_string(), "Generation error: test generation error");
87    }
88
89    #[test]
90    fn test_codegen_error_formatting_display() {
91        let error = CodegenError::Formatting("test formatting error".to_string());
92        assert_eq!(error.to_string(), "Formatting error: test formatting error");
93    }
94
95    #[test]
96    fn test_codegen_error_io_from() {
97        let io_error = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
98        let error: CodegenError = io_error.into();
99        assert!(matches!(error, CodegenError::Io(_)));
100        assert!(error.to_string().contains("file not found"));
101    }
102
103    #[test]
104    fn test_codegen_error_json_from() {
105        let json_str = "{ invalid json }";
106        let json_error = serde_json::from_str::<serde_json::Value>(json_str).unwrap_err();
107        let error: CodegenError = json_error.into();
108        assert!(matches!(error, CodegenError::Json(_)));
109        assert!(error.to_string().contains("JSON error"));
110    }
111}