relay_event_schema/protocol/contexts/
ota_updates.rs

1use relay_protocol::{Annotated, Empty, FromValue, IntoValue, Object, Value};
2
3use crate::processor::ProcessValue;
4
5/// OTA (Expo) Updates context.
6///
7/// Contains the OTA Updates constants present when the event was created.
8#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
9pub struct OTAUpdatesContext {
10    /// The channel name of the current build, if configured for use with EAS Update.
11    pub channel: Annotated<String>,
12
13    /// The runtime version of the current build.
14    pub runtime_version: Annotated<String>,
15
16    /// The UUID that uniquely identifies the currently running update.
17    pub update_id: Annotated<String>,
18
19    /// Additional arbitrary fields for forwards compatibility.
20    #[metastructure(additional_properties, retain = true, pii = "maybe")]
21    pub other: Object<Value>,
22}
23
24impl super::DefaultContext for OTAUpdatesContext {
25    fn default_key() -> &'static str {
26        "ota_updates"
27    }
28
29    fn from_context(context: super::Context) -> Option<Self> {
30        match context {
31            super::Context::OTAUpdates(c) => Some(*c),
32            _ => None,
33        }
34    }
35
36    fn cast(context: &super::Context) -> Option<&Self> {
37        match context {
38            super::Context::OTAUpdates(c) => Some(c),
39            _ => None,
40        }
41    }
42
43    fn cast_mut(context: &mut super::Context) -> Option<&mut Self> {
44        match context {
45            super::Context::OTAUpdates(c) => Some(c),
46            _ => None,
47        }
48    }
49
50    fn into_context(self) -> super::Context {
51        super::Context::OTAUpdates(Box::new(self))
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58    use crate::protocol::Context;
59
60    #[test]
61    fn test_ota_updates_context_roundtrip() {
62        let json: &str = r#"{
63  "channel": "production",
64  "runtime_version": "1.0.0",
65  "update_id": "12345678-1234-1234-1234-1234567890ab",
66  "type": "otaupdates"
67}"#;
68        let context = Annotated::new(Context::OTAUpdates(Box::new(OTAUpdatesContext {
69            channel: Annotated::new("production".to_string()),
70            runtime_version: Annotated::new("1.0.0".to_string()),
71            update_id: Annotated::new("12345678-1234-1234-1234-1234567890ab".to_string()),
72            other: Object::default(),
73        })));
74
75        assert_eq!(context, Annotated::from_json(json).unwrap());
76        assert_eq!(json, context.to_json_pretty().unwrap());
77    }
78
79    #[test]
80    fn test_ota_updates_context_with_extra_keys() {
81        let json: &str = r#"{
82  "channel": "production",
83  "runtime_version": "1.0.0",
84  "update_id": "12345678-1234-1234-1234-1234567890ab",
85  "created_at": "2023-01-01T00:00:00.000Z",
86  "emergency_launch_reason": "some reason",
87  "is_embedded_launch": false,
88  "is_emergency_launch": true,
89  "is_enabled": true,
90  "launch_duration": 1000,
91  "type": "otaupdates"
92}"#;
93        let mut other = Object::new();
94        other.insert("is_enabled".to_string(), Annotated::new(Value::Bool(true)));
95        other.insert(
96            "is_embedded_launch".to_string(),
97            Annotated::new(Value::Bool(false)),
98        );
99        other.insert(
100            "is_emergency_launch".to_string(),
101            Annotated::new(Value::Bool(true)),
102        );
103        other.insert(
104            "emergency_launch_reason".to_string(),
105            Annotated::new(Value::String("some reason".to_string())),
106        );
107        other.insert(
108            "launch_duration".to_string(),
109            Annotated::new(Value::I64(1000)),
110        );
111        other.insert(
112            "created_at".to_string(),
113            Annotated::new(Value::String("2023-01-01T00:00:00.000Z".to_string())),
114        );
115
116        let context = Annotated::new(Context::OTAUpdates(Box::new(OTAUpdatesContext {
117            channel: Annotated::new("production".to_string()),
118            runtime_version: Annotated::new("1.0.0".to_string()),
119            update_id: Annotated::new("12345678-1234-1234-1234-1234567890ab".to_string()),
120            other,
121        })));
122
123        assert_eq!(context, Annotated::from_json(json).unwrap());
124        assert_eq!(json, context.to_json_pretty().unwrap());
125    }
126
127    #[test]
128    fn test_ota_updates_context_with_is_enabled_false() {
129        let json: &str = r#"{
130  "is_enabled": false,
131  "type": "otaupdates"
132}"#;
133        let mut other = Object::new();
134        other.insert("is_enabled".to_string(), Annotated::new(Value::Bool(false)));
135
136        let context = Annotated::new(Context::OTAUpdates(Box::new(OTAUpdatesContext {
137            channel: Annotated::empty(),
138            runtime_version: Annotated::empty(),
139            update_id: Annotated::empty(),
140            other,
141        })));
142
143        assert_eq!(context, Annotated::from_json(json).unwrap());
144        assert_eq!(json, context.to_json_pretty().unwrap());
145    }
146}