Skip to main content

greentic_types/
wizard.rs

1//! Wizard planning and delegation primitives.
2
3use alloc::{collections::BTreeMap, string::String, vec::Vec};
4
5#[cfg(feature = "schemars")]
6use schemars::JsonSchema;
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9use serde_json::Value;
10
11/// Stable wizard identifier.
12#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14#[cfg_attr(feature = "schemars", derive(JsonSchema))]
15#[cfg_attr(feature = "serde", serde(transparent))]
16pub struct WizardId(pub String);
17
18impl WizardId {
19    /// Returns the identifier as a string slice.
20    pub fn as_str(&self) -> &str {
21        &self.0
22    }
23}
24
25impl From<String> for WizardId {
26    fn from(value: String) -> Self {
27        Self(value)
28    }
29}
30
31impl From<&str> for WizardId {
32    fn from(value: &str) -> Self {
33        Self(value.to_owned())
34    }
35}
36
37impl From<WizardId> for String {
38    fn from(value: WizardId) -> Self {
39        value.0
40    }
41}
42
43/// Target system that will execute wizard actions.
44#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
45#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
46#[cfg_attr(feature = "schemars", derive(JsonSchema))]
47#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
48pub enum WizardTarget {
49    /// Component scope.
50    Component,
51    /// Flow scope.
52    Flow,
53    /// Pack scope.
54    Pack,
55    /// Operator scope.
56    Operator,
57    /// Development tooling scope.
58    Dev,
59    /// Bundle scope.
60    Bundle,
61}
62
63/// Canonical wizard mode.
64#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
65#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
66#[cfg_attr(feature = "schemars", derive(JsonSchema))]
67#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
68pub enum WizardMode {
69    /// Default mode.
70    Default,
71    /// Setup mode.
72    Setup,
73    /// Update mode.
74    Update,
75    /// Remove mode.
76    Remove,
77    /// Scaffold mode.
78    Scaffold,
79    /// Build mode.
80    Build,
81    /// New mode.
82    New,
83}
84
85/// Wizard plan metadata.
86#[derive(Clone, Debug, PartialEq)]
87#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
88#[cfg_attr(feature = "schemars", derive(JsonSchema))]
89pub struct WizardPlanMeta {
90    /// Wizard identifier.
91    pub id: WizardId,
92    /// Wizard target scope.
93    pub target: WizardTarget,
94    /// Requested execution mode.
95    pub mode: WizardMode,
96}
97
98/// Deterministic wizard plan.
99#[derive(Clone, Debug, PartialEq)]
100#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
101#[cfg_attr(feature = "schemars", derive(JsonSchema))]
102pub struct WizardPlan {
103    /// Plan metadata and routing identity.
104    pub meta: WizardPlanMeta,
105    /// Ordered steps to execute.
106    pub steps: Vec<WizardStep>,
107}
108
109/// A single wizard plan step.
110#[derive(Clone, Debug, PartialEq)]
111#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
112#[cfg_attr(feature = "schemars", derive(JsonSchema))]
113#[cfg_attr(feature = "serde", serde(rename_all = "snake_case", tag = "type"))]
114pub enum WizardStep {
115    /// Ensure directories exist.
116    EnsureDir {
117        /// Directories to ensure.
118        paths: Vec<String>,
119    },
120    /// Write files as path -> UTF-8 content.
121    WriteFiles {
122        /// Map of relative path to content.
123        files: BTreeMap<String, String>,
124    },
125    /// Legacy bridge to invoke CLI commands.
126    RunCli {
127        /// Executable command.
128        command: String,
129        /// Command arguments.
130        #[cfg_attr(
131            feature = "serde",
132            serde(default, skip_serializing_if = "Vec::is_empty")
133        )]
134        args: Vec<String>,
135    },
136    /// Delegate part of the wizard to another target/id/mode.
137    Delegate {
138        /// Target scope for delegation.
139        target: WizardTarget,
140        /// Delegate wizard identifier.
141        id: WizardId,
142        /// Delegate mode.
143        mode: WizardMode,
144        /// Optional prefilled answers for deterministic replay.
145        #[cfg_attr(
146            feature = "serde",
147            serde(default, skip_serializing_if = "BTreeMap::is_empty")
148        )]
149        prefilled_answers: BTreeMap<String, Value>,
150        /// Optional output key remapping.
151        #[cfg_attr(
152            feature = "serde",
153            serde(default, skip_serializing_if = "BTreeMap::is_empty")
154        )]
155        output_map: BTreeMap<String, String>,
156    },
157}