outlayer_cli/commands/
projects.rs1use anyhow::Result;
2
3use crate::config::{self, NetworkConfig};
4use crate::near::NearClient;
5
6pub 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 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 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}