1use serde::{Deserialize, Serialize};
2use uuid::Uuid;
3
4#[derive(Debug, Clone, Serialize, Deserialize, Default)]
5pub struct StepMetadata {
6 pub id: Uuid,
7 pub label: String,
8 pub description: Option<String>,
9 pub inputs: Vec<TypeInfo>,
10 pub outputs: Vec<TypeInfo>,
11}
12
13impl StepMetadata {
14 pub fn to_json(&self) -> serde_json::Value {
15 serde_json::to_value(self).unwrap_or(serde_json::Value::Null)
16 }
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct TypeInfo {
21 pub name: String,
22 #[serde(default, skip_serializing_if = "Option::is_none")]
25 pub json_schema: Option<serde_json::Value>,
26}
27
28impl TypeInfo {
29 pub fn new(name: impl Into<String>) -> Self {
30 Self {
31 name: name.into(),
32 json_schema: None,
33 }
34 }
35
36 pub fn with_json_schema(mut self, schema: serde_json::Value) -> Self {
37 self.json_schema = Some(schema);
38 self
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use serde_json::json;
46
47 #[test]
48 fn type_info_new_has_no_schema() {
49 let info = TypeInfo::new("i32");
50 assert_eq!(info.name, "i32");
51 assert!(info.json_schema.is_none());
52 }
53
54 #[test]
55 fn type_info_with_json_schema_builder() {
56 let schema = json!({"type": "object", "properties": {"x": {"type": "integer"}}});
57 let info = TypeInfo::new("MyStruct").with_json_schema(schema.clone());
58 assert_eq!(info.json_schema.unwrap(), schema);
59 }
60
61 #[test]
62 fn type_info_json_schema_omitted_when_none() {
63 let info = TypeInfo::new("i32");
64 let json = serde_json::to_value(&info).unwrap();
65 assert!(!json.as_object().unwrap().contains_key("json_schema"));
66 }
67
68 #[test]
69 fn type_info_json_schema_present_when_some() {
70 let schema = json!({"type": "string"});
71 let info = TypeInfo::new("String").with_json_schema(schema.clone());
72 let json = serde_json::to_value(&info).unwrap();
73 assert_eq!(json["json_schema"], schema);
74 }
75
76 #[test]
77 fn type_info_deserializes_without_json_schema_field() {
78 let json = r#"{"name": "u64"}"#;
79 let info: TypeInfo = serde_json::from_str(json).unwrap();
80 assert_eq!(info.name, "u64");
81 assert!(info.json_schema.is_none());
82 }
83
84 #[test]
85 fn type_info_roundtrip_with_schema() {
86 let schema = json!({"type": "array", "items": {"type": "integer"}});
87 let info = TypeInfo::new("Vec<i32>").with_json_schema(schema.clone());
88 let serialized = serde_json::to_string(&info).unwrap();
89 let deserialized: TypeInfo = serde_json::from_str(&serialized).unwrap();
90 assert_eq!(deserialized.name, "Vec<i32>");
91 assert_eq!(deserialized.json_schema.unwrap(), schema);
92 }
93}