gitdataai/libs/service/skill/info.rs
2026-04-14 19:02:01 +08:00

105 lines
3.3 KiB
Rust

//! List and retrieve project skills.
use crate::AppService;
use crate::error::AppError;
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter, QueryOrder};
use serde::{Deserialize, Serialize};
use session::Session;
use utoipa::ToSchema;
#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct SkillResponse {
pub id: i64,
pub project_uuid: String,
pub slug: String,
pub name: String,
pub description: Option<String>,
pub source: String,
pub repo_id: Option<String>,
pub commit_sha: Option<String>,
pub blob_hash: Option<String>,
pub content: String,
pub metadata: serde_json::Value,
pub enabled: bool,
pub created_by: Option<String>,
pub created_at: chrono::DateTime<chrono::Utc>,
pub updated_at: chrono::DateTime<chrono::Utc>,
}
impl From<models::projects::project_skill::Model> for SkillResponse {
fn from(s: models::projects::project_skill::Model) -> Self {
Self {
id: s.id,
project_uuid: s.project_uuid.to_string(),
slug: s.slug,
name: s.name,
description: s.description,
source: s.source,
repo_id: s.repo_id.map(|id| id.to_string()),
commit_sha: s.commit_sha,
blob_hash: s.blob_hash,
content: s.content,
metadata: s.metadata,
enabled: s.enabled,
created_by: s.created_by.map(|id| id.to_string()),
created_at: s.created_at,
updated_at: s.updated_at,
}
}
}
#[derive(Debug, Clone, Deserialize, utoipa::IntoParams)]
pub struct SkillListQuery {
pub source: Option<String>,
pub enabled: Option<bool>,
}
impl AppService {
/// List all skills registered to a project.
pub async fn skill_list(
&self,
project_uuid: String,
query: SkillListQuery,
_ctx: &Session,
) -> Result<Vec<SkillResponse>, AppError> {
let project_id = uuid::Uuid::parse_str(&project_uuid)
.map_err(|_| AppError::BadRequest("Invalid project UUID".to_string()))?;
use models::projects::project_skill::Column as C;
let mut q = models::projects::project_skill::Entity::find()
.filter(C::ProjectUuid.eq(project_id))
.order_by_asc(C::Name);
if let Some(source) = &query.source {
q = q.filter(C::Source.eq(source.clone()));
}
if let Some(enabled) = query.enabled {
q = q.filter(C::Enabled.eq(enabled));
}
let skills = q.all(&self.db).await?;
Ok(skills.into_iter().map(SkillResponse::from).collect())
}
/// Get a single skill by slug within a project.
pub async fn skill_get(
&self,
project_uuid: String,
slug: String,
_ctx: &Session,
) -> Result<SkillResponse, AppError> {
let project_id = uuid::Uuid::parse_str(&project_uuid)
.map_err(|_| AppError::BadRequest("Invalid project UUID".to_string()))?;
use models::projects::project_skill::Column as C;
let skill = models::projects::project_skill::Entity::find()
.filter(C::ProjectUuid.eq(project_id))
.filter(C::Slug.eq(slug))
.one(&self.db)
.await?
.ok_or_else(|| AppError::NotFound("Skill not found".to_string()))?;
Ok(SkillResponse::from(skill))
}
}