stonehm 0.1.2

Automatic OpenAPI 3.0 generation for Axum applications
Documentation

Stonehm - Automatic OpenAPI 3.0 Generation for Axum

Stonehm is a Rust crate that automatically generates OpenAPI 3.0 specifications for Axum web applications by analyzing handler functions and their documentation.

Features

  • Automatic OpenAPI generation: Extract documentation from function comments
  • Schema generation: Automatically generate JSON schemas for request/response types
  • Zero runtime overhead: All processing happens at compile time
  • Axum integration: Drop-in replacement for axum::Router
  • Documentation-driven: Uses standard Rust doc comments

Quick Start

Add stonehm to your Cargo.toml:

[dependencies]
stonehm = "0.1"
axum = "0.7"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

Basic Usage

use axum::Json;
use serde::{Deserialize, Serialize};
use stonehm::{api_router, api_handler, StoneSchema};

#[derive(Serialize, StoneSchema)]
struct HelloResponse {
    message: String,
}

#[derive(Deserialize, StoneSchema)]
struct GreetRequest {
    name: String,
}

#[derive(Serialize, StoneSchema)]
struct GreetResponse {
    greeting: String,
}

/// Returns a simple hello world message
///
/// This endpoint doesn't require any parameters and always returns
/// the same friendly greeting message.
///
/// # Responses
/// - 200: Successfully returned hello message
#[api_handler]
async fn hello() -> Json<HelloResponse> {
    Json(HelloResponse {
        message: "Hello, World!".to_string(),
    })
}

/// Creates a personalized greeting
///
/// Takes a name in the request body and returns a personalized
/// greeting message.
///
/// # Request Body
/// Content-Type: application/json
/// The request body should contain a JSON object with a name field.
///
/// # Responses
/// - 200: Successfully created personalized greeting
/// - 400: Invalid request body
#[api_handler]
async fn greet(Json(payload): Json<GreetRequest>) -> Json<GreetResponse> {
    Json(GreetResponse {
        greeting: format!("Hello, {}!", payload.name),
    })
}

// Note: This example shows the API structure but doesn't compile
// due to missing tokio dependency in doctests
fn main() {
    let app = api_router!("My API", "1.0.0")
        .get("/", hello)
        .post("/greet", greet)
        .with_openapi_routes()  // Adds /openapi.json and /openapi.yaml
        .into_router();
}

Documentation Format

Stonehm extracts documentation from standard Rust doc comments using these sections:

Parameters

Document path, query, and header parameters:

use stonehm::{api_handler, StoneSchema};
use axum::Json;
use serde::Serialize;

#[derive(Serialize, StoneSchema)]
struct User { id: u32 }

/// Get user by ID
///
/// # Parameters
/// - id (path): The user's unique identifier
/// - include_posts (query): Whether to include user's posts
/// - authorization (header): Bearer token for authentication
#[api_handler]
async fn get_user() -> Json<User> {
    Json(User { id: 1 })
}

Request Body

Document the expected request body:

use stonehm::{api_handler, StoneSchema};
use axum::Json;
use serde::{Serialize, Deserialize};

#[derive(Deserialize, StoneSchema)]
struct CreateUserRequest { name: String }

#[derive(Serialize, StoneSchema)]
struct User { id: u32 }

/// Create a new user
///
/// # Request Body
/// Content-Type: application/json
/// User information including name, email, and optional preferences.
#[api_handler]
async fn create_user(Json(user): Json<CreateUserRequest>) -> Json<User> {
    Json(User { id: 1 })
}

Responses

Document possible response status codes:

use stonehm::{api_handler, StoneSchema};
use axum::Json;
use serde::Serialize;

#[derive(Serialize, StoneSchema)]
struct User { id: u32 }

/// Update user information
///
/// # Responses
/// - 200: User successfully updated
/// - 400: Invalid user data provided
/// - 404: User not found
/// - 500: Internal server error
#[api_handler]
async fn update_user() -> Json<User> {
    Json(User { id: 1 })
}

Schema Generation

Use the StoneSchema derive macro on your request/response types:

use serde::Serialize;
use stonehm::StoneSchema;

#[derive(Serialize, StoneSchema)]
struct User {
    id: u32,
    name: String,
    email: String,
    active: bool,
}

This automatically generates JSON Schema definitions that are included in the OpenAPI specification.