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}