use ggen_core::project_generator::{create_new_project, ProjectConfig, ProjectType};
use ggen_utils::error::Result;
#[derive(Debug, Clone, Default)]
pub struct NewInput {
pub name: String,
pub project_type: String,
pub framework: Option<String>,
pub output: Option<String>,
pub skip_install: bool,
}
#[derive(Debug, Clone)]
pub struct CreationResult {
pub project_path: String,
pub next_steps: String,
}
pub fn create_project(args: &NewInput) -> Result<CreationResult> {
ggen_core::project_generator::common::validate_project_name(&args.name)?;
let project_type: ProjectType = args.project_type.parse()?;
let output_path = args
.output
.as_deref()
.map(std::path::PathBuf::from)
.unwrap_or_else(|| std::path::PathBuf::from("."));
let config = ProjectConfig {
name: args.name.clone(),
project_type: project_type.clone(),
framework: args.framework.clone(),
path: output_path,
};
let runtime = tokio::runtime::Runtime::new()
.map_err(|e| ggen_utils::error::Error::new_fmt(format_args!("Runtime error: {}", e)))?;
runtime.block_on(async { create_new_project(&config).await })?;
let next_steps = match project_type {
ProjectType::RustWeb | ProjectType::RustCli | ProjectType::RustLib => {
" cargo run".to_string()
}
ProjectType::NextJs | ProjectType::Nuxt => {
if !args.skip_install {
" npm run dev".to_string()
} else {
" npm install\n npm run dev".to_string()
}
}
};
let output_dir = args.output.as_deref().unwrap_or(".");
let project_path = std::path::Path::new(output_dir).join(&args.name);
Ok(CreationResult {
project_path: project_path.display().to_string(),
next_steps,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_validate_project_name() {
assert!(ggen_core::project_generator::common::validate_project_name("my-project").is_ok());
assert!(ggen_core::project_generator::common::validate_project_name("my_project").is_ok());
assert!(ggen_core::project_generator::common::validate_project_name("my project").is_err());
assert!(ggen_core::project_generator::common::validate_project_name("").is_err());
}
#[test]
fn test_next_steps_rust() {
let args = NewInput {
name: "test-project".to_string(),
project_type: "rust-cli".to_string(),
framework: None,
output: Some("/tmp".to_string()),
skip_install: false,
};
let project_type: ProjectType = args.project_type.parse().unwrap();
let next_steps = match project_type {
ProjectType::RustWeb | ProjectType::RustCli | ProjectType::RustLib => {
" cargo run".to_string()
}
_ => String::new(),
};
assert_eq!(next_steps, " cargo run");
}
}