wasmer_cli/commands/app/secrets/utils/
render.rs

1use super::{BackendSecretWrapper, Secret};
2use crate::utils::render::CliRender;
3use colored::Colorize;
4use comfy_table::{Cell, Table};
5use time::OffsetDateTime;
6use wasmer_backend_api::types::{DateTime, Secret as BackendSecret};
7
8impl CliRender for Secret {
9    fn render_item_table(&self) -> String {
10        let mut table = Table::new();
11        let Secret { name, value }: &Secret = self;
12
13        table.load_preset(comfy_table::presets::NOTHING);
14        table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
15
16        let value = sanitize_value(value);
17        table.add_rows([
18            vec![
19                Cell::new("Name".to_string()).add_attribute(comfy_table::Attribute::Bold),
20                Cell::new("Value".to_string()).add_attribute(comfy_table::Attribute::Bold),
21            ],
22            vec![Cell::new(name.to_string()), Cell::new(format!("'{value}'"))],
23        ]);
24        table.to_string()
25    }
26
27    fn render_list_table(items: &[Self]) -> String {
28        if items.is_empty() {
29            return String::new();
30        }
31        let mut table = Table::new();
32        table.load_preset(comfy_table::presets::NOTHING);
33        table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
34
35        table.set_header(vec![
36            Cell::new("Name".to_string()).add_attribute(comfy_table::Attribute::Bold),
37            Cell::new("Value".to_string()).add_attribute(comfy_table::Attribute::Bold),
38        ]);
39        table.add_rows(items.iter().map(|s| {
40            vec![
41                Cell::new(s.name.clone()),
42                Cell::new(format!("'{}'", sanitize_value(&s.value))),
43            ]
44        }));
45        table.to_string()
46    }
47}
48
49impl CliRender for BackendSecretWrapper {
50    fn render_item_table(&self) -> String {
51        let mut table = Table::new();
52        let BackendSecret {
53            name, updated_at, ..
54        }: &BackendSecret = &self.0;
55        let last_updated = last_updated_to_human(updated_at.clone())
56            .unwrap()
57            .to_string();
58        table.add_rows([
59            vec!["Name".to_string(), name.to_string()],
60            vec![
61                "Last updated".to_string(),
62                format!("{last_updated} ago").dimmed().to_string(),
63            ],
64        ]);
65        table.to_string()
66    }
67
68    fn render_list_table(items: &[Self]) -> String {
69        if items.is_empty() {
70            return String::new();
71        }
72        let mut table = Table::new();
73        table.load_preset(comfy_table::presets::NOTHING);
74        table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
75
76        table.set_header(vec![
77            Cell::new("Name".to_string()).add_attribute(comfy_table::Attribute::Bold),
78            Cell::new("Last updated".to_string()).add_attribute(comfy_table::Attribute::Bold),
79        ]);
80        table.add_rows(items.iter().map(|s| {
81            let last_updated = last_updated_to_human(s.0.updated_at.clone())
82                .unwrap()
83                .to_string();
84            vec![
85                Cell::new(s.0.name.clone()),
86                Cell::new(format!("{last_updated} ago").dimmed().to_string()),
87            ]
88        }));
89        table.to_string()
90    }
91}
92
93fn last_updated_to_human(last_update: DateTime) -> anyhow::Result<humantime::Duration> {
94    let last_update: OffsetDateTime = last_update.try_into()?;
95    let elapsed: std::time::Duration = (OffsetDateTime::now_utc() - last_update).try_into()?;
96    Ok(humantime::Duration::from(std::time::Duration::from_secs(
97        elapsed.as_secs(),
98    )))
99}
100
101pub(crate) fn sanitize_value(value: &str) -> String {
102    value
103        .chars()
104        .map(|c| {
105            if c.is_ascii() {
106                let c = c as u8;
107                std::ascii::escape_default(c).to_string()
108            } else {
109                c.to_string()
110            }
111        })
112        .collect::<Vec<String>>()
113        .join("")
114}