Skip to main content

esi_openapi/groups/
meta.rs

1use crate::prelude::*;
2use std::collections::HashMap;
3
4/// Endpoints for Meta
5pub struct MetaGroup<'a> {
6    pub(crate) esi: &'a Esi,
7}
8
9/// HTTP method of a route.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
11pub enum HttpMethod {
12    /// `GET`
13    #[serde(rename = "GET")]
14    Get,
15    /// `POST`
16    #[serde(rename = "POST")]
17    Post,
18    /// `PUT`
19    #[serde(rename = "PUT")]
20    Put,
21    /// `DELETE`
22    #[serde(rename = "DELETE")]
23    Delete,
24    /// A method this version of the crate does not know about.
25    #[serde(other)]
26    Unrecognized,
27}
28
29/// The kind of change recorded in the changelog.
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
31#[serde(rename_all = "lowercase")]
32pub enum ChangeType {
33    /// A breaking change.
34    Breaking,
35    /// A non-breaking change.
36    Changed,
37    /// A new route.
38    New,
39    /// A removed route.
40    Removed,
41    /// A kind of change this version of the crate does not know about.
42    #[serde(other)]
43    Unrecognized,
44}
45
46/// Health of a route.
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
48pub enum RouteHealth {
49    /// The status is not known.
50    Unknown,
51    /// The route is working as expected.
52    #[serde(rename = "OK")]
53    Ok,
54    /// The route is working, but with degraded performance.
55    Degraded,
56    /// The route is not working.
57    Down,
58    /// The route is recovering.
59    Recovering,
60    /// A status this version of the crate does not know about.
61    #[serde(other)]
62    Unrecognized,
63}
64
65/// The list of compatibility dates supported by ESI.
66#[derive(Debug, Clone, PartialEq, Deserialize)]
67#[allow(missing_docs)]
68pub struct CompatibilityDates {
69    pub compatibility_dates: Vec<String>,
70}
71
72/// One change to a route, as listed in the ESI changelog.
73#[derive(Debug, Clone, PartialEq, Deserialize)]
74#[allow(missing_docs)]
75pub struct ChangelogEntry {
76    pub compatibility_date: String,
77    pub description: String,
78    pub method: HttpMethod,
79    pub path: String,
80    #[serde(rename = "type")]
81    pub change_type: ChangeType,
82}
83
84/// The ESI changelog, keyed by compatibility date.
85#[derive(Debug, Clone, PartialEq, Deserialize)]
86#[allow(missing_docs)]
87pub struct Changelog {
88    pub changelog: HashMap<String, Vec<ChangelogEntry>>,
89}
90
91/// A previous name of the API.
92#[derive(Debug, Clone, PartialEq, Deserialize)]
93#[allow(missing_docs)]
94pub struct ApiNameEntry {
95    pub date: String,
96    pub name: String,
97}
98
99/// Current and past names of the API.
100#[derive(Debug, Clone, PartialEq, Deserialize)]
101#[allow(missing_docs)]
102pub struct ApiName {
103    pub current: String,
104    pub history: Vec<ApiNameEntry>,
105}
106
107/// Health of a single route.
108#[derive(Debug, Clone, PartialEq, Deserialize)]
109#[allow(missing_docs)]
110pub struct RouteStatus {
111    pub method: HttpMethod,
112    pub path: String,
113    pub status: RouteHealth,
114}
115
116/// Health of every ESI route.
117#[derive(Debug, Clone, PartialEq, Deserialize)]
118#[allow(missing_docs)]
119pub struct ApiStatus {
120    pub routes: Vec<RouteStatus>,
121}
122
123impl MetaGroup<'_> {
124    api_get!(
125        /// Get the changelog of ESI routes.
126        get_changelog,
127        "GetMetaChangelog",
128        RequestType::Public,
129        Changelog,
130    );
131
132    api_get!(
133        /// Get the compatibility dates supported by ESI.
134        get_compatibility_dates,
135        "GetMetaCompatibilityDates",
136        RequestType::Public,
137        CompatibilityDates,
138    );
139
140    api_get!(
141        /// Get the current and past names of the API.
142        get_name,
143        "GetMetaName",
144        RequestType::Public,
145        ApiName,
146    );
147
148    api_get!(
149        /// Get the health of every ESI route.
150        get_status,
151        "GetMetaStatus",
152        RequestType::Public,
153        ApiStatus,
154    );
155}
156
157#[cfg(test)]
158mod tests {
159    use super::{
160        ApiName, ApiStatus, ChangeType, Changelog, CompatibilityDates, HttpMethod, RouteHealth,
161    };
162
163    #[test]
164    fn test_parse_compatibility_dates() {
165        let json = r#"{"compatibility_dates":["2026-08-18","2020-01-01"]}"#;
166        let dates: CompatibilityDates = serde_json::from_str(json).unwrap();
167        assert_eq!(dates.compatibility_dates.len(), 2);
168    }
169
170    #[test]
171    fn test_parse_changelog() {
172        let json = r#"{"changelog":{"2026-08-18":[{"method":"GET","path":"/status","compatibility_date":"2026-08-18","type":"changed","description":"Updated."}]}}"#;
173        let log: Changelog = serde_json::from_str(json).unwrap();
174        assert_eq!(
175            log.changelog["2026-08-18"][0].change_type,
176            ChangeType::Changed
177        );
178        assert_eq!(log.changelog["2026-08-18"][0].method, HttpMethod::Get);
179    }
180
181    #[test]
182    fn test_parse_name_and_status() {
183        let name: ApiName = serde_json::from_str(
184            r#"{"current":"ESI","history":[{"date":"2026-01-01","name":"Old"}]}"#,
185        )
186        .unwrap();
187        assert_eq!(name.history[0].name, "Old");
188        let status: ApiStatus =
189            serde_json::from_str(r#"{"routes":[{"method":"GET","path":"/status","status":"OK"}]}"#)
190                .unwrap();
191        assert_eq!(status.routes[0].status, RouteHealth::Ok);
192    }
193}