allsource_core/application/use_cases/
manage_schema.rs1use crate::application::dto::{
2 ListSchemasResponse, RegisterSchemaRequest, RegisterSchemaResponse, SchemaDto,
3 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 crate::application::dto::CompatibilityModeDto;
122 use serde_json::json;
123
124 #[test]
125 fn test_register_schema() {
126 let request = RegisterSchemaRequest {
127 subject: "user.created".to_string(),
128 schema: json!({
129 "type": "object",
130 "properties": {
131 "name": {"type": "string"},
132 "email": {"type": "string"}
133 }
134 }),
135 compatibility_mode: Some(CompatibilityModeDto::Backward),
136 description: Some("User creation event schema".to_string()),
137 tags: Some(vec!["user".to_string(), "core".to_string()]),
138 };
139
140 let response = RegisterSchemaUseCase::execute(request);
141 assert!(response.is_ok());
142
143 let response = response.unwrap();
144 assert_eq!(response.schema.subject, "user.created");
145 assert_eq!(response.schema.version, 1);
146 assert_eq!(response.schema.tags.len(), 2);
147 assert_eq!(
148 response.schema.compatibility_mode,
149 CompatibilityModeDto::Backward
150 );
151 }
152
153 #[test]
154 fn test_create_next_version() {
155 let schema = Schema::new_v1(
156 "order.placed".to_string(),
157 json!({"type": "object"}),
158 CompatibilityMode::None,
159 )
160 .unwrap();
161
162 let new_schema = json!({
163 "type": "object",
164 "properties": {
165 "amount": {"type": "number"}
166 }
167 });
168
169 let result = CreateNextSchemaVersionUseCase::execute(
170 &schema,
171 new_schema,
172 Some("Version 2".to_string()),
173 );
174
175 assert!(result.is_ok());
176 let next = result.unwrap();
177 assert_eq!(next.version, 2);
178 assert_eq!(next.subject, "order.placed");
179 }
180
181 #[test]
182 fn test_update_schema_metadata() {
183 let mut schema = Schema::new_v1(
184 "test.event".to_string(),
185 json!({"type": "object"}),
186 CompatibilityMode::None,
187 )
188 .unwrap();
189
190 schema.add_tag("old-tag".to_string()).unwrap();
191
192 let request = UpdateSchemaRequest {
193 description: Some("Updated description".to_string()),
194 tags: Some(vec!["new-tag".to_string()]),
195 compatibility_mode: None,
196 };
197
198 let result = UpdateSchemaMetadataUseCase::execute(schema, request);
199 assert!(result.is_ok());
200
201 let updated = result.unwrap();
202 assert_eq!(updated.description, Some("Updated description".to_string()));
203 assert_eq!(updated.tags, vec!["new-tag".to_string()]);
204 }
205
206 #[test]
207 fn test_list_schemas() {
208 let schemas = vec![
209 Schema::new_v1(
210 "event.one".to_string(),
211 json!({"type": "object"}),
212 CompatibilityMode::None,
213 )
214 .unwrap(),
215 Schema::new_v1(
216 "event.two".to_string(),
217 json!({"type": "object"}),
218 CompatibilityMode::Backward,
219 )
220 .unwrap(),
221 ];
222
223 let response = ListSchemasUseCase::execute(schemas);
224 assert_eq!(response.count, 2);
225 assert_eq!(response.schemas.len(), 2);
226 }
227}