aion_server/authoring/error.rs
1//! Authoring API error taxonomy and its wire mapping.
2//!
3//! Mirrors [`crate::api::handlers::deploy::DeployApiError`]: a small set of
4//! failure classes the transports render distinctly. The defining class is
5//! [`AuthoringApiError::TypeError`], which carries the verbatim `gleam`
6//! compiler diagnostics so the author sees the real type error inline (HTTP
7//! 400). Everything else maps onto the standard wire-code tables.
8
9use aion_proto::WireError;
10
11/// Failure classes for the server-side authoring loop.
12#[derive(Debug)]
13pub enum AuthoringApiError {
14 /// The submitted source did not compile or type-check. The carried string
15 /// is the verbatim `gleam` compiler output, returned inline so the author
16 /// corrects against the real type-checker (rendered 400 by the HTTP
17 /// facade).
18 TypeError(String),
19 /// The server is draining or the engine is shutting down (503).
20 Unavailable(WireError),
21 /// Mapped wire failure rendered through the standard code tables:
22 /// authorization denials, spawn/packaging/load faults, and misconfiguration.
23 Wire(WireError),
24}
25
26impl AuthoringApiError {
27 /// A stable refusal-class label for audit lines and metrics.
28 #[must_use]
29 pub fn outcome(&self) -> &'static str {
30 match self {
31 Self::TypeError(_) => "type_error",
32 Self::Unavailable(_) => "unavailable",
33 Self::Wire(wire) => wire.code.as_str(),
34 }
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use aion_proto::WireError;
41
42 use super::AuthoringApiError;
43
44 #[test]
45 fn outcome_labels_are_stable() {
46 assert_eq!(
47 AuthoringApiError::TypeError("error: bad".to_owned()).outcome(),
48 "type_error"
49 );
50 assert_eq!(
51 AuthoringApiError::Unavailable(WireError::backend("draining")).outcome(),
52 "unavailable"
53 );
54 assert_eq!(
55 AuthoringApiError::Wire(WireError::invalid_input("nope")).outcome(),
56 WireError::invalid_input("nope").code.as_str()
57 );
58 }
59}