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