baobao_codegen/schema/
types.rs

1//! Types for code generation.
2
3use baobao_core::{ContextFieldType, DatabaseType};
4use baobao_manifest::{Context, ContextField};
5
6/// Info about a command for code generation
7#[derive(Debug, Clone)]
8pub struct CommandInfo {
9    pub name: String,
10    pub description: String,
11    pub has_subcommands: bool,
12}
13
14/// Info about a context field for code generation
15#[derive(Debug, Clone)]
16pub struct ContextFieldInfo {
17    pub name: String,
18    /// Language-agnostic field type
19    pub field_type: ContextFieldType,
20    pub env_var: String,
21    pub is_async: bool,
22    pub pool: PoolConfigInfo,
23    pub sqlite: Option<SqliteConfigInfo>,
24}
25
26/// Pool configuration for code generation
27#[derive(Debug, Clone, Default)]
28pub struct PoolConfigInfo {
29    pub max_connections: Option<u32>,
30    pub min_connections: Option<u32>,
31    pub acquire_timeout: Option<u64>,
32    pub idle_timeout: Option<u64>,
33    pub max_lifetime: Option<u64>,
34}
35
36impl PoolConfigInfo {
37    pub fn has_config(&self) -> bool {
38        self.max_connections.is_some()
39            || self.min_connections.is_some()
40            || self.acquire_timeout.is_some()
41            || self.idle_timeout.is_some()
42            || self.max_lifetime.is_some()
43    }
44}
45
46/// SQLite-specific configuration for code generation
47#[derive(Debug, Clone, Default)]
48pub struct SqliteConfigInfo {
49    /// Direct file path (e.g., "db.sqlite") - takes precedence over env var
50    pub path: Option<String>,
51    pub create_if_missing: Option<bool>,
52    pub read_only: Option<bool>,
53    pub journal_mode: Option<String>,
54    pub synchronous: Option<String>,
55    pub busy_timeout: Option<u64>,
56    pub foreign_keys: Option<bool>,
57}
58
59impl SqliteConfigInfo {
60    pub fn has_config(&self) -> bool {
61        self.create_if_missing.is_some()
62            || self.read_only.is_some()
63            || self.journal_mode.is_some()
64            || self.synchronous.is_some()
65            || self.busy_timeout.is_some()
66            || self.foreign_keys.is_some()
67    }
68}
69
70/// Collect context fields from the manifest into code generation info.
71///
72/// This is a shared utility to avoid duplicating the collection logic
73/// in each language generator.
74pub fn collect_context_fields(context: &Context) -> Vec<ContextFieldInfo> {
75    context
76        .fields()
77        .into_iter()
78        .map(|(name, field)| {
79            let env_var = field
80                .env()
81                .map(|s| s.to_string())
82                .unwrap_or_else(|| field.default_env().to_string());
83
84            let pool = field
85                .pool_config()
86                .map(|p| PoolConfigInfo {
87                    max_connections: p.max_connections,
88                    min_connections: p.min_connections,
89                    acquire_timeout: p.acquire_timeout,
90                    idle_timeout: p.idle_timeout,
91                    max_lifetime: p.max_lifetime,
92                })
93                .unwrap_or_default();
94
95            let sqlite = field.sqlite_config().map(|s| SqliteConfigInfo {
96                path: s.path.clone(),
97                create_if_missing: s.create_if_missing,
98                read_only: s.read_only,
99                journal_mode: s.journal_mode.as_ref().map(|m| m.as_str().to_string()),
100                synchronous: s.synchronous.as_ref().map(|m| m.as_str().to_string()),
101                busy_timeout: s.busy_timeout,
102                foreign_keys: s.foreign_keys,
103            });
104
105            // Convert schema ContextField to core ContextFieldType
106            let field_type = match &field {
107                ContextField::Postgres(_) => ContextFieldType::Database(DatabaseType::Postgres),
108                ContextField::Mysql(_) => ContextFieldType::Database(DatabaseType::Mysql),
109                ContextField::Sqlite(_) => ContextFieldType::Database(DatabaseType::Sqlite),
110                ContextField::Http(_) => ContextFieldType::Http,
111            };
112
113            ContextFieldInfo {
114                name: name.to_string(),
115                field_type,
116                env_var,
117                is_async: field.is_async(),
118                pool,
119                sqlite,
120            }
121        })
122        .collect()
123}