Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export OpenAPI spec at build time #214

Closed
peteole opened this issue Jul 9, 2022 · 5 comments
Closed

Export OpenAPI spec at build time #214

peteole opened this issue Jul 9, 2022 · 5 comments

Comments

@peteole
Copy link

peteole commented Jul 9, 2022

Hi,

is there a simple way to export the generated OpenAPI spec to a file at compile time instead of serving it at runtime? This would fit my use case much better:)

And pretty cool crate btw!

@juhaku
Copy link
Owner

juhaku commented Jul 9, 2022

Hello,

Thanks, :)

There is no build in way to handle this but implementing something like this per user basis is not a big of a deal. I don't think build in implementaiton for this would be practical or at least I am not sure how it could be implemented so that the behaviour would be generic across the users. But of course ideas and PRs are always welcome. :)

I would implement it roughly something like this to get this behaviour.

# in Cargo.toml add custom bin target to generate the spec from the types
[[bin]]
name = "gen-openapi"
path = "./src/gen_openapi.rs"

Then in the in the Rust code something like this. Or perhaps you can call the code in your main app to generate the OpenAPI doc. and then write it to the file. You could easily share code between your app and binary which would generate the write the code to a file.

// in ./src/gen_openapi.rs
fn main() {
    let doc = gen_my_openapi();
    fs::write("./path/to/file", doc);
}

// in /src/openapi.rs 
fn gen_my_openapi() -> String {
  #[derive(Deserialize, ToSchema)]
  struct Person {
      /// Id of person
      id: i64,
      /// Name of person
      name: String,
  }

  #[derive(OpenApi)]
  #[openapi(schemas(components(Person)))]
  struct ApiDoc;

  ApiDoc::openapi().to_pretty_json().unwrap()
}

Then you can call the code from your terminal session with.

 cargo run --bin gen-openapi

While this is en extra step. But I concur it is better to have it as manual step than automatically write to the file when values for macros are changed. And if that was the approach then the runtime modifiers could not be used. This step could also be used together with cargo watch if necessary and needed with automatic document updates.

Aternatively if it is seen better that the API doc is dumped to a file everytime you build your application one could leverage usage of build.rs. The similar generation and file writing could be done within the build.rs file what is executed everytime the application is built.

@peteole
Copy link
Author

peteole commented Jul 10, 2022

Thanks, this solved my issue! I am a bit new to rust so it will take a while and not be perfect from the beginning, but would you mind me creating a pull request for documenting this once I get it done? I am currently going one step further and generate clients from the OpenAPI-Spec in the build step:
https://github.com/peteole/notifier/blob/master/src/generate_openapi.rs
Once this works properly I could also add this as a "bonus recipe".

@juhaku
Copy link
Owner

juhaku commented Jul 10, 2022

Great, not at all. Just need to find a right place for this thing. Perhaps it could be in a form of an example in examples folder. And then add a link to the Go beyond the surface section.

@juhaku
Copy link
Owner

juhaku commented Feb 15, 2023

Added note about this in the REAMDE.md

@juhaku juhaku closed this as completed Feb 15, 2023
@pkb-pmj
Copy link

pkb-pmj commented Aug 19, 2023

Aternatively if it is seen better that the API doc is dumped to a file everytime you build your application one could leverage usage of build.rs. The similar generation and file writing could be done within the build.rs file what is executed everytime the application is built.

I wish that would work.
I have all the macro annotations inside the application code. Now funny things happen if I want to execute cargo run --bin gen-openapi inside build.rs: gen-openapi depends on the application code too, so it first has to build the application, which runs build.rs again, and you end up with infinite recursion. And Cargo doesn't provide a way to not run the build script for gen-openapi, which would have been an acceptable workaround.

Since the OpenAPI spec only actually exists at runtime, I unfortunately don't think it would be possible to export it at build time, without some major changes to the fundamental way this crate works.
That's an important distinction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants