forge-codegen 0.0.1-alpha

TypeScript code generator for the Forge framework
Documentation
mod api;
mod client;
mod stores;
mod types;

pub use api::ApiGenerator;
pub use client::ClientGenerator;
pub use stores::StoreGenerator;
pub use types::TypeGenerator;

use std::path::PathBuf;

use forge_core::schema::SchemaRegistry;

/// TypeScript code generator for FORGE.
///
/// Generates TypeScript types, API bindings, and Svelte stores from Rust schema.
pub struct TypeScriptGenerator {
    /// Output directory for generated files.
    output_dir: PathBuf,
    /// Type generator.
    type_gen: TypeGenerator,
    /// API generator.
    api_gen: ApiGenerator,
    /// Client generator.
    client_gen: ClientGenerator,
    /// Store generator.
    store_gen: StoreGenerator,
}

impl TypeScriptGenerator {
    /// Create a new TypeScript generator.
    pub fn new(output_dir: impl Into<PathBuf>) -> Self {
        let output_dir = output_dir.into();
        Self {
            output_dir: output_dir.clone(),
            type_gen: TypeGenerator::new(output_dir.clone()),
            api_gen: ApiGenerator::new(output_dir.clone()),
            client_gen: ClientGenerator::new(output_dir.clone()),
            store_gen: StoreGenerator::new(output_dir),
        }
    }

    /// Generate all TypeScript artifacts.
    pub fn generate(&self, registry: &SchemaRegistry) -> Result<(), Error> {
        // Ensure output directory exists
        std::fs::create_dir_all(&self.output_dir)?;

        // Generate types
        let types_content = self.type_gen.generate(registry)?;
        std::fs::write(self.output_dir.join("types.ts"), types_content)?;

        // Generate API bindings
        let api_content = self.api_gen.generate(registry)?;
        std::fs::write(self.output_dir.join("api.ts"), api_content)?;

        // Generate client
        let client_content = self.client_gen.generate()?;
        std::fs::write(self.output_dir.join("client.ts"), client_content)?;

        // Generate stores
        let stores_content = self.store_gen.generate()?;
        std::fs::write(self.output_dir.join("stores.ts"), stores_content)?;

        // Generate index
        let index_content = self.generate_index();
        std::fs::write(self.output_dir.join("index.ts"), index_content)?;

        Ok(())
    }

    /// Generate the index.ts barrel export.
    fn generate_index(&self) -> String {
        r#"// Auto-generated by FORGE - DO NOT EDIT
export * from './types';
export * from './api';
export * from './client';
export * from './stores';
"#
        .to_string()
    }

    /// Get the output directory.
    pub fn output_dir(&self) -> &PathBuf {
        &self.output_dir
    }
}

/// Code generation error.
#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),

    #[error("Serialization error: {0}")]
    Serialization(String),

    #[error("Template error: {0}")]
    Template(String),
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_generator_creation() {
        let gen = TypeScriptGenerator::new("/tmp/forge");
        assert_eq!(gen.output_dir(), &PathBuf::from("/tmp/forge"));
    }

    #[test]
    fn test_generate_index() {
        let gen = TypeScriptGenerator::new("/tmp/forge");
        let index = gen.generate_index();
        assert!(index.contains("export * from './types'"));
        assert!(index.contains("export * from './api'"));
        assert!(index.contains("export * from './client'"));
        assert!(index.contains("export * from './stores'"));
    }
}