aide

repository·main·Indexed 20 days ago

https://github.com/tamasfe/aide

A code-first API documentation library for Rust designed to automate the generation of OpenAPI 3.1.x specifications from source code. It leverages schemars for schema generation and provides traits like OperationInput and OperationOutput to document HTTP parameters and responses. Aide includes integration for Axum and provides tools for customizing documentation via the WithApi wrapper and ApiOverride trait.

Tokens
11.8K
Snippets
40
Records
50
Agent score
71%

What's inside aide

  1. Overview of Aide

    main
    Aide is a code-first API documentation and utility library for Rust. It is designed to help developers generate documentation (such as OpenAPI specifications) directly from their Rust code, reducing the need for manual documentation maintenance.
  2. Explore the Aide ecosystem

    main

    Aide has a growing ecosystem of community-maintained projects, including:

    • aide-axum-typed-multipart-2: A wrapper around axum_typed_multipart that enables documentation generation for multipart requests.
    • rovo: A tool for doc-comment-driven OpenAPI documentation generation specifically for Axum web applications, built on top of Aide.
  3. Configure documentation generation settings via thread-local context

    main

    Aide uses a thread-local GenContext to manage settings for API documentation generation. Most configuration is performed using top-level functions that modify this context for the current thread. This allows you to set global behaviors (like error handling or schema extraction) without passing a context object through every function call in your application.

    // Example of configuring the context
    // These settings apply to the current thread
    
    aide::extract_schemas(true);
    aide::inferred_empty_response_status(204);
    aide::strip_query_null_types(true);
  4. How Aide generates OpenAPI documentation

    main

    aide is a code-first OpenAPI 3.1.x documentation generator. It uses a combination of type-based generation and declarative transformations to minimize manual documentation effort.

    Type-based Generation

    aide leverages the schemars crate for schema generation. For JSON-based APIs, you simply need to implement schemars::JsonSchema alongside serde's Serialize and Deserialize traits on your types.

    Automatic Parameter and Response Documentation

    aide uses the OperationInput and OperationOutput traits to automatically document HTTP parameters and responses. For example, if you use an axum::Json<T> extractor, aide will automatically generate an application/json request body documentation using the schema of T, provided T implements JsonSchema.

    Declarative Documentation

    Manual documentation is handled through composable transform functions and a builder-pattern API, allowing you to augment the automatically generated schema with specific details.

  5. Customize API documentation using `WithApi` and `ApiOverride`

    main

    Aide allows you to customize how types are documented in your OpenAPI specification using the WithApi<T> wrapper. This is useful for two scenarios:

    1. Overriding documentation for existing types: If a type already implements OperationInput or OperationOutput, you can use WithApi with a custom ApiOverride implementation to provide different documentation metadata.
    2. Adding documentation to types that don't support it: You can wrap types that do not natively implement OperationInput or OperationOutput to make them compatible with Aide's documentation generation.

    Implementation Approaches

    1. Simple Type Override

    Use this when you want to override the documentation for a specific concrete type.

    use aide::{ApiOverride, OperationInput, WithApi};
    
    #[derive(Eq, PartialEq, Debug)] 
    struct SomeType;
    
    #[derive(Debug)]
    struct MyApiOverride;
    
    impl ApiOverride for MyApiOverride {
        type Target = SomeType;
    }
    
    // Implement OperationInput (or OperationOutput) on the override type to define custom docs
    impl OperationInput for MyApiOverride {
        // override stuff here
    }
    
    // Use WithApi in your handler
    async fn my_handler(WithApi(ty, ..): WithApi<MyApiOverride>) -> bool {
        assert_eq!(ty, SomeType);
        true
    }

    2. Generic Type Override

    Use this when you want to apply documentation logic to a generic wrapper (e.g., a custom XML or JSON wrapper) across multiple target types.

    use std::marker::PhantomData;
    use aide::{ApiOverride, OperationInput, WithApi};
    
    #[derive(Eq, PartialEq, Debug)] 
    struct SomeType;
    
    #[derive(Eq, PartialEq, Debug)] 
    struct CustomXML<T>(T);
    
    #[derive(Debug)]
    struct MyCustomXML<T>(PhantomData<T>);
    
    impl<T> ApiOverride for MyCustomXML<T> {
        type Target = CustomXML<T>;
    }
    
    impl<T> OperationInput for MyCustomXML<T> {
        // override stuff with access to T
    }
    
    async fn my_handler(WithApi(ty, ..): WithApi<MyCustomXML<SomeType>>) -> bool {
        assert_eq!(ty, CustomXML(SomeType));
        true
    }
    use aide::{ApiOverride, OperationInput, WithApi};
    
    #[derive(Eq, PartialEq, Debug)] 
    struct SomeType;
    
    #[derive(Debug)]
    struct MyApiOverride;
    
    impl ApiOverride for MyApiOverride {
        type Target = SomeType;
    }
    
    impl OperationInput for MyApiOverride {
        // override stuff
    }
    
    async fn my_handler(WithApi(ty, ..): WithApi<MyApiOverride>) -> bool {
        assert_eq!(ty, SomeType);
        true
    }
  6. Handle documentation generation errors

    main

    During the OpenAPI generation process, some errors may occur. By default, aide takes no action on these errors (they are swallowed), which might indicate bugs in the documentation logic.

    To handle these errors, you can register an error handler in the thread-local context using aide::generate::on_error.

    Warning: It is not advised to simply panic on all errors, especially in production environments, as aide may produce false positives when contextual information is insufficient.

  7. Configure Aide feature flags

    main

    aide has no features enabled by default. You must enable specific features depending on your requirements.

    Core Features

    • macros: Enables additional helper macros, including the OperationIo derive macro.

    Axum Integration

    If using axum, you can enable specific feature gates for various extractors and types:

    • axum (base integration)
    • axum-form
    • axum-json
    • axum-matched-path
    • axum-multipart
    • axum-original-uri
    • axum-query
    • axum-tokio (for ConnectInfo)
    • axum-ws (WebSockets)

    Axum-extra Integration

    • axum-extra
    • axum-extra-cookie
    • axum-extra-cookie-private
    • axum-extra-form
    • axum-extra-headers
    • axum-extra-query
    • axum-extra-json-deserializer

    UI Documentation Providers

    • swagger
    • redoc
    • scalar
  8. Use `OperationIo` derive macro for boilerplate reduction

    main

    The OperationIo derive macro (provided by aide_macros) simplifies implementing OperationInput and OperationOutput. You can use attributes to customize which parts of the trait are implemented:

    • #[aide(input)]: Implements OperationInput.
    • #[aide(output)]: Implements OperationOutput.
    • #[aide(input, output)]: Implements both.
    • #[aide(input_with = "Type", output_with = "Type")]: Uses specific types for the input/output logic.
    • #[aide(json_schema)]: Adds JsonSchema bounds to the implementation.
    #[derive(OperationIo)]
    #[aide(input, output)]
    struct MyDataWrapper(String);
  9. Strip null types from query parameters with strip_query_null_types

    main

    When enabled, null types are automatically removed from query parameter schemas during finalization. This is useful because query strings cannot express null values (a parameter is either present or absent). This is enabled by default.

    // Disable automatic stripping of null types
    aide::strip_query_null_types(false);
  10. Toggle error response visibility with all_error_responses

    main

    Controls whether all theoretically possible error responses (including framework-specific ones) are output. This is disabled by default.

    // Enable outputting all possible error responses
    aide::all_error_responses(true);