1pub mod api;
2pub mod auth;
3pub mod db;
4pub mod env;
5pub mod executor;
6pub mod rpc;
7
8#[cfg(test)]
9mod tests;
10
11use axum::{http::StatusCode, response::IntoResponse};
12use db::Database;
13use executor::Executor;
14use serde::Deserialize;
15use std::{path::PathBuf, sync::Arc};
16
17pub type Result<T, E = Error> = std::result::Result<T, E>;
18
19pub enum Error {
20 Http(StatusCode, String),
21 Database(sea_orm::error::DbErr),
22 Internal(anyhow::Error),
23}
24
25impl From<anyhow::Error> for Error {
26 fn from(error: anyhow::Error) -> Self {
27 Self::Internal(error)
28 }
29}
30
31impl From<sea_orm::error::DbErr> for Error {
32 fn from(error: sea_orm::error::DbErr) -> Self {
33 Self::Database(error)
34 }
35}
36
37impl From<axum::Error> for Error {
38 fn from(error: axum::Error) -> Self {
39 Self::Internal(error.into())
40 }
41}
42
43impl From<hyper::Error> for Error {
44 fn from(error: hyper::Error) -> Self {
45 Self::Internal(error.into())
46 }
47}
48
49impl From<serde_json::Error> for Error {
50 fn from(error: serde_json::Error) -> Self {
51 Self::Internal(error.into())
52 }
53}
54
55impl IntoResponse for Error {
56 fn into_response(self) -> axum::response::Response {
57 match self {
58 Error::Http(code, message) => (code, message).into_response(),
59 Error::Database(error) => {
60 (StatusCode::INTERNAL_SERVER_ERROR, format!("{}", &error)).into_response()
61 }
62 Error::Internal(error) => {
63 (StatusCode::INTERNAL_SERVER_ERROR, format!("{}", &error)).into_response()
64 }
65 }
66 }
67}
68
69impl std::fmt::Debug for Error {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 match self {
72 Error::Http(code, message) => (code, message).fmt(f),
73 Error::Database(error) => error.fmt(f),
74 Error::Internal(error) => error.fmt(f),
75 }
76 }
77}
78
79impl std::fmt::Display for Error {
80 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81 match self {
82 Error::Http(code, message) => write!(f, "{code}: {message}"),
83 Error::Database(error) => error.fmt(f),
84 Error::Internal(error) => error.fmt(f),
85 }
86 }
87}
88
89impl std::error::Error for Error {}
90
91#[derive(Deserialize)]
92pub struct Config {
93 pub http_port: u16,
94 pub database_url: String,
95 pub database_max_connections: u32,
96 pub api_token: String,
97 pub invite_link_prefix: String,
98 pub live_kit_server: Option<String>,
99 pub live_kit_key: Option<String>,
100 pub live_kit_secret: Option<String>,
101 pub rust_log: Option<String>,
102 pub log_json: Option<bool>,
103 pub zed_environment: Arc<str>,
104}
105
106#[derive(Default, Deserialize)]
107pub struct MigrateConfig {
108 pub database_url: String,
109 pub migrations_path: Option<PathBuf>,
110}
111
112pub struct AppState {
113 pub db: Arc<Database>,
114 pub live_kit_client: Option<Arc<dyn live_kit_server::api::Client>>,
115 pub config: Config,
116}
117
118impl AppState {
119 pub async fn new(config: Config) -> Result<Arc<Self>> {
120 let mut db_options = db::ConnectOptions::new(config.database_url.clone());
121 db_options.max_connections(config.database_max_connections);
122 let mut db = Database::new(db_options, Executor::Production).await?;
123 db.initialize_notification_kinds().await?;
124
125 let live_kit_client = if let Some(((server, key), secret)) = config
126 .live_kit_server
127 .as_ref()
128 .zip(config.live_kit_key.as_ref())
129 .zip(config.live_kit_secret.as_ref())
130 {
131 Some(Arc::new(live_kit_server::api::LiveKitClient::new(
132 server.clone(),
133 key.clone(),
134 secret.clone(),
135 )) as Arc<dyn live_kit_server::api::Client>)
136 } else {
137 None
138 };
139
140 let this = Self {
141 db: Arc::new(db),
142 live_kit_client,
143 config,
144 };
145 Ok(Arc::new(this))
146 }
147}