use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
#[derive(Debug, Deserialize, ToSchema)]
pub struct CreateConnectionRequest {
pub kind: Option<String>,
pub provider: String,
pub name: String,
pub config: serde_json::Value,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct ConnectionResponse {
pub id: String,
pub kind: String,
pub provider: String,
pub name: String,
pub created_at: i64,
pub updated_at: i64,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct ConnectionListResponse {
pub data: Vec<ConnectionResponse>,
}
#[derive(Debug, Deserialize, ToSchema)]
pub struct UpdateConnectionRequest {
pub name: Option<String>,
pub config: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct ConnectionTestResponse {
pub ok: bool,
pub provider: String,
pub message: Option<String>,
pub scope: Option<serde_json::Value>,
}
#[derive(Debug, Deserialize, ToSchema)]
pub struct TriggerSyncRequest {
#[serde(default = "default_strategy")]
pub strategy: String,
pub file_keys: Option<Vec<String>>,
pub endpoint: Option<String>,
pub completion_window: Option<String>,
#[serde(default)]
pub force: bool,
}
fn default_strategy() -> String {
"snapshot".to_string()
}
#[derive(Debug, Serialize, ToSchema)]
pub struct SyncOperationResponse {
pub id: String,
pub connection_id: String,
pub status: String,
pub strategy: String,
pub files_found: i32,
pub files_skipped: i32,
pub files_ingested: i32,
pub files_failed: i32,
pub batches_created: i32,
pub error_summary: Option<serde_json::Value>,
pub started_at: Option<i64>,
pub completed_at: Option<i64>,
pub created_at: i64,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct SyncOperationListResponse {
pub data: Vec<SyncOperationResponse>,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct SyncEntryResponse {
pub id: String,
pub external_key: String,
pub external_size_bytes: Option<i64>,
pub status: String,
pub file_id: Option<String>,
pub batch_id: Option<String>,
pub template_count: Option<i32>,
pub error: Option<String>,
pub skipped_lines: i32,
#[serde(skip_serializing_if = "Option::is_none")]
pub validation_errors: Option<serde_json::Value>,
pub created_at: i64,
pub updated_at: i64,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct SyncEntryListResponse {
pub data: Vec<SyncEntryResponse>,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct SyncedKeyResponse {
pub key: String,
pub last_modified: Option<i64>,
pub status: String,
}
#[derive(Debug, Deserialize)]
pub struct ListConnectionsQuery {
pub kind: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct ListExternalFilesQuery {
pub limit: Option<usize>,
pub cursor: Option<String>,
pub search: Option<String>,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct ExternalFileResponse {
pub key: String,
pub size_bytes: Option<i64>,
pub last_modified: Option<i64>,
pub display_name: Option<String>,
}
#[derive(Debug, Serialize, ToSchema)]
pub struct ExternalFileListResponse {
pub data: Vec<ExternalFileResponse>,
pub has_more: bool,
pub next_cursor: Option<String>,
}
impl From<crate::db::models::connections::Connection> for ConnectionResponse {
fn from(c: crate::db::models::connections::Connection) -> Self {
Self {
id: c.id.to_string(),
kind: c.kind,
provider: c.provider,
name: c.name,
created_at: c.created_at.timestamp(),
updated_at: c.updated_at.timestamp(),
}
}
}
impl From<crate::db::models::connections::SyncOperation> for SyncOperationResponse {
fn from(s: crate::db::models::connections::SyncOperation) -> Self {
Self {
id: s.id.to_string(),
connection_id: s.connection_id.to_string(),
status: s.status,
strategy: s.strategy,
files_found: s.files_found,
files_skipped: s.files_skipped,
files_ingested: s.files_ingested,
files_failed: s.files_failed,
batches_created: s.batches_created,
error_summary: s.error_summary,
started_at: s.started_at.map(|dt| dt.timestamp()),
completed_at: s.completed_at.map(|dt| dt.timestamp()),
created_at: s.created_at.timestamp(),
}
}
}
impl From<crate::db::models::connections::SyncEntry> for SyncEntryResponse {
fn from(e: crate::db::models::connections::SyncEntry) -> Self {
Self {
id: e.id.to_string(),
external_key: e.external_key,
external_size_bytes: e.external_size_bytes,
status: e.status,
file_id: e.file_id.map(|id| id.to_string()),
batch_id: e.batch_id.map(|id| id.to_string()),
template_count: e.template_count,
error: e.error,
skipped_lines: e.skipped_lines,
validation_errors: e.validation_errors,
created_at: e.created_at.timestamp(),
updated_at: e.updated_at.timestamp(),
}
}
}