tix-tracker 0.12.0

A terminal issue tracker: markdown + YAML frontmatter issues with a kanban TUI and CLI
Documentation
#[allow(clippy::wildcard_imports)]
use super::*;

pub(super) fn create_template(_config: &Config, _store: &Store, args: &Value) -> ToolOutcome {
    let id = req_string(args, "id")?;
    let definition = match template_definition(args, "create") {
        Ok(definition) => definition,
        Err(outcome) => return outcome,
    };
    let (mut config, path) = match template_management_config() {
        Ok(loaded) => loaded,
        Err(error) => return Ok(error_result(crate::error::render_error(&error))),
    };
    let outcome = {
        let mut service = TemplateService::new(&mut config, &path);
        service.create(&id, definition)
    };
    match outcome {
        Ok(outcome) => Ok(success_result(
            format!("created template `{}`", outcome.value()),
            template_outcome_value(
                "create",
                "accepted",
                template_registry_value(&config, outcome.value()),
                Vec::new(),
            ),
        )),
        Err(error) => Ok(template_write_refusal("create", &error)),
    }
}

pub(super) fn delete_template(_config: &Config, _store: &Store, args: &Value) -> ToolOutcome {
    let reference = req_string(args, "template")?;
    // The schema declares `confirm` required, but a schema is documentation a
    // client may ignore, and a write tool whose confirmation is optional is a
    // write tool a client can call by accident (C-004). Checked before anything
    // is loaded, so a forgotten confirmation writes nothing at all.
    if opt_bool(args, "confirm")? != Some(true) {
        return Ok(template_error_result(
            "invalid input: `confirm` must be true to delete a template definition".to_string(),
            template_outcome_value(
                "delete",
                "rejected",
                None,
                vec![json!({
                    "kind": "missing-confirmation",
                    "field": "confirm",
                    "message": "requires `confirm: true`",
                })],
            ),
        ));
    }
    let (mut config, path) = match template_management_config() {
        Ok(loaded) => loaded,
        Err(error) => return Ok(error_result(crate::error::render_error(&error))),
    };
    let outcome = {
        let mut service = TemplateService::new(&mut config, &path);
        service.delete(&reference, TemplateDeleteConfirmed::confirmed())
    };
    match outcome {
        Ok(outcome) => {
            let detail = outcome.value();
            Ok(success_result(
                format!("deleted template `{}`", detail.id()),
                template_outcome_value(
                    "delete",
                    "accepted",
                    Some(template_value(detail)),
                    Vec::new(),
                ),
            ))
        }
        Err(error) => Ok(template_write_refusal("delete", &error)),
    }
}

pub(super) fn duplicate_template(_config: &Config, _store: &Store, args: &Value) -> ToolOutcome {
    let reference = req_string(args, "template")?;
    let new_id = opt_string(args, "new_id")?;
    let name = opt_string(args, "name")?;
    let (mut config, path) = match template_management_config() {
        Ok(loaded) => loaded,
        Err(error) => return Ok(error_result(crate::error::render_error(&error))),
    };
    let outcome = {
        let mut service = TemplateService::new(&mut config, &path);
        service.duplicate(&reference, new_id.as_deref(), name.as_deref())
    };
    match outcome {
        Ok(outcome) => {
            let detail = outcome.value();
            Ok(success_result(
                format!("duplicated template `{reference}` as `{}`", detail.id()),
                template_outcome_value(
                    "duplicate",
                    "accepted",
                    Some(template_value(detail)),
                    Vec::new(),
                ),
            ))
        }
        Err(error) => Ok(template_write_refusal("duplicate", &error)),
    }
}

pub(super) fn get_template(_config: &Config, _store: &Store, args: &Value) -> ToolOutcome {
    let reference = req_string(args, "template")?;
    let (mut config, path) = match template_management_config() {
        Ok(loaded) => loaded,
        Err(error) => return Ok(error_result(crate::error::render_error(&error))),
    };
    let service = TemplateService::new(&mut config, &path);
    match service.show(&reference) {
        Ok(detail) => Ok(success_result(
            cmd_templates::render_detail(&detail),
            json!({ "template": template_value(&detail) }),
        )),
        Err(error) => Ok(error_result(crate::error::render_error(&error))),
    }
}

pub(super) fn list_templates(_config: &Config, _store: &Store, _args: &Value) -> ToolOutcome {
    let (mut config, path) = match template_management_config() {
        Ok(loaded) => loaded,
        Err(error) => return Ok(error_result(crate::error::render_error(&error))),
    };
    let service = TemplateService::new(&mut config, &path);
    let details = service.list();
    let templates: Vec<Value> = details.iter().map(template_value).collect();
    Ok(success_result(
        cmd_templates::render_list(&details),
        json!({ "templates": templates }),
    ))
}

pub(super) fn update_template(_config: &Config, _store: &Store, args: &Value) -> ToolOutcome {
    let reference = req_string(args, "template")?;
    let definition = match template_definition(args, "update") {
        Ok(definition) => definition,
        Err(outcome) => return outcome,
    };
    let (mut config, path) = match template_management_config() {
        Ok(loaded) => loaded,
        Err(error) => return Ok(error_result(crate::error::render_error(&error))),
    };
    let outcome = {
        let mut service = TemplateService::new(&mut config, &path);
        service.update(&reference, definition)
    };
    match outcome {
        Ok(outcome) => {
            let id = outcome.value();
            let (status, text) = if outcome.is_noop() {
                ("no-op", format!("unchanged template `{id}`"))
            } else {
                ("accepted", format!("updated template `{id}`"))
            };
            Ok(success_result(
                text,
                template_outcome_value(
                    "update",
                    status,
                    template_registry_value(&config, id),
                    Vec::new(),
                ),
            ))
        }
        Err(error) => Ok(template_write_refusal("update", &error)),
    }
}

pub(super) fn dispatch(
    config: &Config,
    store: &Store,
    name: &str,
    arguments: &Value,
) -> Option<ToolOutcome> {
    match name {
        "list_templates" => Some(list_templates(config, store, arguments)),
        "get_template" => Some(get_template(config, store, arguments)),
        "create_template" => Some(create_template(config, store, arguments)),
        "update_template" => Some(update_template(config, store, arguments)),
        "duplicate_template" => Some(duplicate_template(config, store, arguments)),
        "delete_template" => Some(delete_template(config, store, arguments)),
        _ => None,
    }
}