1use std::collections::BTreeMap;
7use std::path::PathBuf;
8
9use schemars::JsonSchema;
10use serde::Serialize;
11
12use crate::codes::{Code, ErrorCode, Kind};
13use crate::settings::Settings;
14
15type JsonMap = serde_json::Map<String, serde_json::Value>;
16
17pub const SCHEMA_VERSION: &str = "dre/run-results/v1";
19
20#[derive(Debug, Clone, Serialize, JsonSchema)]
22#[schemars(title = "DRE run results")]
23pub struct RunResults {
24 #[schemars(schema_with = "schema_version")]
26 pub schema_version: &'static str,
27 pub run_id: String,
29 pub report: String,
30 pub set: Option<String>,
32 pub binding: String,
34 pub managed: bool,
36 pub profile: Option<String>,
38 pub connections: Vec<String>,
40 pub target: String,
42 pub schedule: Option<String>,
44 pub schedule_vars: Option<JsonMap>,
46 pub vars: JsonMap,
48 pub run_date: String,
50 pub scheduled_at: Option<String>,
52 pub timezone: String,
54 pub params: Params,
56 pub status: Status,
57 pub error: Option<String>,
59 pub error_code: Option<ErrorCode>,
61 pub error_kind: Option<Kind>,
63 pub preview: bool,
65 pub row_limit: Option<u64>,
67 pub started_at: String,
69 pub duration_ms: u64,
70 pub result_sets: Vec<ResultSet>,
72 pub outputs: Vec<OutputFile>,
74 pub output_results: Vec<OutputResult>,
76 pub delivery: Option<String>,
78 pub deliveries: Vec<Delivery>,
80 pub schema_drift: Vec<String>,
82 pub target_path: PathBuf,
84 #[schemars(schema_with = "settings")]
86 pub settings: Settings,
87 pub manifest_checksum: Option<String>,
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, JsonSchema)]
93#[serde(rename_all = "snake_case")]
94pub enum Status {
95 Success,
96 Error,
97 DryRun,
99 Checked,
101 Cancelled,
103 TimedOut,
105}
106
107#[derive(Debug, Clone, Serialize, JsonSchema)]
109pub struct Params {
110 pub selector: Option<String>,
111 pub set: Option<String>,
112 pub schedule: Option<String>,
113 pub target: Option<String>,
115 pub profile: Option<String>,
117 pub vars: BTreeMap<String, String>,
119 pub run_date: String,
120 pub scheduled_at: Option<String>,
121 pub timezone: Option<String>,
123 pub output_name: Option<String>,
124 pub output_path: Option<String>,
125 pub dry_run: bool,
126 pub preview: Option<u64>,
127 pub accept_schema_change: bool,
128}
129
130#[derive(Debug, Clone, Serialize, JsonSchema)]
132pub struct ResultSet {
133 pub name: String,
135 pub query: String,
136 pub connection: String,
138 pub rows: u64,
139 pub columns: Vec<String>,
140}
141
142#[derive(Debug, Clone, Serialize, JsonSchema)]
144pub struct OutputFile {
145 pub path: PathBuf,
147 pub size: u64,
148 pub delivered_to: Option<String>,
150 pub output: Option<String>,
152}
153
154#[derive(Debug, Clone, Serialize, JsonSchema)]
156pub struct OutputResult {
157 pub name: Option<String>,
158 pub format: String,
159 pub queries: Vec<String>,
161 #[schemars(schema_with = "output_status")]
162 pub status: &'static str,
163 pub error: Option<String>,
164 pub files: Vec<OutputFileRef>,
165 pub delivery: Option<String>,
166 pub deliveries: Vec<Delivery>,
167 #[serde(skip_serializing_if = "Option::is_none")]
169 pub when: Option<bool>,
170 #[serde(skip_serializing_if = "Option::is_none")]
172 pub message: Option<Message>,
173}
174
175#[derive(Debug, Clone, Serialize, JsonSchema)]
177pub struct OutputFileRef {
178 pub path: PathBuf,
179 pub size: u64,
180 pub delivered_to: Option<String>,
181}
182
183#[derive(Debug, Clone, Serialize, JsonSchema)]
185pub struct Message {
186 pub title: String,
187 pub text: String,
188}
189
190#[derive(Debug, Clone, Serialize, JsonSchema)]
192pub struct Delivery {
193 pub profile: String,
195 #[serde(rename = "type")]
197 pub kind: Option<String>,
198 pub target: String,
200 #[schemars(schema_with = "delivery_status")]
201 pub status: &'static str,
202 #[serde(skip_serializing_if = "Option::is_none")]
204 pub location: Option<String>,
205 #[serde(skip_serializing_if = "Option::is_none")]
207 pub attempts: Option<u32>,
208 #[serde(skip_serializing_if = "Option::is_none")]
209 pub error: Option<String>,
210 #[serde(skip_serializing_if = "Option::is_none")]
211 pub error_code: Option<ErrorCode>,
212}
213
214fn schema_version(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
215 schemars::json_schema!({"const": SCHEMA_VERSION})
216}
217
218fn output_status(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
219 schemars::json_schema!({"enum": ["delivered", "kept", "skipped", "failed"]})
220}
221
222fn delivery_status(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
223 schemars::json_schema!({"enum": ["delivered", "not_delivered", "failed"]})
224}
225
226fn settings(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
227 schemars::json_schema!({
228 "type": "array",
229 "items": {
230 "type": "object",
231 "properties": {
232 "name": {"type": "string"},
233 "value": {"type": ["string", "null"]},
234 "source": {"type": "string", "description": "A flag (`--target`), an environment variable (`DRE_TARGET`), a dre_project.yml key, how it was found, or `default`."}
235 },
236 "required": ["name", "value", "source"]
237 },
238 "x-dre-null": true
239 })
240}
241
242impl JsonSchema for Code {
243 fn schema_name() -> std::borrow::Cow<'static, str> {
244 "Code".into()
245 }
246 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
247 schemars::json_schema!({"type": "string", "description": "A code from the error codes reference, e.g. `query-failed`."})
248 }
249 fn inline_schema() -> bool {
250 true
251 }
252}
253
254impl JsonSchema for ErrorCode {
255 fn schema_name() -> std::borrow::Cow<'static, str> {
256 "ErrorCode".into()
257 }
258 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
259 schemars::json_schema!({"type": "string", "description": "A code from the error codes reference, e.g. `query-failed`, or a plugin's own, namespaced by the plugin, e.g. `sftp/host-key-mismatch`."})
260 }
261 fn inline_schema() -> bool {
262 true
263 }
264}
265
266impl JsonSchema for Kind {
267 fn schema_name() -> std::borrow::Cow<'static, str> {
268 "Kind".into()
269 }
270 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
271 schemars::json_schema!({"enum": ["usage", "config", "plugin", "refused", "connection", "auth", "query", "delivery", "internal", "cancelled", "timed_out"]})
272 }
273 fn inline_schema() -> bool {
274 true
275 }
276}