use crate::{
application::dto::{
ListSchemasResponse, RegisterSchemaRequest, RegisterSchemaResponse, SchemaDto,
UpdateSchemaRequest,
},
domain::entities::{CompatibilityMode, Schema},
error::Result,
};
pub struct RegisterSchemaUseCase;
impl RegisterSchemaUseCase {
pub fn execute(request: RegisterSchemaRequest) -> Result<RegisterSchemaResponse> {
let compatibility_mode = request
.compatibility_mode
.map_or(CompatibilityMode::None, CompatibilityMode::from);
let mut schema = Schema::new_v1(request.subject, request.schema, compatibility_mode)?;
if let Some(description) = request.description {
schema.set_description(description)?;
}
if let Some(tags) = request.tags {
for tag in tags {
schema.add_tag(tag)?;
}
}
Ok(RegisterSchemaResponse {
schema: SchemaDto::from(&schema),
})
}
}
pub struct CreateNextSchemaVersionUseCase;
impl CreateNextSchemaVersionUseCase {
pub fn execute(
current_schema: &Schema,
new_schema_definition: serde_json::Value,
description: Option<String>,
) -> Result<SchemaDto> {
let mut next_schema = current_schema.create_next_version(new_schema_definition)?;
if let Some(desc) = description {
next_schema.set_description(desc)?;
}
for tag in current_schema.tags() {
next_schema.add_tag(tag.clone())?;
}
Ok(SchemaDto::from(&next_schema))
}
}
pub struct UpdateSchemaMetadataUseCase;
impl UpdateSchemaMetadataUseCase {
pub fn execute(mut schema: Schema, request: UpdateSchemaRequest) -> Result<SchemaDto> {
if let Some(description) = request.description {
if description.is_empty() {
schema.clear_description();
} else {
schema.set_description(description)?;
}
}
if let Some(tags) = request.tags {
for existing_tag in schema.tags().to_vec() {
schema.remove_tag(&existing_tag)?;
}
for tag in tags {
schema.add_tag(tag)?;
}
}
Ok(SchemaDto::from(&schema))
}
}
pub struct ListSchemasUseCase;
impl ListSchemasUseCase {
pub fn execute(schemas: &[Schema]) -> ListSchemasResponse {
let schema_dtos: Vec<SchemaDto> = schemas.iter().map(SchemaDto::from).collect();
let count = schema_dtos.len();
ListSchemasResponse {
schemas: schema_dtos,
count,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::application::dto::CompatibilityModeDto;
use serde_json::json;
#[test]
fn test_register_schema() {
let request = RegisterSchemaRequest {
subject: "user.created".to_string(),
schema: json!({
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
}
}),
compatibility_mode: Some(CompatibilityModeDto::Backward),
description: Some("User creation event schema".to_string()),
tags: Some(vec!["user".to_string(), "core".to_string()]),
};
let response = RegisterSchemaUseCase::execute(request);
assert!(response.is_ok());
let response = response.unwrap();
assert_eq!(response.schema.subject, "user.created");
assert_eq!(response.schema.version, 1);
assert_eq!(response.schema.tags.len(), 2);
assert_eq!(
response.schema.compatibility_mode,
CompatibilityModeDto::Backward
);
}
#[test]
fn test_create_next_version() {
let schema = Schema::new_v1(
"order.placed".to_string(),
json!({"type": "object"}),
CompatibilityMode::None,
)
.unwrap();
let new_schema = json!({
"type": "object",
"properties": {
"amount": {"type": "number"}
}
});
let result = CreateNextSchemaVersionUseCase::execute(
&schema,
new_schema,
Some("Version 2".to_string()),
);
assert!(result.is_ok());
let next = result.unwrap();
assert_eq!(next.version, 2);
assert_eq!(next.subject, "order.placed");
}
#[test]
fn test_update_schema_metadata() {
let mut schema = Schema::new_v1(
"test.event".to_string(),
json!({"type": "object"}),
CompatibilityMode::None,
)
.unwrap();
schema.add_tag("old-tag".to_string()).unwrap();
let request = UpdateSchemaRequest {
description: Some("Updated description".to_string()),
tags: Some(vec!["new-tag".to_string()]),
compatibility_mode: None,
};
let result = UpdateSchemaMetadataUseCase::execute(schema, request);
assert!(result.is_ok());
let updated = result.unwrap();
assert_eq!(updated.description, Some("Updated description".to_string()));
assert_eq!(updated.tags, vec!["new-tag".to_string()]);
}
#[test]
fn test_list_schemas() {
let schemas = vec![
Schema::new_v1(
"event.one".to_string(),
json!({"type": "object"}),
CompatibilityMode::None,
)
.unwrap(),
Schema::new_v1(
"event.two".to_string(),
json!({"type": "object"}),
CompatibilityMode::Backward,
)
.unwrap(),
];
let response = ListSchemasUseCase::execute(&schemas);
assert_eq!(response.count, 2);
assert_eq!(response.schemas.len(), 2);
}
}