headless_lms_server/programs/doc_file_generator/
mod.rs1#![allow(clippy::redundant_clone)]
108#![allow(unused_imports)]
109
110pub mod example;
111
112use chrono::{TimeZone, Utc};
113use example::Example;
114use headless_lms_models::{
115 course_background_question_answers::CourseBackgroundQuestionAnswer,
116 course_background_questions::{
117 CourseBackgroundQuestion, CourseBackgroundQuestionType, CourseBackgroundQuestionsAndAnswers,
118 },
119 course_instance_enrollments::CourseInstanceEnrollmentsInfo,
120 course_module_completions::{
121 CourseModuleCompletion, CourseModuleCompletionWithRegistrationInfo,
122 StudyRegistryCompletion, StudyRegistryGrade,
123 },
124 courses::CourseBreadcrumbInfo,
125 exercise_task_submissions::PeerOrSelfReviewsReceived,
126 exercises::ExerciseStatusSummaryForUser,
127 library::global_stats::{GlobalCourseModuleStatEntry, GlobalStatEntry},
128 page_audio_files::PageAudioFile,
129 page_visit_datum_summary_by_courses::PageVisitDatumSummaryByCourse,
130 page_visit_datum_summary_by_courses_countries::PageVisitDatumSummaryByCoursesCountries,
131 page_visit_datum_summary_by_courses_device_types::PageVisitDatumSummaryByCourseDeviceTypes,
132 page_visit_datum_summary_by_pages::PageVisitDatumSummaryByPages,
133 peer_or_self_review_configs::CourseMaterialPeerOrSelfReviewConfig,
134 peer_or_self_review_question_submissions::{
135 PeerOrSelfReviewAnswer, PeerOrSelfReviewQuestionAndAnswer,
136 PeerOrSelfReviewQuestionSubmission,
137 },
138 peer_or_self_review_submissions::PeerOrSelfReviewSubmission,
139 peer_review_queue_entries::PeerReviewQueueEntry,
140 proposed_block_edits::EditedBlockStillExistsData,
141 research_forms::{ResearchForm, ResearchFormQuestion, ResearchFormQuestionAnswer},
142 student_countries::StudentCountry,
143 teacher_grading_decisions::{TeacherDecisionType, TeacherGradingDecision},
144 user_details::UserDetail,
145 user_research_consents::UserResearchConsent,
146};
147use serde::Serialize;
148use serde_json::{Serializer, Value, json, ser::PrettyFormatter};
149use std::{collections::HashMap, fs};
150
151use uuid::Uuid;
152
153use crate::controllers::course_material::exercises::CourseMaterialPeerOrSelfReviewDataWithToken;
154
155fn ex<T: Example>() -> T {
157 Example::example()
158}
159
160#[macro_export]
161macro_rules! doc_path {
162 ($filename:expr_2021, $extension:expr_2021) => {{
163 let windows_safe_filename = $filename
164 .replace('<', "(")
165 .replace('>', ")")
166 .replace(" ", "");
167
168 let mut s = String::new();
169 s.push_str(env!("CARGO_MANIFEST_DIR"));
170 s.push_str("/generated-docs/");
171 s.push_str(windows_safe_filename.as_str());
172 s.push_str($extension);
173 s
174 }};
175}
176
177#[macro_export]
180macro_rules! doc {
181 (T, Option, Vec, $($t:tt)*) => {
182 ::doc_macro::example!($($t)*);
183 doc!(@inner T, $($t)*);
184 doc!(@inner Option, $($t)*);
185 doc!(@inner Vec, $($t)*);
186 };
187 (Option, Vec, $($t:tt)*) => {
188 ::doc_macro::example!($($t)*);
189 doc!(@inner Option, $($t)*);
190 doc!(@inner Vec, $($t)*);
191 };
192 (T, Option, $($t:tt)*) => {
193 ::doc_macro::example!($($t)*);
194 doc!(@inner T, $($t)*);
195 doc!(@inner Option, $($t)*);
196 };
197 (T, Vec, $($t:tt)*) => {
198 ::doc_macro::example!($($t)*);
199 doc!(@inner T, $($t)*);
200 doc!(@inner Vec, $($t)*);
201 };
202 (T, $($t:tt)*) => {
203 ::doc_macro::example!($($t)*);
204 doc!(@inner T, $($t)*);
205 };
206 (Option, $($t:tt)*) => {
207 ::doc_macro::example!($($t)*);
208 doc!(@inner Option, $($t)*);
209 };
210 (Vec, $($t:tt)*) => {
211 ::doc_macro::example!($($t)*);
212 doc!(@inner Vec, $($t)*);
213 };
214 (@inner T, $i:ident :: $($t:tt)*) => {
216 doc!($i, Example::example());
217 };
218 (@inner Option, $i:ident :: $($t:tt)*) => {
219 doc!(Option<$i>, Example::example());
220 };
221 (@inner Vec, $i:ident :: $($t:tt)*) => {
222 doc!(Vec<$i>, Example::example());
223 };
224 (@inner T, $i:ident $($t:tt)*) => {
226 doc!($i, Example::example());
227 };
228 (@inner Option, $i:ident $($t:tt)*) => {
229 doc!(Option<$i>, Example::example());
230 };
231 (@inner Vec, $i:ident $($t:tt)*) => {
232 doc!(Vec<$i>, Example::example());
233 };
234 ($t:ty, $e:expr_2021) => {{
236 let expr: $t = $e;
237
238 let json_path = $crate::doc_path!(
239 stringify!($t),
240 ".json"
241 );
242 $crate::programs::doc_file_generator::write_json(&json_path, expr);
243 }};
244 ($($t:tt)*) => {
246 doc!(T, $($t)*);
247 };
248}
249
250pub async fn main() -> anyhow::Result<()> {
251 fs::read_dir(concat!(env!("CARGO_MANIFEST_DIR"), "/generated-docs/"))
253 .map_err(|e| anyhow::anyhow!("Failed to read generated-docs directory: {}", e))?
254 .filter_map(|file| {
255 file.ok().filter(|f| {
256 f.file_name()
257 .to_str()
258 .is_some_and(|n| n.ends_with(".json") || n.ends_with(".ts"))
259 })
260 })
261 .try_for_each(|f| -> anyhow::Result<()> {
262 fs::remove_file(f.path())
263 .map_err(|e| anyhow::anyhow!("Failed to remove file {:?}: {}", f.path(), e))?;
264 Ok(())
265 })?;
266
267 controllers();
269
270 external();
271
272 doc!((), ex());
273 doc!(i64, 123);
274 doc!(bool, ex());
275 doc!(
276 Vec<bool>,
277 vec![false, true, false, true, false, true, true, true]
278 );
279 doc!(String, ex());
280 doc!(Uuid, ex());
281 doc!(Vec<Uuid>, ex());
282
283 Ok(())
284}
285
286pub fn write_json<T: Serialize>(path: &str, value: T) {
287 let mut file =
288 std::fs::File::create(path).expect("Failed to create file for JSON serialization");
289 let formatter = PrettyFormatter::with_indent(b" ");
290 let mut serializer = Serializer::with_formatter(&mut file, formatter);
291 serde::Serialize::serialize(&value, &mut serializer)
292 .expect("Failed to serialize value to JSON");
293}
294
295#[allow(non_local_definitions)]
296fn controllers() {
297 doc!(
298 T,
299 Vec,
300 StudyRegistryCompletion {
301 completion_date: Utc.with_ymd_and_hms(2022, 6, 21, 0, 0, 0).unwrap(),
302 completion_language: "en-US".to_string(),
303 completion_registration_attempt_date: None,
304 email: "student@example.com".to_string(),
305 grade: StudyRegistryGrade::new(true, Some(4)),
306 id: Uuid::parse_str("633852ce-c82a-4d60-8ab5-28745163f6f9")
307 .expect("Invalid UUID constant in doc generator"),
308 user_id,
309 tier: None
310 }
311 );
312}
313
314fn external() {}