sdk: readable clients (no Empty wrapper, no unused error module), documented examples with tests

This commit is contained in:
2026-10-23 01:05:19 +01:00
parent edc2d1a63b
commit 0516158883
15 changed files with 426 additions and 81 deletions
+31 -5
View File
@@ -56,20 +56,33 @@ pub fn client_rs(name: &str, doc: &Value) -> Result<String, String> {
local_refs(&mut ps);
let mut rs = method["result"]["schema"].clone();
local_refs(&mut rs);
let p = space
.add_type(&serde_json::from_value(ps).map_err(|e| e.to_string())?)
.map_err(|e| e.to_string())?;
let empty = method["params"].as_array().is_none_or(Vec::is_empty);
let p = if empty {
None
} else {
Some(
space
.add_type(&serde_json::from_value(ps).map_err(|e| e.to_string())?)
.map_err(|e| e.to_string())?,
)
};
let r = space
.add_type(&serde_json::from_value(rs).map_err(|e| e.to_string())?)
.map_err(|e| e.to_string())?;
let p = space.get_type(&p).map_err(|e| e.to_string())?.ident();
let p = p
.map(|p| {
space
.get_type(&p)
.map(|p| p.ident())
.map_err(|e| e.to_string())
})
.transpose()?;
let r = space.get_type(&r).map_err(|e| e.to_string())?.ident();
let docs = method
.get("description")
.or_else(|| method.get("summary"))
.and_then(Value::as_str)
.unwrap_or("");
let empty = method["params"].as_array().is_none_or(Vec::is_empty);
let arg = if empty { quote!() } else { quote!(params:#p) };
let params = if empty {
quote!(::sausage_plugin::serde_json::json!({}))
@@ -122,6 +135,19 @@ pub fn client_rs(name: &str, doc: &Value) -> Result<String, String> {
}
serde_attrs(std::slice::from_mut(item));
}
let uses_error = file
.items
.iter()
.filter(|item| !matches!(item, syn::Item::Mod(m) if m.ident == "error"))
.any(|item| {
quote!(#item)
.to_string()
.contains("error :: ConversionError")
});
if !uses_error {
file.items
.retain(|item| !matches!(item, syn::Item::Mod(m) if m.ident == "error"));
}
let types = &file.items;
let mut file =
syn::parse2::<syn::File>(quote!(mod #module {#(#types)* #(#functions)* #(#endpoints)*}))
+16
View File
@@ -1,4 +1,18 @@
//! Check the shared generator against a real example's discovered document.
/// String enums retain the conversion support that their parsers need.
#[test]
fn enum_client_keeps_used_error_support() {
let doc = serde_json::json!({
"components":{"schemas":{"Mode":{"type":"string","enum":["fast","slow"]}}},
"methods":[{"name":"mode","params":[],"result":{"schema":{"$ref":"#/components/schemas/Mode"}}}]
});
let code = sausage_interface::client_rs("settings", &doc).unwrap();
assert!(code.contains("pub mod error"));
assert!(code.contains("error::ConversionError"));
assert!(!code.contains("ModeParams"));
syn::parse_file(&code).unwrap();
}
#[test]
fn notes_client_preserves_names_and_docs() {
let document =
@@ -7,6 +21,8 @@ fn notes_client_preserves_names_and_docs() {
assert!(code.contains("pub struct AddParams"));
assert!(code.contains("pub struct Added"));
assert!(!code.contains("AddedResult"));
assert!(!code.contains("pub struct Empty"));
assert!(!code.contains("pub mod error"));
assert!(code.contains("The complete note text"));
assert!(code.contains("pub fn add(params: AddParams)"));
syn::parse_file(&code).unwrap();