cartulary 0.3.0-alpha.1

The knowledge layer of your project — decisions, issues, docs, all in one place.
Documentation
//! Generic `created` command — read-only accessor for the creation
//! date of an issue or decision record.
//!
//! Date is event-log derived (carried by the `Created` event); there
//! is no `update` verb by design.

use clap::{Arg, Command};

use crate::infra::driving::cli::errors::{die1, CliError};
use crate::infra::driving::cli::output::OutputFormat;
use crate::infra::driving::cli::render_structured;

pub(crate) fn subcommand(noun: &'static str, id_help: &'static str) -> Command {
    let article = super::indefinite(noun);
    Command::new("created")
        .about(format!("Read the creation date of {article}"))
        .subcommand_required(true)
        .arg_required_else_help(true)
        .subcommand(
            Command::new("show")
                .about(format!("Print the creation date of {article}"))
                .arg(id_arg(id_help)),
        )
}

fn id_arg(help: &'static str) -> Arg {
    Arg::new("id").required(true).value_name("ID").help(help)
}

pub(crate) enum View {
    NotFound,
    Shown { date: String },
}

pub(crate) fn render(
    view: View,
    display_id: &str,
    canonical_id: &str,
    noun: &str,
    output_fmt: OutputFormat,
) {
    match view {
        View::NotFound => die1(
            CliError::not_found(format!("{noun} '{display_id}'"), &format!("{noun} list")),
            output_fmt,
        ),
        View::Shown { date } if output_fmt.is_structured() => {
            #[derive(serde::Serialize)]
            struct CreatedResult<'a> {
                id: &'a str,
                created: &'a str,
            }
            render_structured(
                &CreatedResult {
                    id: canonical_id,
                    created: &date,
                },
                output_fmt,
            );
        }
        View::Shown { date } => println!("{date}"),
    }
}