wasmer_cli/commands/app/secrets/utils/
render.rs1use 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}