Skip to main content

dsp_cli/
lib.rs

1//! `dsp-cli` — AI-agent-friendly CLI for the DaSCH Service Platform.
2//!
3//! The orientation entry point is `idea.md` in the repository root; the
4//! ubiquitous-language reference is `CONTEXT.md`. The internal architecture
5//! is described in dsp-cli/ADR-0008 (`docs/adr/0008-internal-architecture.md`).
6//!
7//! This crate exposes a library surface so tests can reach the action layer
8//! without going through the binary; the binary itself is `src/main.rs`.
9
10pub mod actions;
11pub mod cli;
12pub mod client;
13pub mod config;
14pub mod diagnostic;
15pub mod model;
16pub mod render;
17pub mod update;
18pub(crate) mod util;
19
20use crate::cli::{
21    AuthCmd, Cli, DataModelCmd, ProjectCmd, ResourceCmd, ResourceTypeCmd, SparqlCmd, TopLevel, VocabularyCmd, VreCmd,
22};
23use crate::client::http::HttpDspClient;
24use crate::config::Config;
25use crate::diagnostic::Diagnostic;
26
27/// Top-level entry point used by `main.rs` and by integration tests.
28///
29/// Routes CLI commands to the appropriate action function. The match is
30/// exhaustive — adding a new variant forces an explicit dispatch update.
31///
32/// For vre leaf commands and auth commands, the renderer is constructed from
33/// the `--format` / `-j` / `-l` flags parsed into `FormatArgs` and resolved
34/// via `FormatArgs::resolve().into_renderer()`. The auth commands additionally
35/// build a `Config` from `--server`/`DSP_SERVER` and, for login, an
36/// `HttpDspClient`.
37pub fn run(cli: Cli) -> Result<(), Diagnostic> {
38    // Captured before `match cli.command` (which moves that field out of `cli`) —
39    // `allow_insecure_server` is a global flag, not scoped to any one leaf Args.
40    let allow_insecure = cli.allow_insecure_server;
41
42    match cli.command {
43        TopLevel::Auth { cmd } => match cmd {
44            AuthCmd::Login(args) => {
45                let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
46                let client = HttpDspClient::new()?;
47                let fmt = args.format.resolve();
48                let opts = args.format.table_options(fmt)?;
49                let mut renderer = fmt.into_renderer_with_options(opts);
50                actions::auth::login::run(&args, &cfg, &client, &mut *renderer)
51            }
52            AuthCmd::Status(args) => {
53                let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
54                let fmt = args.format.resolve();
55                let opts = args.format.table_options(fmt)?;
56                let mut renderer = fmt.into_renderer_with_options(opts);
57                actions::auth::status::run(&args, &cfg, &mut *renderer)
58            }
59            AuthCmd::Logout(args) => {
60                let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
61                let fmt = args.format.resolve();
62                let opts = args.format.table_options(fmt)?;
63                let mut renderer = fmt.into_renderer_with_options(opts);
64                actions::auth::logout::run(&args, &cfg, &mut *renderer)
65            }
66            AuthCmd::SetToken(args) => {
67                let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
68                let client = HttpDspClient::new()?;
69                let fmt = args.format.resolve();
70                let opts = args.format.table_options(fmt)?;
71                let mut renderer = fmt.into_renderer_with_options(opts);
72                actions::auth::set_token::run(&cfg, &client, &mut *renderer)
73            }
74            AuthCmd::Token(args) => {
75                let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
76                actions::auth::token::run(&cfg)
77            }
78        },
79
80        TopLevel::Vre { cmd } => match cmd {
81            VreCmd::Project { cmd } => match cmd {
82                ProjectCmd::List(args) => {
83                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
84                    let client = HttpDspClient::new()?;
85                    let fmt = args.format.resolve();
86                    let opts = args.format.table_options(fmt)?;
87                    let mut renderer = fmt.into_renderer_with_options(opts);
88                    actions::vre::project::list(&args, &cfg, &client, &mut *renderer)
89                }
90                ProjectCmd::Describe(args) => {
91                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
92                    let client = HttpDspClient::new()?;
93                    let fmt = args.format.resolve();
94                    let opts = args.format.table_options(fmt)?;
95                    let mut renderer = fmt.into_renderer_with_options(opts);
96                    actions::vre::project::describe(&args, &cfg, &client, &mut *renderer)
97                }
98                ProjectCmd::Dump(args) => {
99                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
100                    let client = HttpDspClient::new()?;
101                    let fmt = args.format.resolve();
102                    let opts = args.format.table_options(fmt)?;
103                    let mut renderer = fmt.into_renderer_with_options(opts);
104                    let mut reporter = fmt.into_progress_reporter();
105                    actions::vre::project::dump(&args, &cfg, &client, &mut *renderer, &mut *reporter)
106                }
107            },
108            VreCmd::DataModel { cmd } => match cmd {
109                DataModelCmd::List(args) => {
110                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
111                    let client = HttpDspClient::new()?;
112                    let fmt = args.format.resolve();
113                    let opts = args.format.table_options(fmt)?;
114                    let mut renderer = fmt.into_renderer_with_options(opts);
115                    actions::vre::data_model::list(&args, &cfg, &client, &mut *renderer)
116                }
117                DataModelCmd::Describe(args) => {
118                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
119                    let client = HttpDspClient::new()?;
120                    let fmt = args.format.resolve();
121                    let opts = args.format.table_options(fmt)?;
122                    let mut renderer = fmt.into_renderer_with_options(opts);
123                    actions::vre::data_model::describe(&args, &cfg, &client, &mut *renderer)
124                }
125                DataModelCmd::Structure(args) => {
126                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
127                    let client = HttpDspClient::new()?;
128                    let fmt = args.format.resolve();
129                    let opts = args.format.table_options(fmt)?;
130                    let mut renderer = fmt.into_renderer_with_options(opts);
131                    actions::vre::data_model::structure(&args, &cfg, &client, &mut *renderer)
132                }
133            },
134            VreCmd::ResourceType { cmd } => match cmd {
135                ResourceTypeCmd::List(args) => {
136                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
137                    let client = HttpDspClient::new()?;
138                    let fmt = args.format.resolve();
139                    let opts = args.format.table_options(fmt)?;
140                    let mut renderer = fmt.into_renderer_with_options(opts);
141                    actions::vre::resource_type::list(&args, &cfg, &client, &mut *renderer)
142                }
143                ResourceTypeCmd::Describe(args) => {
144                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
145                    let client = HttpDspClient::new()?;
146                    let fmt = args.format.resolve();
147                    let opts = args.format.table_options(fmt)?;
148                    let mut renderer = fmt.into_renderer_with_options(opts);
149                    actions::vre::resource_type::describe(&args, &cfg, &client, &mut *renderer)
150                }
151            },
152            VreCmd::Resource { cmd } => match cmd {
153                ResourceCmd::List(args) => {
154                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
155                    let client = HttpDspClient::new()?;
156                    let fmt = args.format.resolve();
157                    let opts = args.format.table_options(fmt)?;
158                    let mut renderer = fmt.into_renderer_with_options(opts);
159                    actions::vre::resource::list(&args, &cfg, &client, &mut *renderer)
160                }
161                ResourceCmd::Describe(args) => {
162                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
163                    let client = HttpDspClient::new()?;
164                    let fmt = args.format.resolve();
165                    let opts = args.format.table_options(fmt)?;
166                    let mut renderer = fmt.into_renderer_with_options(opts);
167                    actions::vre::resource::describe(&args, &cfg, &client, &mut *renderer)
168                }
169            },
170            VreCmd::Vocabulary { cmd } => match cmd {
171                VocabularyCmd::List(args) => {
172                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
173                    let client = HttpDspClient::new()?;
174                    let fmt = args.format.resolve();
175                    let opts = args.format.table_options(fmt)?;
176                    let mut renderer = fmt.into_renderer_with_options(opts);
177                    actions::vre::vocabulary::list(&args, &cfg, &client, &mut *renderer)
178                }
179                VocabularyCmd::Describe(args) => {
180                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
181                    let client = HttpDspClient::new()?;
182                    let fmt = args.format.resolve();
183                    let opts = args.format.table_options(fmt)?;
184                    let mut renderer = fmt.into_renderer_with_options(opts);
185                    actions::vre::vocabulary::describe(&args, &cfg, &client, &mut *renderer)
186                }
187            },
188            // No renderer, no table_options — D2/D16: the response is a
189            // store-authored byte stream, not a dsp-cli-rendered view.
190            VreCmd::Sparql { cmd } => match cmd {
191                SparqlCmd::Query(args) => {
192                    let cfg = Config::resolve(args.server.as_deref(), allow_insecure)?;
193                    let client = HttpDspClient::new()?;
194                    actions::vre::sparql::run(&args, &cfg, &client)
195                }
196            },
197        },
198
199        TopLevel::Docs(args) => actions::docs::run(&args),
200    }
201}