Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ From this repository's root (e.g., after cloning), try the included bookstore ex
```console
$ oapi-codegen --config-file examples/bookstore/oapi-codegen-server.yaml examples/bookstore/openapi.yaml
✓ wrote generated/restapi.rs
note: add the crates the generated code references to Cargo.toml:
serde = { version = "1.0.229", features = ["derive"] }
serde_json = "1.0.151"
http = "1.4.2"
axum = { version = "0.8.9", features = ["multipart"] }
axum-extra = { version = "0.12.6", features = ["query"] }
# or:
cargo add serde@1.0.229 --features derive
cargo add serde_json@1.0.151
cargo add http@1.4.2
cargo add axum@0.8.9 --features multipart
cargo add axum-extra@0.12.6 --features query

```

Expand Down
10 changes: 10 additions & 0 deletions crates/oapi-codegen/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,14 @@ pub struct Cli {
/// config sets `output:`.
#[arg(short = 'o', long)]
pub output_file: Option<PathBuf>,

/// After writing, run `cargo add` for each crate the generated code needs.
///
/// If set, this runs without prompting. If not set, and stdin is an
/// interactive terminal, you are asked first; otherwise the run only prints
/// the dependency list. `cargo add` targets the package whose `Cargo.toml`
/// is nearest the output and merges with any existing declaration, so a
/// crate already present is updated in place rather than duplicated.
#[arg(long)]
pub install_deps: bool,
}
53 changes: 53 additions & 0 deletions crates/oapi-codegen/src/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
use std::io::ErrorKind;
use std::path::Path;

use anstream::eprint;
use anstream::eprintln;
use oapi_codegen::Error;
use oapi_codegen::config::Generate;
use oapi_codegen::deps::Dependency;
use owo_colors::OwoColorize;

/// Example `generate:` block shown when a config enables no artifacts. Each
Expand Down Expand Up @@ -105,6 +107,57 @@ pub fn report_wrote(path: &Path) {
eprintln!("{} wrote {}", "✓".green().bold(), path.display());
}

/// After a successful write, list the external crates the generated code
/// references so the consumer can add them to `Cargo.toml` — Cargo does not
/// infer them from `use` paths the way `go mod tidy` does. Prints nothing when
/// the output references no external crates (e.g. `server-urls` only).
pub fn report_dependencies(deps: &[Dependency]) {
if deps.is_empty() {
return;
}
eprintln!(
" {} add the crates the generated code references to Cargo.toml:",
"note:".cyan().bold()
);
for dep in deps {
eprintln!(" {}", dep.toml().dimmed());
}
eprintln!(" {}", "# or:".dimmed());
for dep in deps {
eprintln!(" {}", dep.cargo_add().dimmed());
}
}

/// Ask whether to run the `cargo add` commands now. Returns `false` on EOF or a
/// non-affirmative answer. Only meaningful on an interactive terminal.
pub fn prompt_install_dependencies() -> bool {
use std::io::Write;
eprint!(" {} run these `cargo add` commands now? [y/N] ", "?".cyan().bold());
let _ = std::io::stderr().flush();
Comment thread
dotkas marked this conversation as resolved.
let mut answer = String::new();
if std::io::stdin().read_line(&mut answer).is_err() {
return false;
}
let answer = answer.trim().to_ascii_lowercase();
return answer == "y" || answer == "yes";
}

/// Report that a dependency is being added via `cargo add`.
pub fn report_installing(dep: &Dependency) {
eprintln!(" {} {}", "+".green().bold(), dep.cargo_add().dimmed());
}

/// Report that a `cargo add` invocation failed, without aborting — the output
/// file is already written, so a failed convenience step is a warning, not a
/// fatal error.
pub fn report_install_failed(dep: &Dependency, detail: &str) {
eprintln!(
" {} `{}` failed: {detail}",
"warning:".yellow().bold(),
dep.cargo_add()
);
}

/// Build the context-specific hints shown after an error message.
fn hints_for(err: &Error) -> Vec<String> {
match err {
Expand Down
Loading