Skip to content

Commit

Permalink
Add CLI command to generate an openapi schema
Browse files Browse the repository at this point in the history
  • Loading branch information
spencewenski committed Apr 7, 2024
1 parent 3e35f41 commit 257e915
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 2 deletions.
16 changes: 14 additions & 2 deletions src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ use async_trait::async_trait;
use clap::{Parser, Subcommand};

use crate::app_context::AppContext;
#[cfg(feature = "open-api")]
use crate::cli::list_routes::ListRoutesArgs;
#[cfg(feature = "open-api")]
use crate::cli::open_api_schema::OpenApiArgs;
use crate::config::environment::Environment;

#[cfg(feature = "open-api")]
pub mod list_routes;
#[cfg(feature = "open-api")]
pub mod open_api_schema;

/// Implement to enable Roadster to run your custom CLI commands.
#[async_trait]
Expand Down Expand Up @@ -107,17 +112,24 @@ impl RunRoadsterCommand for RoadsterArgs {

#[derive(Debug, Subcommand)]
pub enum RoadsterSubCommand {
/// List the API routes available in the app. Note: this command will only list routes that
/// were defined using the `Aide` crate.
/// List the API routes available in the app. Note: only the routes defined
/// using the `Aide` crate will be included in the output.
#[cfg(feature = "open-api")]
ListRoutes(ListRoutesArgs),
/// Generate an OpenAPI 3.1 schema for the app's API routes. Note: only the routes defined
/// using the `Aide` crate will be included in the schema.
#[cfg(feature = "open-api")]
OpenApi(OpenApiArgs),
}

#[async_trait]
impl RunRoadsterCommand for RoadsterSubCommand {
async fn run(&self, cli: &RoadsterCli, context: &AppContext) -> anyhow::Result<bool> {
match self {
#[cfg(feature = "open-api")]
RoadsterSubCommand::ListRoutes(args) => args.run(cli, context).await,
#[cfg(feature = "open-api")]
RoadsterSubCommand::OpenApi(args) => args.run(cli, context).await,
}
}
}
40 changes: 40 additions & 0 deletions src/cli/open_api_schema.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

use async_trait::async_trait;
use clap::Parser;
use tracing::info;

use crate::app_context::AppContext;
use crate::cli::{RoadsterCli, RunRoadsterCommand};

#[derive(Debug, Parser)]
pub struct OpenApiArgs {
/// The file to write the schema to. If not provided, will write to stdout.
#[clap(short, long, value_name = "FILE", value_hint = clap::ValueHint::FilePath)]
pub output: Option<PathBuf>,
/// Whether to pretty-print the schema. Default: false.
#[clap(short, long, default_value_t = false)]
pub pretty_print: bool,
}

#[async_trait]
impl RunRoadsterCommand for OpenApiArgs {
async fn run(&self, _cli: &RoadsterCli, context: &AppContext) -> anyhow::Result<bool> {
let schema_json = if self.pretty_print {
serde_json::to_string_pretty(context.api.as_ref())?
} else {
serde_json::to_string(context.api.as_ref())?
};
if let Some(path) = &self.output {
info!("Writing schema to {:?}", path);
write!(File::create(path)?, "{schema_json}")?;
} else {
info!("OpenAPI schema:");
info!("{schema_json}");
};

Ok(true)
}
}

0 comments on commit 257e915

Please sign in to comment.