nils-memo-cli 0.3.3

CLI crate for nils-memo-cli in the nils-cli workspace.
Documentation
use serde::Serialize;

use crate::errors::AppError;

#[derive(Debug, Serialize)]
struct JsonResultEnvelope<'a, T>
where
    T: Serialize,
{
    schema_version: &'a str,
    command: &'a str,
    ok: bool,
    result: T,
}

#[derive(Debug, Serialize)]
struct JsonResultsEnvelope<'a, T>
where
    T: Serialize,
{
    schema_version: &'a str,
    command: &'a str,
    ok: bool,
    results: T,
}

#[derive(Debug, Serialize)]
struct JsonResultsEnvelopeWithMeta<'a, T>
where
    T: Serialize,
{
    schema_version: &'a str,
    command: &'a str,
    ok: bool,
    results: T,
    #[serde(skip_serializing_if = "Option::is_none")]
    pagination: Option<serde_json::Value>,
    #[serde(skip_serializing_if = "Option::is_none")]
    meta: Option<serde_json::Value>,
}

#[derive(Debug, Serialize)]
struct JsonErrorEnvelope<'a> {
    schema_version: &'a str,
    command: &'a str,
    ok: bool,
    error: crate::errors::JsonError<'a>,
}

pub fn emit_json_result<T>(schema_version: &str, command: &str, result: T) -> Result<(), AppError>
where
    T: Serialize,
{
    let envelope = JsonResultEnvelope {
        schema_version,
        command,
        ok: true,
        result,
    };
    print_json(&envelope)
}

pub fn emit_json_results<T>(schema_version: &str, command: &str, results: T) -> Result<(), AppError>
where
    T: Serialize,
{
    let envelope = JsonResultsEnvelope {
        schema_version,
        command,
        ok: true,
        results,
    };
    print_json(&envelope)
}

pub fn emit_json_results_with_meta<T>(
    schema_version: &str,
    command: &str,
    results: T,
    pagination: Option<serde_json::Value>,
    meta: Option<serde_json::Value>,
) -> Result<(), AppError>
where
    T: Serialize,
{
    let envelope = JsonResultsEnvelopeWithMeta {
        schema_version,
        command,
        ok: true,
        results,
        pagination,
        meta,
    };
    print_json(&envelope)
}

pub fn emit_json_error(
    schema_version: &str,
    command: &str,
    err: &AppError,
) -> Result<(), AppError> {
    let envelope = JsonErrorEnvelope {
        schema_version,
        command,
        ok: false,
        error: err.json_error(),
    };
    print_json(&envelope)
}

fn print_json<T>(value: &T) -> Result<(), AppError>
where
    T: Serialize,
{
    let encoded = serde_json::to_string(value).map_err(|err| {
        AppError::runtime(format!("failed to serialize JSON output: {err}"))
            .with_code("internal-error")
    })?;
    println!("{encoded}");
    Ok(())
}