dre_core/config/
project.rs1use schemars::JsonSchema;
9use serde::Deserialize;
10use serde::de::IgnoredAny;
11
12use super::de::{Located, Loose, Map, UnknownKeys};
13use crate::dates::{WeekNumbering, WeekStart};
14
15type JsonMap = serde_json::Map<String, serde_json::Value>;
16pub type FormatOptions = Located<Loose<Option<Map<Loose<JsonMap>>>>>;
18pub type DispatchList = Located<Loose<Vec<Loose<Dispatch>>>>;
20
21#[derive(Deserialize, JsonSchema)]
23#[schemars(title = "DRE project", deny_unknown_fields)]
24pub struct ProjectFile {
25 #[schemars(required, length(min = 1))]
27 pub name: Option<Located<Loose<String>>>,
28 pub default_profile: Option<Located<Loose<String>>>,
30 #[schemars(schema_with = "output_ref")]
32 #[serde(default)]
33 pub default_output: Option<IgnoredAny>,
34 #[schemars(schema_with = "format_options")]
36 #[serde(default)]
37 pub format_options: Option<FormatOptions>,
38 pub default_set: Option<Located<Loose<String>>>,
40 #[schemars(schema_with = "any_map")]
42 #[serde(default)]
43 pub vars: Option<Located<Loose<Option<JsonMap>>>>,
44 #[schemars(range(min = 1), extend("default" = 10000))]
46 pub run_query_max_rows: Option<Located<Loose<u64>>>,
47 #[schemars(range(min = 0), extend("default" = 200))]
49 pub lookup_inline_max_rows: Option<Located<Loose<u64>>>,
50 pub dispatch: Option<DispatchList>,
52 #[schemars(extend("default" = true))]
54 pub mask_secrets: Option<Located<Loose<bool>>>,
55 pub timezone: Option<Located<Loose<String>>>,
57 pub locale: Option<Located<Loose<String>>>,
59 #[schemars(extend("default" = "monday"))]
61 pub week_start: Option<Located<Loose<WeekStart>>>,
62 #[schemars(extend("default" = "iso"))]
64 pub week_numbering: Option<Located<Loose<WeekNumbering>>>,
65 pub reports: Option<Located<Loose<Folder>>>,
67 pub flags: Option<Located<Loose<Flags>>>,
69 pub target_path: Option<Located<Loose<String>>>,
71 #[schemars(schema_with = "super::dependencies::plugins")]
73 #[serde(default)]
74 pub plugins: Option<IgnoredAny>,
75 #[schemars(schema_with = "sources_ref")]
77 #[serde(default)]
78 pub sources: Option<IgnoredAny>,
79 #[schemars(skip)]
81 pub target: Option<Located<IgnoredAny>>,
82 #[schemars(skip)]
84 pub destinations: Option<Located<IgnoredAny>>,
85 #[schemars(skip)]
86 pub formats: Option<Located<IgnoredAny>>,
87 #[serde(rename = "$unknown", default)]
88 #[schemars(skip)]
89 pub unknown: UnknownKeys,
90}
91
92#[derive(Deserialize, JsonSchema)]
94#[schemars(deny_unknown_fields)]
95pub struct Flags {
96 #[schemars(range(min = 1), extend("default" = 60))]
98 pub http_timeout: Option<Located<Loose<u64>>>,
99 #[schemars(range(min = 1), extend("default" = 1))]
101 pub keep_runs: Option<Located<Loose<u64>>>,
102 #[schemars(schema_with = "duration")]
104 #[serde(default)]
105 pub run_timeout: Option<Located<Loose<serde_json::Value>>>,
106 #[serde(rename = "$unknown", default)]
107 #[schemars(skip)]
108 pub unknown: UnknownKeys,
109}
110
111#[derive(Deserialize, JsonSchema)]
113#[schemars(deny_unknown_fields, inline)]
114pub struct Dispatch {
115 #[schemars(required)]
117 pub macro_namespace: Option<Loose<String>>,
118 #[schemars(required, length(min = 1))]
120 pub search_order: Option<Loose<Vec<Loose<String>>>>,
121}
122
123#[derive(Deserialize, JsonSchema)]
125#[schemars(rename = "folder", extend("additionalProperties" = {"$ref": "#/$defs/folder"}))]
126pub struct Folder {
127 #[serde(rename = "+tags")]
129 pub tags: Option<Located<Loose<Vec<String>>>>,
130 #[serde(rename = "+output")]
132 #[serde(default)]
133 #[schemars(schema_with = "output_ref")]
134 pub output: Option<Located<Loose<JsonMap>>>,
135 #[serde(rename = "+profile")]
137 pub profile: Option<Located<Loose<String>>>,
138 #[serde(rename = "+schedule")]
140 #[schemars(skip)]
141 pub schedule: Option<Located<IgnoredAny>>,
142 #[serde(rename = "+vars")]
144 #[serde(default)]
145 #[schemars(schema_with = "any_map")]
146 pub vars: Option<Located<Loose<JsonMap>>>,
147 #[serde(rename = "+timezone")]
149 pub timezone: Option<Located<Loose<String>>>,
150 #[serde(rename = "+locale")]
152 pub locale: Option<Located<Loose<String>>>,
153 #[serde(rename = "$unknown", default)]
155 #[schemars(skip)]
156 pub rest: Map<Located<Loose<Folder>>>,
157}
158
159impl Folder {
160 pub fn sets_anything(&self) -> bool {
163 self.tags.is_some()
164 || self.output.is_some()
165 || self.profile.is_some()
166 || self.schedule.is_some()
167 || self.vars.is_some()
168 || self.timezone.is_some()
169 || self.locale.is_some()
170 || self.rest.iter().any(|(k, _)| k.value.starts_with('+'))
171 }
172}
173
174fn output_ref(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
175 schemars::json_schema!({"$ref": "report.schema.json#/$defs/output"})
176}
177
178pub(super) fn sources_ref(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
179 schemars::json_schema!({"$ref": "sources.schema.json#/properties/sources"})
180}
181
182fn duration(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
183 schemars::json_schema!({
184 "oneOf": [
185 {"type": "string", "pattern": "^\\s*[0-9]+(\\.[0-9]+)?\\s*(ms|s|m|h)?\\s*$"},
186 {"type": "number", "minimum": 0}
187 ]
188 })
189}
190
191fn any_map(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
192 schemars::json_schema!({"type": "object", "additionalProperties": true})
193}
194
195fn format_options(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
196 schemars::json_schema!({"type": "object", "additionalProperties": {"type": "object"}})
197}