1use alloc::{collections::BTreeMap, string::String};
4use core::fmt;
5use core::str::FromStr;
6
7use chrono::{DateTime, Utc};
8#[cfg(feature = "schemars")]
9use schemars::JsonSchema;
10#[cfg(feature = "serde")]
11use serde::{Deserialize, Serialize};
12use serde_json::Value;
13
14use crate::{GResult, GreenticError, TenantCtx, validate_identifier};
15
16pub type EventMetadata = BTreeMap<String, String>;
18
19#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
21#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
22#[cfg_attr(feature = "schemars", derive(JsonSchema))]
23#[cfg_attr(feature = "serde", serde(try_from = "String", into = "String"))]
24pub struct EventId(String);
25
26impl EventId {
27 pub fn as_str(&self) -> &str {
29 &self.0
30 }
31
32 pub fn new(value: impl AsRef<str>) -> GResult<Self> {
34 value.as_ref().parse()
35 }
36
37 pub fn into_inner(self) -> String {
39 self.0
40 }
41}
42
43impl From<EventId> for String {
44 fn from(value: EventId) -> Self {
45 value.0
46 }
47}
48
49impl AsRef<str> for EventId {
50 fn as_ref(&self) -> &str {
51 self.as_str()
52 }
53}
54
55impl fmt::Display for EventId {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 f.write_str(self.as_str())
58 }
59}
60
61impl FromStr for EventId {
62 type Err = GreenticError;
63
64 fn from_str(value: &str) -> Result<Self, Self::Err> {
65 validate_identifier(value, "EventId")?;
66 Ok(Self(value.to_owned()))
67 }
68}
69
70impl TryFrom<String> for EventId {
71 type Error = GreenticError;
72
73 fn try_from(value: String) -> Result<Self, Self::Error> {
74 EventId::from_str(&value)
75 }
76}
77
78impl TryFrom<&str> for EventId {
79 type Error = GreenticError;
80
81 fn try_from(value: &str) -> Result<Self, Self::Error> {
82 EventId::from_str(value)
83 }
84}
85
86#[derive(Clone, Debug, PartialEq)]
88#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
89#[cfg_attr(feature = "schemars", derive(JsonSchema))]
90pub struct EventEnvelope {
91 pub id: EventId,
93 pub topic: String,
95 pub r#type: String,
97 pub source: String,
99 pub tenant: TenantCtx,
101 #[cfg_attr(
103 feature = "serde",
104 serde(default, skip_serializing_if = "Option::is_none")
105 )]
106 pub subject: Option<String>,
107 #[cfg_attr(
109 feature = "schemars",
110 schemars(with = "String", description = "RFC3339 timestamp in UTC")
111 )]
112 pub time: DateTime<Utc>,
113 #[cfg_attr(
115 feature = "serde",
116 serde(default, skip_serializing_if = "Option::is_none")
117 )]
118 pub correlation_id: Option<String>,
119 pub payload: Value,
121 #[cfg_attr(feature = "serde", serde(default))]
123 pub metadata: EventMetadata,
124}