1use chrono::{DateTime, Utc};
2use schemars::JsonSchema;
3use serde::{Deserialize, Serialize};
4use utoipa::{IntoParams, ToSchema};
5use uuid::Uuid;
6
7use crate::Pagination;
8use crate::Visibility;
9
10#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
11#[serde(rename_all = "snake_case")]
12pub enum SourceOriginStatusKind {
13 Unknown,
14 Connected,
15 Unreachable,
16 Misconfigured,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
20pub struct SourceStatus {
21 pub group_key: String,
22 pub group_path: String,
23 pub visibility: Visibility,
24 pub source_key: String,
25 pub display_name: String,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
27 pub description: Option<String>,
28 #[serde(default)]
29 pub example_queries: Vec<String>,
30 pub connection: String,
31 pub has_database_url: bool,
32 pub origin_status: SourceOriginStatusKind,
33 #[serde(default, skip_serializing_if = "Option::is_none")]
34 pub origin_message: Option<String>,
35 pub sync_strategy: String,
36 pub connector_type: String,
37 pub base_query: String,
38 pub batch_size: i64,
39 pub last_cursor_updated_at: Option<DateTime<Utc>>,
40 pub last_cursor_external_id: Option<String>,
41 pub last_success_at: Option<DateTime<Utc>>,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
45pub struct ListSourcesResponse {
46 pub sources: Vec<SourceStatus>,
47}
48
49#[derive(Debug, Clone, Deserialize, IntoParams, ToSchema)]
50#[into_params(parameter_in = Query)]
51pub struct SourcePageQuery {
52 #[serde(default = "default_page")]
53 pub page: u32,
54 #[serde(default = "default_page_size")]
55 pub page_size: u32,
56 #[serde(default)]
57 pub query: Option<String>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
61pub struct SourcePageResponse {
62 pub items: Vec<SourceStatus>,
63 pub pagination: Pagination,
64}
65
66const fn default_page() -> u32 {
67 1
68}
69
70const fn default_page_size() -> u32 {
71 50
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize, ToSchema, JsonSchema)]
75pub struct SyncOutcome {
76 pub records_seen: usize,
77 pub records_changed: usize,
78 pub chunks_upserted: usize,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
82pub struct SourceConfigInput {
83 pub source_key: String,
84 #[serde(default, skip_serializing_if = "Option::is_none")]
85 pub display_name: Option<String>,
86 #[serde(default, skip_serializing_if = "Option::is_none")]
87 pub description: Option<String>,
88 #[serde(default)]
89 pub example_queries: Vec<String>,
90 pub connection: String,
91 #[serde(default, skip_serializing_if = "Option::is_none")]
92 pub database_url: Option<String>,
93 pub sync_strategy: String,
94 pub connector_type: String,
95 pub base_query: String,
96 pub batch_size: i64,
97 #[serde(default, skip_serializing_if = "Option::is_none")]
98 pub visibility: Option<Visibility>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
102pub struct SourceConnectionResponse {
103 pub name: String,
104 pub has_database_url: bool,
105 pub origin_status: SourceOriginStatusKind,
106 #[serde(default, skip_serializing_if = "Option::is_none")]
107 pub origin_message: Option<String>,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
111pub struct UpsertSourceConnectionRequest {
112 pub name: String,
113 #[serde(default, skip_serializing_if = "Option::is_none")]
114 pub database_url: Option<String>,
115}
116
117#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
118pub struct CreateSourceFolderRequest {
119 #[serde(default, skip_serializing_if = "Option::is_none")]
120 pub parent_folder_id: Option<Uuid>,
121 pub folder_name: String,
122 pub source_config: SourceConfigInput,
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
126pub struct SourceFolderResponse {
127 pub folder_id: Uuid,
128 pub source_config_file_id: Uuid,
129 pub records_folder_id: Uuid,
130 pub path: String,
131}