Skip to main content

outlayer_cli/commands/
projects.rs

1use anyhow::Result;
2
3use crate::config::{self, NetworkConfig};
4use crate::near::NearClient;
5
6/// `outlayer projects [account]` — list projects for a user
7pub async fn list(network: &NetworkConfig, account: Option<String>) -> Result<()> {
8    let account_id = match account {
9        Some(id) => id,
10        None => {
11            let creds = config::load_credentials(network)?;
12            creds.account_id
13        }
14    };
15
16    let near = NearClient::new(network);
17
18    let projects: Vec<crate::near::ProjectView> = near
19        .view_call(
20            "list_user_projects",
21            serde_json::json!({ "account_id": account_id }),
22        )
23        .await?;
24
25    if projects.is_empty() {
26        eprintln!("No projects for {account_id}.");
27        return Ok(());
28    }
29
30    println!(
31        "{:<35} {:<12} {:<30} {:<10}",
32        "PROJECT", "VERSION", "SOURCE", "UUID"
33    );
34
35    for p in &projects {
36        let short_version = if p.active_version.len() > 10 {
37            &p.active_version[..10]
38        } else {
39            &p.active_version
40        };
41
42        // Fetch active version to get source type
43        let source_str = match near.get_version(&p.project_id, &p.active_version).await {
44            Ok(Some(v)) => format_source(&v.source),
45            _ => "---".to_string(),
46        };
47
48        println!(
49            "{:<35} {:<12} {:<30} {:<10}",
50            p.project_id, short_version, source_str, p.uuid
51        );
52    }
53
54    Ok(())
55}
56
57fn format_source(source: &serde_json::Value) -> String {
58    if let Some(obj) = source.as_object() {
59        if let Some(github) = obj.get("GitHub") {
60            let repo = github
61                .get("repo")
62                .and_then(|v| v.as_str())
63                .unwrap_or("?");
64            // Shorten repo URL
65            let short_repo = repo
66                .strip_prefix("https://github.com/")
67                .unwrap_or(repo);
68            let commit = github
69                .get("commit")
70                .and_then(|v| v.as_str())
71                .unwrap_or("?");
72            let short_commit = if commit.len() > 7 {
73                &commit[..7]
74            } else {
75                commit
76            };
77            return format!("github:{short_repo}@{short_commit}");
78        }
79        if let Some(wasm) = obj.get("WasmUrl") {
80            let url = wasm.get("url").and_then(|v| v.as_str()).unwrap_or("?");
81            let short = if url.len() > 25 {
82                &url[..25]
83            } else {
84                url
85            };
86            return format!("wasm:{short}...");
87        }
88    }
89    "unknown".to_string()
90}