backbone-bucket 0.2.0

Bucket Bounded Context: File Storage Module for Backbone Framework
Documentation
//! Commands for Bucket aggregate
//!
//! Generated by backbone-schema. Do not edit manually.
//!
//! CQRS Commands represent intent to change state.

use async_trait::async_trait;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use uuid::Uuid;

use crate::domain::entity::Bucket;
use crate::infrastructure::persistence::BucketRepository;
use super::CommandHandler;

// ============================================================================
// COMMAND TRAIT (DEPRECATED)
// ============================================================================

/// Command trait for Bucket operations
///
/// **DEPRECATED**: Use the generic `CommandHandler<C>` trait from `mod.rs` instead.
/// This trait is kept for backwards compatibility.
#[deprecated(since = "0.2.0", note = "Use CommandHandler<C> trait instead")]
#[async_trait]
pub trait BucketCommand: Send + Sync {
    type Output;
    async fn execute(&self) -> Result<Self::Output>;
}

// ============================================================================
// CREATE COMMAND
// ============================================================================

/// Command to create a new bucket
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateBucketCommand {
    pub name: String,
    pub slug: String,
    pub description: Option<String>,
    pub owner_id: Uuid,
    pub bucket_type: BucketType,
    pub status: BucketStatus,
    pub storage_backend: StorageBackend,
    pub root_path: String,
    pub file_count: i32,
    pub total_size_bytes: i64,
    pub max_file_size: Option<i64>,
    pub allowed_mime_types: Vec<String>,
    pub auto_delete_after_days: Option<i32>,
    pub enable_cdn: bool,
    pub enable_versioning: bool,
    pub enable_deduplication: bool,
    pub metadata: serde_json::Value,
}

/// Handler for CreateBucketCommand
pub struct CreateBucketHandler<R: BucketRepository> {
    repository: std::sync::Arc<R>,
}

impl<R: BucketRepository> CreateBucketHandler<R> {
    pub fn new(repository: std::sync::Arc<R>) -> Self {
        Self { repository }
    }
}

#[async_trait]
impl<R: BucketRepository + 'static> CommandHandler<CreateBucketCommand> for CreateBucketHandler<R> {
    type Output = Bucket;

    async fn handle(&self, cmd: CreateBucketCommand) -> Result<Self::Output> {
        let entity = Bucket::builder()
            .id(Uuid::new_v4().to_string())
            .name(cmd.name)
            .slug(cmd.slug)
            .description(cmd.description)
            .owner_id(cmd.owner_id)
            .bucket_type(cmd.bucket_type)
            .status(cmd.status)
            .storage_backend(cmd.storage_backend)
            .root_path(cmd.root_path)
            .file_count(cmd.file_count)
            .total_size_bytes(cmd.total_size_bytes)
            .max_file_size(cmd.max_file_size)
            .allowed_mime_types(cmd.allowed_mime_types)
            .auto_delete_after_days(cmd.auto_delete_after_days)
            .enable_cdn(cmd.enable_cdn)
            .enable_versioning(cmd.enable_versioning)
            .enable_deduplication(cmd.enable_deduplication)
            .metadata(cmd.metadata)
            .build()?;

        self.repository.save(&entity).await
    }
}

// ============================================================================
// UPDATE COMMAND
// ============================================================================

/// Command to update an existing bucket
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateBucketCommand {
    pub id: String,
    pub name: Option<String>,
    pub slug: Option<String>,
    pub description: Option<String>,
    pub owner_id: Option<Uuid>,
    pub bucket_type: Option<BucketType>,
    pub status: Option<BucketStatus>,
    pub storage_backend: Option<StorageBackend>,
    pub root_path: Option<String>,
    pub file_count: Option<i32>,
    pub total_size_bytes: Option<i64>,
    pub max_file_size: Option<i64>,
    pub allowed_mime_types: Option<Vec<String>>,
    pub auto_delete_after_days: Option<i32>,
    pub enable_cdn: Option<bool>,
    pub enable_versioning: Option<bool>,
    pub enable_deduplication: Option<bool>,
    pub metadata: Option<serde_json::Value>,
}

/// Handler for UpdateBucketCommand
pub struct UpdateBucketHandler<R: BucketRepository> {
    repository: std::sync::Arc<R>,
}

impl<R: BucketRepository> UpdateBucketHandler<R> {
    pub fn new(repository: std::sync::Arc<R>) -> Self {
        Self { repository }
    }
}

#[async_trait]
impl<R: BucketRepository + 'static> CommandHandler<UpdateBucketCommand> for UpdateBucketHandler<R> {
    type Output = Option<Bucket>;

    async fn handle(&self, cmd: UpdateBucketCommand) -> Result<Self::Output> {
        let existing = self.repository.find_by_id(&cmd.id).await?;

        let Some(mut entity) = existing else {
            return Ok(None);
        };

        // Apply updates
        if let Some(value) = cmd.name {
            entity.name = value;
        }
        if let Some(value) = cmd.slug {
            entity.slug = value;
        }
        entity.description = cmd.description;
        if let Some(value) = cmd.owner_id {
            entity.owner_id = value;
        }
        if let Some(value) = cmd.bucket_type {
            entity.bucket_type = value;
        }
        if let Some(value) = cmd.status {
            entity.status = value;
        }
        if let Some(value) = cmd.storage_backend {
            entity.storage_backend = value;
        }
        if let Some(value) = cmd.root_path {
            entity.root_path = value;
        }
        if let Some(value) = cmd.file_count {
            entity.file_count = value;
        }
        if let Some(value) = cmd.total_size_bytes {
            entity.total_size_bytes = value;
        }
        entity.max_file_size = cmd.max_file_size;
        if let Some(value) = cmd.allowed_mime_types {
            entity.allowed_mime_types = value;
        }
        entity.auto_delete_after_days = cmd.auto_delete_after_days;
        if let Some(value) = cmd.enable_cdn {
            entity.enable_cdn = value;
        }
        if let Some(value) = cmd.enable_versioning {
            entity.enable_versioning = value;
        }
        if let Some(value) = cmd.enable_deduplication {
            entity.enable_deduplication = value;
        }
        if let Some(value) = cmd.metadata {
            entity.metadata = value;
        }

        self.repository.update(&cmd.id, &entity).await
    }
}

// ============================================================================
// DELETE COMMAND
// ============================================================================

/// Command to delete a bucket
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteBucketCommand {
    pub id: String,
    pub hard_delete: bool,
}

/// Handler for DeleteBucketCommand
pub struct DeleteBucketHandler<R: BucketRepository> {
    repository: std::sync::Arc<R>,
}

impl<R: BucketRepository> DeleteBucketHandler<R> {
    pub fn new(repository: std::sync::Arc<R>) -> Self {
        Self { repository }
    }
}

#[async_trait]
impl<R: BucketRepository + 'static> CommandHandler<DeleteBucketCommand> for DeleteBucketHandler<R> {
    type Output = bool;

    async fn handle(&self, cmd: DeleteBucketCommand) -> Result<Self::Output> {
        if cmd.hard_delete {
            self.repository.delete(&cmd.id).await
        } else {
            self.repository.soft_delete(&cmd.id).await
        }
    }
}

// ============================================================================
// CUSTOM COMMANDS
// ============================================================================
// <<< CUSTOM COMMANDS START >>>

// <<< CUSTOM COMMANDS START >>>
// Add your custom commands here
// Example:
//
// #[derive(Debug, Clone, Serialize, Deserialize)]
// pub struct ActivateBucketCommand {
//     pub id: String,
// }
// <<< CUSTOM COMMANDS END >>>