greentic_bundle/setup/
mod.rs1pub mod backend;
2pub mod legacy_formspec;
3pub mod persist;
4pub mod qa_bridge;
5
6use std::collections::BTreeMap;
7
8use anyhow::Result;
9use serde::{Deserialize, Serialize};
10use serde_json::Value;
11
12pub const SETUP_STATE_DIR: &str = "state/setup";
13pub const SETUP_STATE_SCHEMA_VERSION: u32 = 1;
14
15#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16pub struct FormSpec {
17 pub id: String,
18 pub title: String,
19 pub version: String,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub description: Option<String>,
22 pub questions: Vec<QuestionSpec>,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26pub struct QuestionSpec {
27 pub id: String,
28 pub kind: QuestionKind,
29 pub title: String,
30 #[serde(skip_serializing_if = "Option::is_none")]
31 pub description: Option<String>,
32 pub required: bool,
33 #[serde(default, skip_serializing_if = "Vec::is_empty")]
34 pub choices: Vec<String>,
35 #[serde(skip_serializing_if = "Option::is_none")]
36 pub default_value: Option<Value>,
37 pub secret: bool,
38}
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
41#[serde(rename_all = "snake_case")]
42pub enum QuestionKind {
43 String,
44 Number,
45 Boolean,
46 Enum,
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
50#[serde(tag = "type", rename_all = "snake_case")]
51pub enum SetupSpecInput {
52 Legacy {
53 spec: Value,
54 },
55 ProviderQa {
56 qa_output: Value,
57 #[serde(default)]
58 i18n: BTreeMap<String, String>,
59 },
60}
61
62#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
63pub struct PersistedSetupState {
64 pub schema_version: u32,
65 pub provider_id: String,
66 pub source_kind: String,
67 pub form: FormSpec,
68 pub normalized_answers: BTreeMap<String, Value>,
69 pub non_secret_config: BTreeMap<String, Value>,
70 pub secret_values: BTreeMap<String, Value>,
71}
72
73pub fn form_spec_from_input(
74 input: &SetupSpecInput,
75 provider_id: &str,
76) -> Result<(String, FormSpec)> {
77 match input {
78 SetupSpecInput::Legacy { spec } => {
79 let parsed = match spec {
80 Value::String(raw) => legacy_formspec::parse_setup_spec_str(raw)?,
81 value => legacy_formspec::parse_setup_spec_value(value.clone())?,
82 };
83 Ok((
84 "legacy".to_string(),
85 legacy_formspec::setup_spec_to_form_spec(&parsed, provider_id),
86 ))
87 }
88 SetupSpecInput::ProviderQa { qa_output, i18n } => Ok((
89 "provider_qa".to_string(),
90 qa_bridge::provider_qa_to_form_spec(qa_output, i18n, provider_id),
91 )),
92 }
93}