use gotcha::{api, openapi::generate_openapi, Json, Schematic};
use serde::{Deserialize, Serialize};
#[derive(Schematic, Serialize, Deserialize)]
struct Node {
name: String,
children: Vec<Node>,
}
#[derive(Schematic, Serialize, Deserialize)]
struct User {
id: u32,
}
#[derive(Schematic, Serialize, Deserialize)]
#[serde(tag = "kind")]
enum Expr {
Literal { value: i32 },
Sum { operands: Vec<Expr> },
}
#[api(id = "eval_expr")]
async fn eval_expr() -> Json<Expr> {
unimplemented!()
}
#[api(id = "get_tree")]
async fn get_tree() -> Json<Node> {
unimplemented!()
}
#[api(id = "get_user")]
async fn get_user() -> Json<User> {
unimplemented!()
}
#[api(id = "list_users")]
async fn list_users() -> Json<User> {
unimplemented!()
}
fn operable<H, T>(_handler: H) -> &'static gotcha::openapi::Operable
where
H: gotcha::axum::handler::Handler<T, ()>,
T: 'static,
{
gotcha::router::extract_operable::<H, T, ()>().expect("handler is registered")
}
fn main() {
use gotcha::axum::http::Method;
let mut operables = std::collections::HashMap::new();
operables.insert(("/tree".to_string(), Method::GET), operable(get_tree));
operables.insert(("/users/{id}".to_string(), Method::GET), operable(get_user));
operables.insert(("/users".to_string(), Method::GET), operable(list_users));
operables.insert(("/eval".to_string(), Method::GET), operable(eval_expr));
let spec = generate_openapi(operables);
let json = serde_json::to_value(&spec).unwrap();
let schemas = &json["components"]["schemas"];
assert!(schemas.get("Node").is_some(), "Node is a component: {schemas}");
assert!(schemas.get("User").is_some(), "User is a component: {schemas}");
let children = &schemas["Node"]["properties"]["children"];
assert_eq!(children["items"]["$ref"], "#/components/schemas/Node", "recursive field refs itself: {children}");
let body_ref = |path: &str| json["paths"][path]["get"]["requestBody"].clone();
let _ = body_ref; let user_response = |path: &str| json["paths"][path]["get"]["responses"]["200"]["content"]["application/json"]["schema"].clone();
assert_eq!(user_response("/users/{id}")["$ref"], "#/components/schemas/User");
assert_eq!(user_response("/users")["$ref"], "#/components/schemas/User");
assert!(schemas.get("Expr").is_some(), "enums are components too: {schemas}");
let expr = serde_json::to_string(&schemas["Expr"]).unwrap();
assert!(expr.contains("#/components/schemas/Expr"), "recursive enum refs itself: {expr}");
assert!(schemas.get("string").is_none(), "primitives stay inline: {schemas}");
assert!(schemas.get("u32").is_none(), "primitives stay inline: {schemas}");
}