pub mod bulk;
pub mod format;
pub mod parameters;
pub mod paths;
pub mod responses;
pub mod schemas;
pub mod security;
#[cfg(test)]
mod tests;
use fraiseql_core::schema::{CompiledSchema, RestConfig};
use serde_json::{Value, json};
use super::resource::{MountedRoutes, RestRouteTable};
pub fn generate_openapi(
schema: &CompiledSchema,
route_table: &RestRouteTable,
auth_layer_attached: bool,
mounted: &MountedRoutes,
) -> Result<Value, String> {
let config = schema
.rest_config
.as_ref()
.ok_or_else(|| "REST config not found in compiled schema".to_string())?;
let generator =
OpenApiGenerator::new(schema, route_table, config, auth_layer_attached, mounted);
Ok(generator.generate())
}
struct OpenApiGenerator<'a> {
schema: &'a CompiledSchema,
route_table: &'a RestRouteTable,
config: &'a RestConfig,
security_required: bool,
mounted: &'a MountedRoutes,
}
impl<'a> OpenApiGenerator<'a> {
const fn new(
schema: &'a CompiledSchema,
route_table: &'a RestRouteTable,
config: &'a RestConfig,
auth_layer_attached: bool,
mounted: &'a MountedRoutes,
) -> Self {
Self {
schema,
route_table,
config,
security_required: config.require_auth || auth_layer_attached,
mounted,
}
}
fn generate(&self) -> Value {
let mut spec = json!({
"openapi": "3.0.3",
"info": self.build_info(),
"paths": self.build_paths(),
"components": self.build_components(),
});
spec["servers"] = json!([{
"url": self.config.path,
"description": "REST API base path"
}]);
spec
}
fn build_info(&self) -> Value {
json!({
"title": "FraiseQL REST API",
"version": "1.0.0",
"description": "Auto-generated REST API from compiled schema",
})
}
}