use oas::{
builders, Referenceable, PathItem, Tag, Server, Components, Schema, Parameter,
ParameterIn, Response, MediaType, SecurityScheme, SecurityType,
SecurityRequirement, Info, Contact, License, ExternalDocumentation
};
use std::collections::BTreeMap;
fn main() {
let api = create_comprehensive_api();
println!("{}", serde_json::to_string_pretty(&api).unwrap());
demonstrate_referenceable_types();
demonstrate_schema_creation();
}
fn create_comprehensive_api() -> oas::OpenAPIV3 {
let mut schemas = BTreeMap::new();
let mut user_properties = BTreeMap::new();
user_properties.insert("properties".to_string(), serde_json::json!({
"id": {
"type": "integer",
"format": "int64",
"description": "Unique identifier for the user"
},
"username": {
"type": "string",
"description": "Username for login"
},
"email": {
"type": "string",
"format": "email",
"description": "User's email address"
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "User creation timestamp"
}
}));
user_properties.insert("required".to_string(), serde_json::json!(["id", "username", "email"]));
let user_schema = Schema {
_type: Some("object".to_string()),
description: Some("A user in the system".to_string()),
extras: user_properties,
format: None,
nullable: None,
};
schemas.insert("User".to_string(), Referenceable::data(user_schema));
let mut error_properties = BTreeMap::new();
error_properties.insert("properties".to_string(), serde_json::json!({
"code": {
"type": "integer",
"description": "Error code"
},
"message": {
"type": "string",
"description": "Error message"
}
}));
error_properties.insert("required".to_string(), serde_json::json!(["code", "message"]));
let error_schema = Schema {
_type: Some("object".to_string()),
description: Some("Error response".to_string()),
extras: error_properties,
format: None,
nullable: None,
};
schemas.insert("Error".to_string(), Referenceable::data(error_schema));
let mut responses = BTreeMap::new();
responses.insert("NotFound".to_string(), Referenceable::data(
Response::new("Resource not found")
.with_content({
let mut content = BTreeMap::new();
content.insert("application/json".to_string(),
MediaType::new().with_schema(Referenceable::schema_ref("Error")));
content
})
));
responses.insert("ValidationError".to_string(), Referenceable::data(
Response::new("Validation error")
.with_content({
let mut content = BTreeMap::new();
content.insert("application/json".to_string(),
MediaType::new().with_schema(Referenceable::schema_ref("Error")));
content
})
));
let mut parameters = BTreeMap::new();
parameters.insert("limitParam".to_string(), Referenceable::data(
Parameter::new("limit", ParameterIn::Query)
.with_description("Number of items to return")
.with_schema(Referenceable::data(
Schema::integer()
.with_format("int32")
))
));
parameters.insert("offsetParam".to_string(), Referenceable::data(
Parameter::new("offset", ParameterIn::Query)
.with_description("Number of items to skip")
.with_schema(Referenceable::integer_schema())
));
let mut security_schemes = BTreeMap::new();
security_schemes.insert("bearerAuth".to_string(), Referenceable::data(
SecurityScheme {
_type: SecurityType::Http {
scheme: "bearer".to_string(),
bearer_format: Some("JWT".to_string()),
},
description: Some("JWT Bearer token authentication".to_string()),
}
));
security_schemes.insert("apiKey".to_string(), Referenceable::data(
SecurityScheme {
_type: SecurityType::ApiKey {
name: "X-API-Key".to_string(),
_in: ParameterIn::Header,
},
description: Some("API Key authentication".to_string()),
}
));
let components = Components::new()
.with_schemas(schemas)
.with_responses(responses)
.with_parameters(parameters);
let mut security_requirement_data = BTreeMap::new();
security_requirement_data.insert("bearerAuth".to_string(), vec![]);
let security_requirements = vec![SecurityRequirement { data: security_requirement_data }];
let contact = Contact::new()
.with_name("API Team")
.with_email("api-team@example.com")
.with_url("https://example.com/contact");
let license = License::new("MIT")
.with_url("https://opensource.org/licenses/MIT");
let info = Info::new("User Management API", "2.1.0")
.with_description("A comprehensive API for managing users with authentication, validation, and full CRUD operations")
.with_contact(contact)
.with_license(license);
let servers = vec![
Server::new("https://api.example.com/v2")
.with_description("Production server"),
Server::new("https://staging-api.example.com/v2")
.with_description("Staging server"),
Server::new("http://localhost:3000/v2")
.with_description("Development server"),
];
let tags = vec![
Tag::with_description("users", "User management operations"),
Tag::with_description("auth", "Authentication operations"),
];
let external_docs = ExternalDocumentation {
description: Some("Find more info here".to_string()),
url: "https://example.com/docs".to_string(),
};
let mut api = builders::api("User Management API", "2.1.0")
.with_description("A comprehensive API for managing users")
.with_servers(servers)
.with_components(components);
api.info = info;
api.security = Some(security_requirements);
api.tags = Some(tags);
api.external_docs = Some(external_docs);
api = api
.add_path("/auth/login", PathItem::new()
.with_post(builders::post("User login")
.tag("auth")
.operation_id("loginUser")
.request_body(Referenceable::json_body(
Referenceable::data(Schema::object()
.with_description("Login credentials"))
))
.response("200", Referenceable::data(
Response::new("Login successful")
.with_content({
let mut content = BTreeMap::new();
content.insert("application/json".to_string(),
MediaType::new().with_schema(
Referenceable::data(Schema::object()
.with_description("Login response with token"))
));
content
})
))
.response("401", Referenceable::error("Invalid credentials"))
.build()))
.add_path("/users", PathItem::new()
.with_get(builders::get("List users")
.tag("users")
.operation_id("listUsers")
.parameter(Referenceable::parameter_ref("limitParam"))
.parameter(Referenceable::parameter_ref("offsetParam"))
.response("200", Referenceable::data(
Response::new("List of users")
.with_content({
let mut content = BTreeMap::new();
content.insert("application/json".to_string(),
MediaType::new().with_schema(
Referenceable::data(Schema::array())
));
content
})
))
.build())
.with_post(builders::post("Create user")
.tag("users")
.operation_id("createUser")
.request_body(Referenceable::json_body(
Referenceable::schema_ref("User")
))
.response("201", Referenceable::data(
Response::new("User created")
.with_content({
let mut content = BTreeMap::new();
content.insert("application/json".to_string(),
MediaType::new().with_schema(Referenceable::schema_ref("User")));
content
})
))
.response("400", Referenceable::response_ref("ValidationError"))
.build()))
.add_path("/users/{id}", PathItem::new()
.with_get(builders::get("Get user by ID")
.tag("users")
.operation_id("getUserById")
.parameter(Referenceable::path_param("id")
.with_schema(Referenceable::integer_schema())
.with_description("User ID"))
.response("200", Referenceable::data(
Response::new("User details")
.with_content({
let mut content = BTreeMap::new();
content.insert("application/json".to_string(),
MediaType::new().with_schema(Referenceable::schema_ref("User")));
content
})
))
.response("404", Referenceable::response_ref("NotFound"))
.build())
.with_put(builders::put("Update user")
.tag("users")
.operation_id("updateUser")
.parameter(Referenceable::path_param("id")
.with_schema(Referenceable::integer_schema())
.with_description("User ID"))
.request_body(Referenceable::json_body(
Referenceable::schema_ref("User")
))
.response("200", Referenceable::data(
Response::new("User updated")
.with_content({
let mut content = BTreeMap::new();
content.insert("application/json".to_string(),
MediaType::new().with_schema(Referenceable::schema_ref("User")));
content
})
))
.response("404", Referenceable::response_ref("NotFound"))
.response("400", Referenceable::response_ref("ValidationError"))
.build())
.with_delete(builders::delete("Delete user")
.tag("users")
.operation_id("deleteUser")
.parameter(Referenceable::path_param("id")
.with_schema(Referenceable::integer_schema())
.with_description("User ID"))
.response("204", Referenceable::ok("User deleted"))
.response("404", Referenceable::response_ref("NotFound"))
.build()));
api
}
fn demonstrate_referenceable_types() {
println!("\n=== Referenceable Types Examples ===");
let inline_schema = Referenceable::data(Schema::string());
println!("Inline schema: {:?}", inline_schema.is_data());
let schema_ref = Referenceable::schema_ref("User");
println!("Schema reference: {:?}", schema_ref.is_reference());
let custom_ref: Referenceable<oas::Response> = Referenceable::component_ref("responses", "NotFound");
println!("Custom reference: {:?}", custom_ref.as_reference());
let query_param = Referenceable::query_param("filter")
.with_schema(Referenceable::string_schema())
.with_description("Filter criteria");
let path_param = Referenceable::path_param("id")
.with_schema(Referenceable::integer_schema());
println!("Query param created: {:?}", query_param.is_data());
println!("Path param created: {:?}", path_param.is_data());
}
fn demonstrate_schema_creation() {
println!("\n=== Schema Creation Examples ===");
let string_schema = Schema::string();
let integer_schema = Schema::integer().with_format("int64");
let _boolean_schema = Schema::boolean();
let _array_schema = Schema::array();
let object_schema = Schema::object().with_description("Custom object");
println!("String schema type: {:?}", string_schema._type);
println!("Integer schema format: {:?}", integer_schema.format);
println!("Object schema description: {:?}", object_schema.description);
let ref_string = Referenceable::string_schema();
let ref_integer = Referenceable::integer_schema();
let ref_array = Referenceable::array_schema();
println!("Referenceable string: {:?}", ref_string.is_data());
println!("Referenceable integer: {:?}", ref_integer.is_data());
println!("Referenceable array: {:?}", ref_array.is_data());
}