feat: vertical slice — migrations, postgres adapters, presentation handlers, bootstrap wiring
This commit is contained in:
@@ -153,14 +153,12 @@ impl AssetMetadataRepository for PostgresAssetMetadataRepository {
|
||||
asset_id: &SystemId,
|
||||
source: MetadataSource,
|
||||
) -> Result<(), DomainError> {
|
||||
sqlx::query(
|
||||
"DELETE FROM asset_metadata WHERE asset_id = $1 AND metadata_source = $2",
|
||||
)
|
||||
.bind(*asset_id.as_uuid())
|
||||
.bind(source_to_str(&source))
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.map_err(|e| DomainError::Internal(e.to_string()))?;
|
||||
sqlx::query("DELETE FROM asset_metadata WHERE asset_id = $1 AND metadata_source = $2")
|
||||
.bind(*asset_id.as_uuid())
|
||||
.bind(source_to_str(&source))
|
||||
.execute(&self.pool)
|
||||
.await
|
||||
.map_err(|e| DomainError::Internal(e.to_string()))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
use crate::db::PgPool;
|
||||
use async_trait::async_trait;
|
||||
use domain::{
|
||||
entities::StorageVolume,
|
||||
errors::DomainError,
|
||||
ports::StorageVolumeRepository,
|
||||
entities::StorageVolume, errors::DomainError, ports::StorageVolumeRepository,
|
||||
value_objects::SystemId,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -42,7 +42,10 @@ impl PostgresUserRepository {
|
||||
|
||||
#[async_trait]
|
||||
impl UserRepository for PostgresUserRepository {
|
||||
async fn find_by_id(&self, id: &SystemId) -> Result<Option<domain::entities::User>, DomainError> {
|
||||
async fn find_by_id(
|
||||
&self,
|
||||
id: &SystemId,
|
||||
) -> Result<Option<domain::entities::User>, DomainError> {
|
||||
let row = sqlx::query_as::<_, UserRow>(
|
||||
"SELECT id, username, email, password_hash, created_at FROM users WHERE id = $1",
|
||||
)
|
||||
@@ -54,7 +57,10 @@ impl UserRepository for PostgresUserRepository {
|
||||
row.map(TryInto::try_into).transpose()
|
||||
}
|
||||
|
||||
async fn find_by_email(&self, email: &Email) -> Result<Option<domain::entities::User>, DomainError> {
|
||||
async fn find_by_email(
|
||||
&self,
|
||||
email: &Email,
|
||||
) -> Result<Option<domain::entities::User>, DomainError> {
|
||||
let row = sqlx::query_as::<_, UserRow>(
|
||||
"SELECT id, username, email, password_hash, created_at FROM users WHERE email = $1",
|
||||
)
|
||||
@@ -66,7 +72,10 @@ impl UserRepository for PostgresUserRepository {
|
||||
row.map(TryInto::try_into).transpose()
|
||||
}
|
||||
|
||||
async fn find_by_username(&self, username: &str) -> Result<Option<domain::entities::User>, DomainError> {
|
||||
async fn find_by_username(
|
||||
&self,
|
||||
username: &str,
|
||||
) -> Result<Option<domain::entities::User>, DomainError> {
|
||||
let row = sqlx::query_as::<_, UserRow>(
|
||||
"SELECT id, username, email, password_hash, created_at FROM users WHERE username = $1",
|
||||
)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
use async_trait::async_trait;
|
||||
use bytes::Bytes;
|
||||
use domain::errors::DomainError;
|
||||
use domain::ports::{DataStream, StorageReader, StorageWriter};
|
||||
use futures::stream::StreamExt;
|
||||
|
||||
@@ -44,12 +44,10 @@ impl FileStoragePort for LocalFileStorage {
|
||||
|
||||
async fn read_file(&self, path: &str) -> Result<Bytes, DomainError> {
|
||||
let full = self.resolve(path)?;
|
||||
let data = tokio::fs::read(&full)
|
||||
.await
|
||||
.map_err(|e| match e.kind() {
|
||||
std::io::ErrorKind::NotFound => DomainError::NotFound(path.to_string()),
|
||||
_ => DomainError::Internal(format!("Failed to read file: {e}")),
|
||||
})?;
|
||||
let data = tokio::fs::read(&full).await.map_err(|e| match e.kind() {
|
||||
std::io::ErrorKind::NotFound => DomainError::NotFound(path.to_string()),
|
||||
_ => DomainError::Internal(format!("Failed to read file: {e}")),
|
||||
})?;
|
||||
Ok(Bytes::from(data))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user