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