1use crate::root_envelopes::{RootEnvelopeMode, serialize_named_json_output};
4use serde::Serialize;
5
6#[derive(Debug, Clone, Serialize)]
9#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
10pub struct ListOutput<Boundaries, Diagnostic> {
11 #[serde(default, skip_serializing_if = "Option::is_none")]
12 pub plugins: Option<Vec<ListPluginOutput>>,
13 #[serde(default, skip_serializing_if = "Option::is_none")]
14 pub file_count: Option<usize>,
15 #[serde(default, skip_serializing_if = "Option::is_none")]
16 pub files: Option<Vec<String>>,
17 #[serde(default, skip_serializing_if = "Option::is_none")]
18 pub entry_point_count: Option<usize>,
19 #[serde(default, skip_serializing_if = "Option::is_none")]
20 pub entry_points: Option<Vec<ListEntryPointOutput>>,
21 #[serde(default, skip_serializing_if = "Option::is_none")]
22 pub boundaries: Option<Boundaries>,
23 #[serde(default, skip_serializing_if = "Option::is_none")]
24 pub workspace_count: Option<usize>,
25 #[serde(default, skip_serializing_if = "Option::is_none")]
26 pub workspaces: Option<Vec<WorkspaceInfo>>,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub workspace_diagnostics: Option<Vec<Diagnostic>>,
29}
30
31#[derive(Debug, Clone, Serialize)]
33#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
34pub struct ListPluginOutput {
35 pub name: String,
36}
37
38#[derive(Debug, Clone, Serialize)]
40#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
41pub struct ListEntryPointOutput {
42 pub path: String,
43 pub source: String,
44}
45
46#[derive(Debug, Clone, Serialize)]
51#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
52#[cfg_attr(
53 feature = "schema",
54 schemars(title = "fallow list --boundaries --format json")
55)]
56pub struct ListBoundariesOutput<Status, Rule> {
57 pub boundaries: BoundariesListing<Status, Rule>,
58}
59
60#[derive(Debug, Clone, Serialize)]
62#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
63#[cfg_attr(
64 feature = "schema",
65 schemars(title = "fallow workspaces --format json")
66)]
67pub struct WorkspacesOutput<Diagnostic> {
68 pub workspace_count: usize,
70 pub workspaces: Vec<WorkspaceInfo>,
73 pub workspace_diagnostics: Vec<Diagnostic>,
77}
78
79#[derive(Debug, Clone, Serialize)]
81#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
82pub struct WorkspaceInfo {
83 pub name: String,
86 pub path: String,
89 pub is_internal_dependency: bool,
92}
93
94#[derive(Debug, Clone, Serialize)]
96#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
97pub struct BoundariesListing<Status, Rule> {
98 pub configured: bool,
99 pub zone_count: usize,
100 pub zones: Vec<BoundariesListZone>,
101 pub rule_count: usize,
102 pub rules: Vec<BoundariesListRule>,
103 pub logical_group_count: usize,
104 pub logical_groups: Vec<BoundariesListLogicalGroup<Status, Rule>>,
105}
106
107#[derive(Debug, Clone, Serialize)]
110#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
111pub struct BoundariesListZone {
112 pub name: String,
113 pub patterns: Vec<String>,
114 pub file_count: usize,
115}
116
117#[derive(Debug, Clone, Serialize)]
122#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
123pub struct BoundariesListRule {
124 pub from: String,
125 pub allow: Vec<String>,
126}
127
128#[derive(Debug, Clone, Serialize)]
133#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
134pub struct BoundariesListLogicalGroup<Status, Rule> {
135 pub name: String,
136 pub children: Vec<String>,
137 pub auto_discover: Vec<String>,
138 pub status: Status,
139 pub source_zone_index: usize,
140 pub file_count: usize,
141 #[serde(default, skip_serializing_if = "Option::is_none")]
142 pub authored_rule: Option<Rule>,
143 #[serde(default, skip_serializing_if = "Option::is_none")]
144 pub fallback_zone: Option<String>,
145 #[serde(default, skip_serializing_if = "Option::is_none")]
146 pub merged_from: Option<Vec<usize>>,
147 #[serde(default, skip_serializing_if = "Option::is_none")]
148 pub original_zone_root: Option<String>,
149 #[serde(default, skip_serializing_if = "Vec::is_empty")]
150 pub child_source_indices: Vec<usize>,
151}
152
153pub fn serialize_list_boundaries_json_output<T: Serialize>(
159 output: T,
160 mode: RootEnvelopeMode,
161) -> Result<serde_json::Value, serde_json::Error> {
162 serialize_named_json_output(output, "list-boundaries", mode)
163}
164
165pub fn serialize_list_workspaces_json_output<T: Serialize>(
171 output: T,
172 mode: RootEnvelopeMode,
173) -> Result<serde_json::Value, serde_json::Error> {
174 serialize_named_json_output(output, "list-workspaces", mode)
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180 use serde_json::json;
181
182 #[test]
183 fn list_boundaries_json_output_uses_output_owned_root_contract() {
184 let value = serialize_list_boundaries_json_output(
185 json!({"boundaries": {}}),
186 RootEnvelopeMode::Tagged,
187 )
188 .expect("list boundaries output should serialize");
189
190 assert_eq!(value["kind"], "list-boundaries");
191 }
192
193 #[test]
194 fn list_workspaces_json_output_uses_output_owned_root_contract() {
195 let value = serialize_list_workspaces_json_output(
196 json!({"workspace_count": 0, "workspaces": []}),
197 RootEnvelopeMode::Tagged,
198 )
199 .expect("list workspaces output should serialize");
200
201 assert_eq!(value["kind"], "list-workspaces");
202 }
203}