alibi_core/openapi/
annotations.rs1use super::{OpenApiEndpoint, OpenApiField, OpenApiModel, PluginOpenApiMetadata};
3use crate::AuthRoute;
4use alibi_schema_registry::{EntityRole, FieldDef, core_fields};
5use serde_json::json;
6
7fn wire_name(name: &str) -> String {
8 let mut words = name.split('_');
9 let mut output = words.next().unwrap_or_default().to_owned();
10 for word in words {
11 let mut letters = word.chars();
12 if let Some(first) = letters.next() {
13 output.extend(first.to_uppercase());
14 output.extend(letters);
15 }
16 }
17 output
18}
19fn field(field: &FieldDef, core: bool) -> Option<OpenApiField> {
20 if field.is_primary_key || (core && field.name == "active") {
22 return None;
23 }
24 let ty = field.ty.trim_start_matches("Option<").trim_end_matches('>');
25 let schema = match ty {
26 "DateTimeUtc" => json!({"type":"string","format":"date-time"}),
27 "bool" => json!({"type":"boolean"}),
28 "i64" | "f64" => json!({"type":"number"}),
29 "Json" => json!({"type":"json"}),
30 _ => json!({"type":"string"}),
31 };
32 let mut field = OpenApiField::new(
33 wire_name(field.name),
34 schema,
35 !field.ty.starts_with("Option<"),
36 );
37 if core && matches!(field.name.as_str(), "name" | "email") {
38 field.required = true;
39 }
40 if core && field.name == "emailVerified" {
41 field.input = false;
42 if let Some(object) = field.schema.as_object_mut() {
43 _ = object.insert("default".into(), json!(false));
44 }
45 }
46 Some(field)
47}
48#[must_use]
50pub fn core_models() -> Vec<OpenApiModel> {
51 [
52 ("User", EntityRole::User),
53 ("Session", EntityRole::Session),
54 ("Account", EntityRole::Account),
55 ("Verification", EntityRole::Verification),
56 ]
57 .into_iter()
58 .map(|(name, role)| {
59 OpenApiModel::new(
60 name,
61 core_fields(role)
62 .iter()
63 .filter_map(|definition| field(definition, true))
64 .collect(),
65 )
66 })
67 .collect()
68}
69#[must_use]
71pub fn route_metadata(routes: &[AuthRoute]) -> PluginOpenApiMetadata {
72 PluginOpenApiMetadata {
73 endpoints: routes
74 .iter()
75 .map(|route| {
76 (
77 route.method.clone(),
78 route.path.clone(),
79 OpenApiEndpoint {
80 operation_id: Some(route.operation_id.clone()),
81 ..Default::default()
82 },
83 )
84 })
85 .collect(),
86 ..Default::default()
87 }
88}