use anyhow::Result;
use chrono::Utc;
use sea_orm::entity::prelude::*;
use sea_orm::{ActiveValue::Set, QueryOrder};
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel, Serialize, Deserialize)]
#[sea_orm(table_name = "repos")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
#[sea_orm(unique)]
pub slug: String,
pub provider: String,
pub workspace: String,
pub target_branch: String,
pub developer_focus: Option<String>,
pub custom_prompt: Option<String>,
pub token: String,
pub created_at: String,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
impl Model {
pub async fn insert_new(
db: &DatabaseConnection,
slug: &str,
provider: &str,
workspace: &str,
target_branch: &str,
developer_focus: Option<&str>,
custom_prompt: Option<&str>,
token: &str,
) -> Result<i32> {
let now = Utc::now().to_rfc3339();
let active = ActiveModel {
slug: Set(slug.to_string()),
provider: Set(provider.to_string()),
workspace: Set(workspace.to_string()),
target_branch: Set(target_branch.to_string()),
developer_focus: Set(developer_focus.map(|s| s.to_string())),
custom_prompt: Set(custom_prompt.map(|s| s.to_string())),
token: Set(token.to_string()),
created_at: Set(now),
..Default::default()
};
let result = active.insert(db).await?;
Ok(result.id)
}
pub async fn find_all(db: &DatabaseConnection) -> Result<Vec<Model>> {
let repos = Entity::find()
.order_by_asc(Column::Slug)
.all(db)
.await?;
Ok(repos)
}
pub async fn find_by_slug(db: &DatabaseConnection, slug: &str) -> Result<Option<Model>> {
let repo = Entity::find()
.filter(Column::Slug.eq(slug))
.one(db)
.await?;
Ok(repo)
}
pub async fn find_by_id(db: &DatabaseConnection, id: i32) -> Result<Option<Model>> {
let repo = Entity::find_by_id(id).one(db).await?;
Ok(repo)
}
pub async fn find_by_url(db: &DatabaseConnection, repo_url: &str) -> Result<Option<Model>> {
let repo = Entity::find()
.filter(Column::Slug.eq(repo_url))
.one(db)
.await?;
Ok(repo)
}
pub async fn update_repo(
db: &DatabaseConnection,
id: i32,
slug: &str,
provider: &str,
workspace: &str,
target_branch: &str,
developer_focus: Option<&str>,
custom_prompt: Option<&str>,
token: &str,
) -> Result<u64> {
let result = Entity::update_many()
.col_expr(Column::Slug, Expr::value(slug))
.col_expr(Column::Provider, Expr::value(provider))
.col_expr(Column::Workspace, Expr::value(workspace))
.col_expr(Column::TargetBranch, Expr::value(target_branch))
.col_expr(Column::DeveloperFocus, Expr::value(developer_focus))
.col_expr(Column::CustomPrompt, Expr::value(custom_prompt))
.col_expr(Column::Token, Expr::value(token))
.filter(Column::Id.eq(id))
.exec(db)
.await?;
Ok(result.rows_affected)
}
pub async fn delete(db: &DatabaseConnection, id: i32) -> Result<u64> {
let result = Entity::delete_by_id(id).exec(db).await?;
Ok(result.rows_affected)
}
pub async fn validate_slugs(db: &DatabaseConnection, slugs: &[&str]) -> Result<Vec<Model>> {
let mut repos: Vec<Model> = Vec::new();
for slug in slugs {
let repo = Entity::find()
.filter(Column::Slug.contains(*slug))
.one(db)
.await?;
if let Some(r) = repo {
if !repos.iter().any(|existing| existing.id == r.id) {
repos.push(r);
}
}
}
Ok(repos)
}
}