1use std::sync::OnceLock;
2
3use axum::{response::Response, routing::get, Router as AxumRouter};
4use utoipa::openapi::OpenApi;
5
6use loco_rs::{controller::format, Result};
7
8static OPENAPI_SPEC: OnceLock<OpenApi> = OnceLock::new();
9
10pub fn set_openapi_spec(api: OpenApi) -> &'static OpenApi {
11 OPENAPI_SPEC.get_or_init(|| api)
12}
13
14pub fn get_openapi_spec() -> &'static OpenApi {
18 OPENAPI_SPEC.get().unwrap()
19}
20
21pub async fn openapi_spec_json() -> Result<Response> {
27 format::json(get_openapi_spec())
28}
29
30pub async fn openapi_spec_yaml() -> Result<Response> {
36 let yaml = get_openapi_spec()
37 .to_yaml()
38 .map_err(|e| loco_rs::Error::Any(Box::new(e)))?;
39 format::yaml(&yaml)
40}
41
42pub fn add_openapi_endpoints<T>(
44 mut app: AxumRouter<T>,
45 json_url: &Option<String>,
46 yaml_url: &Option<String>,
47) -> AxumRouter<T>
48where
49 T: Clone + Send + Sync + 'static,
50{
51 if let Some(json_url) = json_url {
52 app = app.route(json_url, get(openapi_spec_json));
53 }
54 if let Some(yaml_url) = yaml_url {
55 app = app.route(yaml_url, get(openapi_spec_yaml));
56 }
57 app
58}