1use comfy_table::Table;
2use wasmer_backend_api::types::{
3 DeployApp, DeployAppVersion, Deployment, DnsDomain, DnsDomainWithRecords, Namespace,
4 SearchPackageVersion,
5};
6
7use crate::utils::render::CliRender;
8
9fn package_full_name(pv: &SearchPackageVersion) -> String {
11 match &pv.package.namespace {
12 Some(ns) => format!("{ns}/{}", pv.package.package_name),
13 None => pv.package.package_name.clone(),
14 }
15}
16
17impl CliRender for SearchPackageVersion {
18 fn render_item_table(&self) -> String {
19 let mut table = Table::new();
20 table.add_rows([
21 vec!["Package".to_string(), package_full_name(self)],
22 vec!["Version".to_string(), self.version.clone()],
23 vec!["Created".to_string(), self.created_at.0.clone()],
24 ]);
25 table.to_string()
26 }
27
28 fn render_list_table(items: &[Self]) -> String {
29 let mut table = Table::new();
30 table.set_header(vec![
31 "Package".to_string(),
32 "Version".to_string(),
33 "Created".to_string(),
34 ]);
35 table.add_rows(items.iter().map(|pv| {
36 vec![
37 package_full_name(pv),
38 pv.version.clone(),
39 pv.created_at.0.clone(),
40 ]
41 }));
42 table.to_string()
43 }
44}
45
46impl CliRender for DnsDomain {
47 fn render_item_table(&self) -> String {
48 let mut table = Table::new();
49 table.add_rows([vec!["Domain".to_string(), self.name.clone()]]);
50 table.to_string()
51 }
52
53 fn render_list_table(items: &[Self]) -> String {
54 if items.is_empty() {
55 return String::new();
56 }
57 let mut table = Table::new();
58 table.set_header(vec!["Domain".to_string(), "Owner".to_string()]);
59 table.add_rows(
60 items
61 .iter()
62 .map(|ns| vec![ns.name.clone(), ns.owner.global_name.clone()]),
63 );
64 table.to_string()
65 }
66}
67
68impl CliRender for DnsDomainWithRecords {
69 fn render_item_table(&self) -> String {
70 let mut output = String::new();
71 let mut table = Table::new();
72 table
73 .load_preset(comfy_table::presets::UTF8_FULL_CONDENSED)
74 .set_header(vec![
75 "Type".to_string(),
76 "Name".to_string(),
77 "TTL".to_string(),
78 "Value".to_string(),
79 ]);
80 let mut rows: Vec<Vec<String>> = vec![];
81 if let Some(ref records) = self.records {
82 records.iter().flatten().for_each(|record| {
83 rows.push(vec![
84 record.record_type().to_string(),
85 record.name().unwrap_or("<no name>").to_string(),
86 record
87 .ttl()
88 .expect("expected a TTL value for record")
89 .to_string(),
90 record.text().to_string(),
91 ]);
92 });
93 }
94
95 table.add_rows(rows);
96 output += &table.to_string();
97 output
98 }
99
100 fn render_list_table(items: &[Self]) -> String {
101 if items.is_empty() {
102 return String::new();
103 }
104 let mut table = Table::new();
105 table.set_header(vec!["Domain".to_string()]);
106 table.add_rows(items.iter().map(|ns| vec![ns.name.clone()]));
107 table.to_string()
108 }
109}
110
111impl CliRender for Namespace {
112 fn render_item_table(&self) -> String {
113 let mut table = Table::new();
114 table.add_rows([
115 vec!["Namespace".to_string(), self.name.clone()],
116 vec!["Id".to_string(), self.id.inner().to_string()],
117 ]);
118 table.to_string()
119 }
120
121 fn render_list_table(items: &[Self]) -> String {
122 let mut table = Table::new();
123 table.set_header(vec!["Namespace".to_string(), "Id".to_string()]);
124 table.add_rows(
125 items
126 .iter()
127 .map(|ns| vec![ns.name.clone(), ns.id.inner().to_string()]),
128 );
129 table.to_string()
130 }
131}
132
133impl CliRender for DeployApp {
134 fn render_item_table(&self) -> String {
135 let mut table = Table::new();
136 table.add_rows([
137 vec![
138 "App".to_string(),
139 format!("{}/{}", self.owner.global_name, self.name),
140 ],
141 vec![
142 "Version".to_string(),
143 self.active_version
144 .as_ref()
145 .map_or_else(|| "n/a".to_string(), |v| v.version.clone()),
146 ],
147 vec!["Created".to_string(), self.created_at.0.clone()],
148 vec!["Updated".to_string(), self.updated_at.0.clone()],
149 vec!["Id".to_string(), self.id.inner().to_string()],
150 ]);
151 table.to_string()
152 }
153
154 fn render_list_table(items: &[Self]) -> String {
155 let mut table = Table::new();
156 table.set_header(vec![
157 "App".to_string(),
158 "Version".to_string(),
159 "Created".to_string(),
160 "Updated".to_string(),
161 "Id".to_string(),
162 ]);
163 table.add_rows(items.iter().map(|app| {
164 vec![
165 format!("{}/{}", app.owner.global_name, app.name),
166 app.active_version
167 .as_ref()
168 .map_or_else(|| "n/a".to_string(), |v| v.version.clone()),
169 app.created_at.0.clone(),
170 app.updated_at.0.clone(),
171 app.id.inner().to_string(),
172 ]
173 }));
174 table.to_string()
175 }
176}
177
178impl CliRender for DeployAppVersion {
179 fn render_item_table(&self) -> String {
180 let mut table = Table::new();
181 table.add_rows([
182 vec!["Version name".to_string(), self.version.clone()],
183 vec!["Created".to_string(), self.created_at.0.clone()],
184 vec!["Id".to_string(), self.id.inner().to_string()],
185 ]);
186 table.to_string()
187 }
188
189 fn render_list_table(items: &[Self]) -> String {
190 let mut table = Table::new();
191 table.set_header(vec![
192 "Version name".to_string(),
193 "Created".to_string(),
194 "Id".to_string(),
195 ]);
196 table.add_rows(items.iter().map(|ver| {
197 vec![
198 ver.version.clone(),
199 ver.created_at.0.clone(),
200 ver.id.inner().to_string(),
201 ]
202 }));
203 table.to_string()
204 }
205}
206
207impl CliRender for wasmer_backend_api::types::AppVersionVolume {
208 fn render_item_table(&self) -> String {
209 let mut table = Table::new();
210 table.add_rows([
211 vec!["Name".to_string(), self.name.clone()],
212 vec![
213 "Used size".to_string(),
214 format_disk_size_opt(self.used_size.clone()),
215 ],
216 ]);
217 table.to_string()
218 }
219
220 fn render_list_table(items: &[Self]) -> String {
221 let mut table = Table::new();
222 table.set_header(vec!["Name".to_string(), "Used size".to_string()]);
223 table.add_rows(items.iter().map(|vol| {
224 vec![
225 vol.name.clone(),
226 format_disk_size_opt(vol.used_size.clone()),
227 ]
228 }));
229 table.to_string()
230 }
231}
232
233impl CliRender for wasmer_backend_api::types::AppDatabase {
234 fn render_item_table(&self) -> String {
235 let mut table = Table::new();
236 table.add_rows([
237 vec!["Name".to_string(), self.name.clone()],
238 vec!["Host".to_string(), self.host.clone()],
239 vec!["Port".to_string(), self.port.clone()],
240 vec!["Username".to_string(), self.username.clone()],
241 vec![
242 "Password".to_string(),
243 self.password.clone().unwrap_or_else(|| "n/a".to_string()),
244 ],
245 vec![
246 "UI".to_string(),
247 self.db_explorer_url
248 .clone()
249 .unwrap_or_else(|| "n/a".to_string()),
250 ],
251 ]);
252 table.to_string()
253 }
254
255 fn render_list_table(items: &[Self]) -> String {
256 let mut table = Table::new();
257 table.set_header(vec![
258 "Name".to_string(),
259 "Host".to_string(),
260 "Port".to_string(),
261 "UI".to_string(),
262 "Password".to_string(),
263 ]);
264 table.add_rows(items.iter().map(|vol| {
265 vec![
266 vol.name.clone(),
267 vol.host.clone(),
268 vol.port.clone(),
269 vol.db_explorer_url
270 .clone()
271 .unwrap_or_else(|| "n/a".to_string()),
272 vol.password.clone().unwrap_or_else(|| "n/a".to_string()),
273 ]
274 }));
275 table.to_string()
276 }
277}
278
279fn format_disk_size_opt(value: Option<wasmer_backend_api::types::BigInt>) -> String {
280 let value = value.and_then(|x| {
281 let y: Option<u64> = x.0.try_into().ok();
282 y
283 });
284
285 if let Some(v) = value {
286 let s = bytesize::ByteSize(v);
287 s.to_string()
288 } else {
289 "n/a".to_string()
290 }
291}
292
293impl CliRender for Deployment {
294 fn render_item_table(&self) -> String {
295 match self {
296 Deployment::NakedDeployment(naked) => naked.render_item_table(),
297 Deployment::AutobuildRepository(build) => build.render_item_table(),
298 Deployment::Other => "unknown deployment type".to_string(),
299 }
300 }
301
302 fn render_list_table(items: &[Self]) -> String {
303 let mut table = Table::new();
304 table.set_header(vec![
305 "Id".to_string(),
306 "Type".to_string(),
307 "Created at".to_string(),
308 "Status".to_string(),
309 "App version".to_string(),
310 ]);
311
312 let rows = items
313 .iter()
314 .map(|item| match item {
315 Deployment::NakedDeployment(naked) => {
316 vec![
317 naked.id.inner().to_string(),
318 "Manual".to_string(),
319 naked.created_at.0.clone(),
320 String::new(),
321 naked
322 .app_version
323 .as_ref()
324 .map_or_else(|| "n/a".to_string(), |x| x.version.clone()),
325 ]
326 }
327 Deployment::AutobuildRepository(build) => {
328 vec![
329 build.id.inner().to_string(),
330 "Autobuild".to_string(),
331 build.status.as_str().to_string(),
332 build.created_at.0.clone(),
333 ]
334 }
335 Deployment::Other => vec![
336 String::new(),
337 "Unknown".to_string(),
338 String::new(),
339 String::new(),
340 ],
341 })
342 .collect::<Vec<_>>();
343 table.add_rows(rows);
344
345 table.to_string()
346 }
347}
348
349impl CliRender for wasmer_backend_api::types::NakedDeployment {
350 fn render_item_table(&self) -> String {
351 let mut table = Table::new();
352 table.add_rows([
353 vec!["Id".to_string(), self.id.clone().into_inner()],
354 vec!["Created at".to_string(), self.created_at.0.clone()],
355 vec![
356 "App version".to_string(),
357 self.app_version
358 .as_ref()
359 .map_or_else(|| "n/a".to_string(), |x| x.version.clone()),
360 ],
361 ]);
362 table.to_string()
363 }
364
365 fn render_list_table(items: &[Self]) -> String {
366 let mut table = Table::new();
367 table.set_header(vec![
368 "Id".to_string(),
369 "Created at".to_string(),
370 "App version".to_string(),
371 ]);
372 table.add_rows(items.iter().map(|item| {
373 vec![
374 item.id.clone().into_inner(),
375 item.created_at.0.clone(),
376 item.app_version
377 .as_ref()
378 .map_or_else(|| "n/a".to_string(), |x| x.version.clone()),
379 ]
380 }));
381 table.to_string()
382 }
383}
384
385impl CliRender for wasmer_backend_api::types::AutobuildRepository {
386 fn render_item_table(&self) -> String {
387 let mut table = Table::new();
388 table.add_rows([
389 vec!["Id".to_string(), self.id.clone().into_inner()],
390 vec!["Status".to_string(), self.status.as_str().to_string()],
391 vec!["Created at".to_string(), self.created_at.0.clone()],
392 ]);
393 table.to_string()
394 }
395
396 fn render_list_table(items: &[Self]) -> String {
397 let mut table = Table::new();
398 table.set_header(vec![
399 "Id".to_string(),
400 "Status".to_string(),
401 "Created at".to_string(),
402 ]);
403 table.add_rows(items.iter().map(|item| {
404 vec![
405 item.id.clone().into_inner(),
406 item.status.as_str().to_string(),
407 item.created_at.0.clone(),
408 ]
409 }));
410 table.to_string()
411 }
412}