Skip to main content

entrenar/cli/commands/research/
init.rs

1//! Research init subcommand
2
3use crate::cli::logging::log;
4use crate::cli::LogLevel;
5use crate::config::{ArtifactTypeArg, LicenseArg, ResearchInitArgs};
6use crate::research::{Affiliation, ArtifactType, Author, License, ResearchArtifact};
7
8/// Convert CLI artifact type argument to research domain type.
9fn convert_artifact_type(arg: &ArtifactTypeArg) -> ArtifactType {
10    match arg {
11        ArtifactTypeArg::Dataset => ArtifactType::Dataset,
12        ArtifactTypeArg::Paper => ArtifactType::Paper,
13        ArtifactTypeArg::Model => ArtifactType::Model,
14        ArtifactTypeArg::Code => ArtifactType::Code,
15        ArtifactTypeArg::Notebook => ArtifactType::Notebook,
16        ArtifactTypeArg::Workflow => ArtifactType::Workflow,
17    }
18}
19
20/// Convert CLI license argument to research domain license.
21fn convert_license(arg: &LicenseArg) -> License {
22    match arg {
23        LicenseArg::CcBy4 => License::CcBy4,
24        LicenseArg::CcBySa4 => License::Custom("CC-BY-SA-4.0".to_string()),
25        LicenseArg::Cc0 => License::Cc0,
26        LicenseArg::Mit => License::Mit,
27        LicenseArg::Apache2 => License::Apache2,
28        LicenseArg::Gpl3 => License::Gpl3,
29        LicenseArg::Bsd3 => License::Bsd3,
30    }
31}
32
33/// Build an Author from CLI arguments (name, optional ORCID and affiliation).
34fn build_author(args: &ResearchInitArgs) -> Result<Option<Author>, String> {
35    let Some(author_name) = &args.author else {
36        return Ok(None);
37    };
38    let mut author = Author::new(author_name);
39
40    if let Some(orcid) = &args.orcid {
41        author = author.with_orcid(orcid).map_err(|e| format!("Invalid ORCID: {e}"))?;
42    }
43    if let Some(affiliation) = &args.affiliation {
44        author = author.with_affiliation(Affiliation::new(affiliation));
45    }
46    Ok(Some(author))
47}
48
49pub fn run_research_init(args: ResearchInitArgs, level: LogLevel) -> Result<(), String> {
50    log(level, LogLevel::Normal, &format!("Initializing research artifact: {}", args.id));
51
52    let artifact_type = convert_artifact_type(&args.artifact_type);
53    let license = convert_license(&args.license);
54    let mut artifact = ResearchArtifact::new(&args.id, &args.title, artifact_type, license);
55
56    if let Some(author) = build_author(&args)? {
57        artifact = artifact.with_author(author);
58    }
59
60    if let Some(description) = &args.description {
61        artifact = artifact.with_description(description);
62    }
63    if let Some(keywords) = &args.keywords {
64        let kw: Vec<&str> = keywords.split(',').map(str::trim).collect();
65        artifact = artifact.with_keywords(kw);
66    }
67    if let Some(doi) = &args.doi {
68        artifact = artifact.with_doi(doi);
69    }
70
71    let yaml = serde_yaml::to_string(&artifact).map_err(|e| format!("Serialization error: {e}"))?;
72    std::fs::write(&args.output, &yaml).map_err(|e| format!("Failed to write file: {e}"))?;
73
74    log(level, LogLevel::Normal, &format!("Artifact saved to: {}", args.output.display()));
75
76    Ok(())
77}