stmo_cli/commands/
discover.rs1#![allow(clippy::missing_errors_doc)]
2
3use crate::api::RedashClient;
4use anyhow::Result;
5
6fn format_resource_line(id: u64, name: &str, url: &str, is_draft: bool) -> String {
7 let draft = if is_draft { " [DRAFT]" } else { "" };
8 format!(" {id} - {name}{draft}\n {url}")
9}
10
11pub async fn discover(client: &RedashClient, search: Option<&str>, limit: usize) -> Result<()> {
12 if let Some(term) = search {
13 discover_by_search(client, term, limit).await
14 } else {
15 discover_own_queries(client).await
16 }
17}
18
19async fn discover_own_queries(client: &RedashClient) -> Result<()> {
20 println!("Fetching your queries from Redash...\n");
21
22 let queries = client.fetch_all_queries().await?;
23
24 println!("=== QUERIES ({}) ===\n", queries.len());
25 for query in &queries {
26 let archived = if query.is_archived { " [ARCHIVED]" } else { "" };
27 let draft = if query.is_draft { " [DRAFT]" } else { "" };
28 println!(" {} - {}{}{}", query.id, query.name, archived, draft);
29 }
30
31 println!("\nUse 'stmo-cli init' to create the queries directory.");
32
33 Ok(())
34}
35
36async fn discover_by_search(client: &RedashClient, term: &str, limit: usize) -> Result<()> {
37 println!("Searching for '{term}'...\n");
38
39 let (queries, dashboards) = tokio::join!(
40 client.search_queries(term, limit),
41 client.search_dashboards(term, limit),
42 );
43 let queries = queries?;
44 let dashboards = dashboards?;
45
46 let base = client.base_url();
47
48 println!("=== QUERIES ({}) ===\n", queries.len());
49 if queries.is_empty() {
50 println!(" No queries found for '{term}'.");
51 } else {
52 for query in &queries {
53 let url = format!("{base}/queries/{}", query.id);
54 println!(
55 "{}",
56 format_resource_line(query.id, &query.name, &url, query.is_draft)
57 );
58 }
59 if queries.len() == limit {
60 println!("\n (showing first {limit}; raise --limit for more)");
61 }
62 }
63
64 println!("\n=== DASHBOARDS ({}) ===\n", dashboards.len());
65 if dashboards.is_empty() {
66 println!(" No dashboards found for '{term}'.");
67 } else {
68 for dashboard in &dashboards {
69 let url = format!("{base}/dashboard/{}", dashboard.slug);
70 println!(
71 "{}",
72 format_resource_line(dashboard.id, &dashboard.name, &url, dashboard.is_draft)
73 );
74 }
75 if dashboards.len() == limit {
76 println!("\n (showing first {limit}; raise --limit for more)");
77 }
78 }
79
80 Ok(())
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn format_resource_line_plain() {
89 let line = format_resource_line(
90 42,
91 "My Dashboard",
92 "https://example.com/dashboard/my",
93 false,
94 );
95 assert!(line.contains("42"));
96 assert!(line.contains("My Dashboard"));
97 assert!(line.contains("https://example.com/dashboard/my"));
98 assert!(!line.contains("[DRAFT]"));
99 }
100
101 #[test]
102 fn format_resource_line_draft() {
103 let line = format_resource_line(7, "WIP", "https://example.com/dashboard/wip", true);
104 assert!(line.contains("[DRAFT]"));
105 assert!(line.contains("WIP"));
106 }
107}