pinakes-plugin-api: add reserved-route and required-endpoint validation

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Id85a7e729b26af8eb028e19418a5a1706a6a6964
This commit is contained in:
raf 2026-03-11 21:26:20 +03:00
commit dccaff2481
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF

View file

@ -41,7 +41,9 @@
//! } //! }
//! } //! }
//! //!
//! Note: expression values are `Expression::Path` strings, not mustache //! # Note
//!
//! Expression values are `Expression::Path` strings, not mustache
//! templates. A bare string like `"title"` resolves the `title` field in the //! templates. A bare string like `"title"` resolves the `title` field in the
//! current item context. Nested fields use dotted segments: `"artist.name"`. //! current item context. Nested fields use dotted segments: `"artist.name"`.
//! Array indices use the same notation: `"items.0.title"`. //! Array indices use the same notation: `"items.0.title"`.
@ -801,11 +803,6 @@ impl UiElement {
))); )));
} }
}, },
Self::Form { fields, .. } if fields.is_empty() => {
return Err(SchemaError::ValidationError(
"Form must have at least one field".to_string(),
));
},
Self::Chart { data, .. } if !page.data_sources.contains_key(data) => { Self::Chart { data, .. } if !page.data_sources.contains_key(data) => {
return Err(SchemaError::ValidationError(format!( return Err(SchemaError::ValidationError(format!(
"Chart references unknown data source: {data}" "Chart references unknown data source: {data}"
@ -867,6 +864,11 @@ impl UiElement {
submit_action, submit_action,
.. ..
} => { } => {
if fields.is_empty() {
return Err(SchemaError::ValidationError(
"Form must have at least one field".to_string(),
));
}
for field in fields { for field in fields {
validate_id(&field.id)?; validate_id(&field.id)?;
if field.label.is_empty() { if field.label.is_empty() {
@ -2120,8 +2122,6 @@ mod tests {
); );
} }
// --- SpecialAction JSON round-trips ---
#[test] #[test]
fn test_special_action_refresh_roundtrip() { fn test_special_action_refresh_roundtrip() {
let action = SpecialAction::Refresh; let action = SpecialAction::Refresh;
@ -2180,8 +2180,6 @@ mod tests {
assert_eq!(back, SpecialAction::CloseModal); assert_eq!(back, SpecialAction::CloseModal);
} }
// --- ActionRef deserialization ordering ---
#[test] #[test]
fn test_action_ref_special_refresh_deserializes() { fn test_action_ref_special_refresh_deserializes() {
let json = serde_json::json!({"action": "refresh"}); let json = serde_json::json!({"action": "refresh"});