Skip to main content

httpgenerator_cli/execution/
orchestrator.rs

1use std::path::PathBuf;
2
3use httpgenerator_core::{generate_http_files, openapi::load_and_normalize_document_with_options};
4
5use crate::{
6    CliError,
7    args::CliArgs,
8    auth::try_get_access_token,
9    observer::{ExecutionObserver, ExecutionSummary, NoopExecutionObserver},
10    writer::write_files,
11};
12
13use super::{
14    authorization::resolve_authorization_header, settings::build_generator_settings,
15    validation::validate_openapi_document,
16};
17
18pub fn execute(args: CliArgs) -> Result<ExecutionSummary, CliError> {
19    let mut observer = NoopExecutionObserver;
20    execute_with(args, &mut observer, try_get_access_token)
21}
22
23pub fn execute_with_observer<O>(
24    args: CliArgs,
25    observer: &mut O,
26) -> Result<ExecutionSummary, CliError>
27where
28    O: ExecutionObserver,
29{
30    execute_with(args, observer, try_get_access_token)
31}
32
33pub fn should_attempt_azure_auth(args: &CliArgs) -> bool {
34    if args
35        .authorization_header
36        .as_deref()
37        .map(str::trim)
38        .is_some_and(|header| !header.is_empty())
39    {
40        return false;
41    }
42
43    args.azure_scope
44        .as_deref()
45        .map(str::trim)
46        .is_some_and(|scope| !scope.is_empty())
47        || args
48            .azure_tenant_id
49            .as_deref()
50            .map(str::trim)
51            .is_some_and(|tenant_id| !tenant_id.is_empty())
52}
53
54pub(crate) fn execute_with<F, O>(
55    args: CliArgs,
56    observer: &mut O,
57    acquire_token: F,
58) -> Result<ExecutionSummary, CliError>
59where
60    F: Fn(Option<&str>, &str) -> Result<Option<String>, String>,
61    O: ExecutionObserver,
62{
63    let open_api_path = args.open_api_path.clone().ok_or(CliError::MissingInput)?;
64    if !args.skip_validation {
65        observer.validation_started();
66    }
67
68    let validation = validate_openapi_document(&open_api_path, args.skip_validation)?;
69    if let Some(inspection) = &validation {
70        observer.validation_succeeded(inspection);
71    }
72
73    let should_attempt_azure_auth = should_attempt_azure_auth(&args);
74    if should_attempt_azure_auth {
75        observer.azure_auth_started();
76    }
77
78    let (authorization_header, azure_auth) = resolve_authorization_header(&args, acquire_token);
79    if should_attempt_azure_auth {
80        observer.azure_auth_finished(&azure_auth);
81    }
82
83    let document = load_and_normalize_document_with_options(&open_api_path, args.skip_validation)
84        .map_err(|error| CliError::LoadOpenApi(error.to_string()))?;
85    let settings = build_generator_settings(&args, open_api_path.clone(), authorization_header);
86    let result = generate_http_files(&settings, &document);
87    observer.file_writing_started(result.files.len());
88    let output_folder = PathBuf::from(&args.output_folder);
89    let files = write_files(&output_folder, result.files, args.timeout)?;
90    observer.files_written(&files);
91
92    Ok(ExecutionSummary {
93        output_folder,
94        files,
95        validation,
96        azure_auth,
97    })
98}