Skip to main content

memo_cli/output/
json.rs

1use serde::Serialize;
2
3use crate::errors::AppError;
4
5#[derive(Debug, Serialize)]
6struct JsonResultEnvelope<'a, T>
7where
8    T: Serialize,
9{
10    schema_version: &'a str,
11    command: &'a str,
12    ok: bool,
13    result: T,
14}
15
16#[derive(Debug, Serialize)]
17struct JsonResultsEnvelope<'a, T>
18where
19    T: Serialize,
20{
21    schema_version: &'a str,
22    command: &'a str,
23    ok: bool,
24    results: T,
25}
26
27#[derive(Debug, Serialize)]
28struct JsonResultsEnvelopeWithMeta<'a, T>
29where
30    T: Serialize,
31{
32    schema_version: &'a str,
33    command: &'a str,
34    ok: bool,
35    results: T,
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pagination: Option<serde_json::Value>,
38    #[serde(skip_serializing_if = "Option::is_none")]
39    meta: Option<serde_json::Value>,
40}
41
42#[derive(Debug, Serialize)]
43struct JsonErrorEnvelope<'a> {
44    schema_version: &'a str,
45    command: &'a str,
46    ok: bool,
47    error: crate::errors::JsonError<'a>,
48}
49
50pub fn emit_json_result<T>(schema_version: &str, command: &str, result: T) -> Result<(), AppError>
51where
52    T: Serialize,
53{
54    let envelope = JsonResultEnvelope {
55        schema_version,
56        command,
57        ok: true,
58        result,
59    };
60    print_json(&envelope)
61}
62
63pub fn emit_json_results<T>(schema_version: &str, command: &str, results: T) -> Result<(), AppError>
64where
65    T: Serialize,
66{
67    let envelope = JsonResultsEnvelope {
68        schema_version,
69        command,
70        ok: true,
71        results,
72    };
73    print_json(&envelope)
74}
75
76pub fn emit_json_results_with_meta<T>(
77    schema_version: &str,
78    command: &str,
79    results: T,
80    pagination: Option<serde_json::Value>,
81    meta: Option<serde_json::Value>,
82) -> Result<(), AppError>
83where
84    T: Serialize,
85{
86    let envelope = JsonResultsEnvelopeWithMeta {
87        schema_version,
88        command,
89        ok: true,
90        results,
91        pagination,
92        meta,
93    };
94    print_json(&envelope)
95}
96
97pub fn emit_json_error(
98    schema_version: &str,
99    command: &str,
100    err: &AppError,
101) -> Result<(), AppError> {
102    let envelope = JsonErrorEnvelope {
103        schema_version,
104        command,
105        ok: false,
106        error: err.json_error(),
107    };
108    print_json(&envelope)
109}
110
111fn print_json<T>(value: &T) -> Result<(), AppError>
112where
113    T: Serialize,
114{
115    let encoded = serde_json::to_string(value).map_err(|err| {
116        AppError::runtime(format!("failed to serialize JSON output: {err}"))
117            .with_code("internal-error")
118    })?;
119    println!("{encoded}");
120    Ok(())
121}