allsource_core/application/use_cases/
manage_schema.rs1use crate::{
2 application::dto::{
3 ListSchemasResponse, RegisterSchemaRequest, RegisterSchemaResponse, SchemaDto,
4 UpdateSchemaRequest,
5 },
6 domain::entities::{CompatibilityMode, Schema},
7 error::Result,
8};
9
10pub struct RegisterSchemaUseCase;
14
15impl RegisterSchemaUseCase {
16 pub fn execute(request: RegisterSchemaRequest) -> Result<RegisterSchemaResponse> {
17 let compatibility_mode = request
19 .compatibility_mode
20 .map(CompatibilityMode::from)
21 .unwrap_or(CompatibilityMode::None);
22
23 let mut schema = Schema::new_v1(request.subject, request.schema, compatibility_mode)?;
25
26 if let Some(description) = request.description {
28 schema.set_description(description)?;
29 }
30
31 if let Some(tags) = request.tags {
33 for tag in tags {
34 schema.add_tag(tag)?;
35 }
36 }
37
38 Ok(RegisterSchemaResponse {
39 schema: SchemaDto::from(&schema),
40 })
41 }
42}
43
44pub struct CreateNextSchemaVersionUseCase;
48
49impl CreateNextSchemaVersionUseCase {
50 pub fn execute(
51 current_schema: &Schema,
52 new_schema_definition: serde_json::Value,
53 description: Option<String>,
54 ) -> Result<SchemaDto> {
55 let mut next_schema = current_schema.create_next_version(new_schema_definition)?;
57
58 if let Some(desc) = description {
60 next_schema.set_description(desc)?;
61 }
62
63 for tag in current_schema.tags() {
65 next_schema.add_tag(tag.clone())?;
66 }
67
68 Ok(SchemaDto::from(&next_schema))
69 }
70}
71
72pub struct UpdateSchemaMetadataUseCase;
76
77impl UpdateSchemaMetadataUseCase {
78 pub fn execute(mut schema: Schema, request: UpdateSchemaRequest) -> Result<SchemaDto> {
79 if let Some(description) = request.description {
81 if description.is_empty() {
82 schema.clear_description();
83 } else {
84 schema.set_description(description)?;
85 }
86 }
87
88 if let Some(tags) = request.tags {
90 for existing_tag in schema.tags().to_vec() {
92 schema.remove_tag(&existing_tag)?;
93 }
94 for tag in tags {
95 schema.add_tag(tag)?;
96 }
97 }
98
99 Ok(SchemaDto::from(&schema))
100 }
101}
102
103pub struct ListSchemasUseCase;
107
108impl ListSchemasUseCase {
109 pub fn execute(schemas: Vec<Schema>) -> ListSchemasResponse {
110 let schema_dtos: Vec<SchemaDto> = schemas.iter().map(SchemaDto::from).collect();
111 let count = schema_dtos.len();
112
113 ListSchemasResponse {
114 schemas: schema_dtos,
115 count,
116 }
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use crate::application::dto::CompatibilityModeDto;
124 use serde_json::json;
125
126 #[test]
127 fn test_register_schema() {
128 let request = RegisterSchemaRequest {
129 subject: "user.created".to_string(),
130 schema: json!({
131 "type": "object",
132 "properties": {
133 "name": {"type": "string"},
134 "email": {"type": "string"}
135 }
136 }),
137 compatibility_mode: Some(CompatibilityModeDto::Backward),
138 description: Some("User creation event schema".to_string()),
139 tags: Some(vec!["user".to_string(), "core".to_string()]),
140 };
141
142 let response = RegisterSchemaUseCase::execute(request);
143 assert!(response.is_ok());
144
145 let response = response.unwrap();
146 assert_eq!(response.schema.subject, "user.created");
147 assert_eq!(response.schema.version, 1);
148 assert_eq!(response.schema.tags.len(), 2);
149 assert_eq!(
150 response.schema.compatibility_mode,
151 CompatibilityModeDto::Backward
152 );
153 }
154
155 #[test]
156 fn test_create_next_version() {
157 let schema = Schema::new_v1(
158 "order.placed".to_string(),
159 json!({"type": "object"}),
160 CompatibilityMode::None,
161 )
162 .unwrap();
163
164 let new_schema = json!({
165 "type": "object",
166 "properties": {
167 "amount": {"type": "number"}
168 }
169 });
170
171 let result = CreateNextSchemaVersionUseCase::execute(
172 &schema,
173 new_schema,
174 Some("Version 2".to_string()),
175 );
176
177 assert!(result.is_ok());
178 let next = result.unwrap();
179 assert_eq!(next.version, 2);
180 assert_eq!(next.subject, "order.placed");
181 }
182
183 #[test]
184 fn test_update_schema_metadata() {
185 let mut schema = Schema::new_v1(
186 "test.event".to_string(),
187 json!({"type": "object"}),
188 CompatibilityMode::None,
189 )
190 .unwrap();
191
192 schema.add_tag("old-tag".to_string()).unwrap();
193
194 let request = UpdateSchemaRequest {
195 description: Some("Updated description".to_string()),
196 tags: Some(vec!["new-tag".to_string()]),
197 compatibility_mode: None,
198 };
199
200 let result = UpdateSchemaMetadataUseCase::execute(schema, request);
201 assert!(result.is_ok());
202
203 let updated = result.unwrap();
204 assert_eq!(updated.description, Some("Updated description".to_string()));
205 assert_eq!(updated.tags, vec!["new-tag".to_string()]);
206 }
207
208 #[test]
209 fn test_list_schemas() {
210 let schemas = vec![
211 Schema::new_v1(
212 "event.one".to_string(),
213 json!({"type": "object"}),
214 CompatibilityMode::None,
215 )
216 .unwrap(),
217 Schema::new_v1(
218 "event.two".to_string(),
219 json!({"type": "object"}),
220 CompatibilityMode::Backward,
221 )
222 .unwrap(),
223 ];
224
225 let response = ListSchemasUseCase::execute(schemas);
226 assert_eq!(response.count, 2);
227 assert_eq!(response.schemas.len(), 2);
228 }
229}