cognee_http_server/dto/
forget.rs1use serde::{Deserialize, Deserializer, Serialize};
4use utoipa::ToSchema;
5use uuid::Uuid;
6
7#[derive(Debug, Clone, Deserialize, ToSchema)]
12#[serde(rename_all = "camelCase")]
13pub struct ForgetPayloadDTO {
14 #[serde(default, alias = "data_id")]
17 pub data_id: Option<Uuid>,
18
19 #[serde(default)]
23 pub dataset: Option<DatasetRef>,
24
25 #[serde(default)]
27 pub everything: bool,
28}
29
30#[derive(Debug, Clone)]
35pub enum DatasetRef {
36 Id(Uuid),
37 Name(String),
38}
39
40impl utoipa::ToSchema for DatasetRef {
41 fn name() -> std::borrow::Cow<'static, str> {
42 std::borrow::Cow::Borrowed("DatasetRef")
43 }
44}
45
46impl utoipa::PartialSchema for DatasetRef {
47 fn schema() -> utoipa::openapi::RefOr<utoipa::openapi::Schema> {
48 utoipa::openapi::RefOr::T(utoipa::openapi::Schema::Object(
49 utoipa::openapi::ObjectBuilder::new()
50 .schema_type(utoipa::openapi::schema::Type::String)
51 .description(Some("Dataset name or UUID string. UUID is tried first."))
52 .build(),
53 ))
54 }
55}
56
57impl<'de> Deserialize<'de> for DatasetRef {
58 fn deserialize<D: Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
59 let s = String::deserialize(d)?;
61 match Uuid::parse_str(&s) {
62 Ok(u) => Ok(DatasetRef::Id(u)),
63 Err(_) => Ok(DatasetRef::Name(s)),
64 }
65 }
66}
67
68#[derive(Debug, Clone, Serialize, ToSchema)]
70#[serde(rename_all = "snake_case")]
71pub struct ForgetDataItemResponse {
72 pub data_id: Uuid,
73 pub dataset_id: Uuid,
74 pub status: String, }
76
77#[derive(Debug, Clone, Serialize, ToSchema)]
78#[serde(rename_all = "snake_case")]
79pub struct ForgetDatasetResponse {
80 pub dataset_id: Uuid,
81 pub status: String,
82}
83
84#[derive(Debug, Clone, Serialize, ToSchema)]
85#[serde(rename_all = "snake_case")]
86pub struct ForgetEverythingResponse {
87 pub datasets_removed: usize,
88 pub status: String,
89}
90
91#[derive(Debug, Clone, Serialize, ToSchema)]
92#[serde(untagged)]
93pub enum ForgetResponseDTO {
94 DataItem(ForgetDataItemResponse),
95 Dataset(ForgetDatasetResponse),
96 Everything(ForgetEverythingResponse),
97}
98
99#[derive(Debug, Serialize, ToSchema)]
101pub struct ForgetErrorResponseDTO {
102 pub error: String,
103}
104
105impl ForgetPayloadDTO {
106 pub fn resolve_mode(&self) -> Result<ForgetMode, &'static str> {
109 if self.everything {
110 return Ok(ForgetMode::Everything);
111 }
112 match (&self.data_id, &self.dataset) {
113 (Some(_), Some(_)) => Ok(ForgetMode::DataItem),
114 (None, Some(_)) => Ok(ForgetMode::Dataset),
115 (Some(_), None) => Err("data_id requires dataset to be specified."),
116 (None, None) => Err("Specify dataset, data_id+dataset, or everything=True."),
117 }
118 }
119}
120
121#[derive(Debug, Clone, Copy)]
122pub enum ForgetMode {
123 DataItem,
124 Dataset,
125 Everything,
126}
127
128#[cfg(test)]
129#[allow(
130 clippy::unwrap_used,
131 clippy::expect_used,
132 reason = "test code — panics are acceptable failures"
133)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn resolve_mode_everything_ignores_other_fields() {
139 let dto = ForgetPayloadDTO {
140 data_id: Some(Uuid::new_v4()),
141 dataset: Some(DatasetRef::Name("foo".into())),
142 everything: true,
143 };
144 assert!(matches!(dto.resolve_mode(), Ok(ForgetMode::Everything)));
145 }
146
147 #[test]
148 fn resolve_mode_data_item() {
149 let dto = ForgetPayloadDTO {
150 data_id: Some(Uuid::new_v4()),
151 dataset: Some(DatasetRef::Name("foo".into())),
152 everything: false,
153 };
154 assert!(matches!(dto.resolve_mode(), Ok(ForgetMode::DataItem)));
155 }
156
157 #[test]
158 fn resolve_mode_dataset_only() {
159 let dto = ForgetPayloadDTO {
160 data_id: None,
161 dataset: Some(DatasetRef::Name("foo".into())),
162 everything: false,
163 };
164 assert!(matches!(dto.resolve_mode(), Ok(ForgetMode::Dataset)));
165 }
166
167 #[test]
168 fn resolve_mode_data_id_without_dataset_errors() {
169 let dto = ForgetPayloadDTO {
170 data_id: Some(Uuid::new_v4()),
171 dataset: None,
172 everything: false,
173 };
174 assert!(dto.resolve_mode().is_err());
175 }
176
177 #[test]
178 fn resolve_mode_nothing_errors() {
179 let dto = ForgetPayloadDTO {
180 data_id: None,
181 dataset: None,
182 everything: false,
183 };
184 assert!(dto.resolve_mode().is_err());
185 }
186
187 #[test]
188 fn dataset_ref_deserialize_uuid() {
189 let uuid = Uuid::new_v4();
190 let s = format!("\"{uuid}\"");
191 let parsed: DatasetRef = serde_json::from_str(&s).unwrap();
192 assert!(matches!(parsed, DatasetRef::Id(_)));
193 }
194
195 #[test]
196 fn dataset_ref_deserialize_name() {
197 let parsed: DatasetRef = serde_json::from_str("\"my_dataset\"").unwrap();
198 assert!(matches!(parsed, DatasetRef::Name(_)));
199 }
200}