greentic_operator/demo/
pack_resolve.rs1use std::path::{Path, PathBuf};
2
3use anyhow::{Context, Result, anyhow};
4
5use crate::domains;
6
7#[derive(Debug, Clone)]
8pub struct DemoPack {
9 pub pack_id: String,
10 pub pack_path: PathBuf,
11 pub entry_flows: Vec<String>,
12 pub default_flow_source: EntryFlowSource,
13}
14
15#[derive(Clone, Copy, Debug)]
16pub enum EntryFlowSource {
17 MetaEntryFlows,
18 FlowsList,
19}
20
21impl EntryFlowSource {
22 fn description(self) -> &'static str {
23 match self {
24 EntryFlowSource::MetaEntryFlows => "meta.entry_flows",
25 EntryFlowSource::FlowsList => "manifest.flows[*].id/entrypoints",
26 }
27 }
28}
29
30impl DemoPack {
31 pub fn select_flow(&self, requested: Option<&str>) -> Result<String> {
32 if self.entry_flows.is_empty() {
33 return Err(anyhow!(
34 "default flow not declared ({}) and no flows available; available flows: []",
35 self.default_flow_source.description()
36 ));
37 }
38 if let Some(flow) = requested {
39 if self.entry_flows.iter().any(|candidate| candidate == flow) {
40 return Ok(flow.to_string());
41 }
42 return Err(anyhow!(
43 "flow `{flow}` not declared via {}; available flows: {}",
44 self.default_flow_source.description(),
45 self.entry_flows.join(", ")
46 ));
47 }
48 Ok(self.entry_flows[0].clone())
49 }
50}
51
52pub fn resolve_pack(packs_dir: &Path, pack_name: &str) -> Result<DemoPack> {
53 let pack_path = packs_dir.join(pack_name);
54 if !pack_path.exists() {
55 return Err(anyhow!(
56 "pack {pack_name} not found under {}",
57 packs_dir.display()
58 ));
59 }
60 let meta = domains::read_pack_meta(&pack_path)
61 .with_context(|| format!("failed to read manifest for pack {}", pack_path.display()))?;
62 Ok(DemoPack {
63 pack_id: meta.pack_id.clone(),
64 pack_path,
65 entry_flows: meta.entry_flows.clone(),
66 default_flow_source: EntryFlowSource::MetaEntryFlows,
67 })
68}