wasmer_cli/
types.rs

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
9/// Render the full name (`namespace/name`) of a package version's package.
10fn 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}