lib.rs

  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    pub slack_api_key: Option<String>,
105    pub slack_panic_channel: Option<String>,
106    pub client_token: String,
107}
108
109impl Config {
110    pub fn is_development(&self) -> bool {
111        self.zed_environment == "development".into()
112    }
113}
114
115#[derive(Default, Deserialize)]
116pub struct MigrateConfig {
117    pub database_url: String,
118    pub migrations_path: Option<PathBuf>,
119}
120
121pub struct AppState {
122    pub db: Arc<Database>,
123    pub live_kit_client: Option<Arc<dyn live_kit_server::api::Client>>,
124    pub config: Config,
125}
126
127impl AppState {
128    pub async fn new(config: Config) -> Result<Arc<Self>> {
129        let mut db_options = db::ConnectOptions::new(config.database_url.clone());
130        db_options.max_connections(config.database_max_connections);
131        let mut db = Database::new(db_options, Executor::Production).await?;
132        db.initialize_notification_kinds().await?;
133
134        let live_kit_client = if let Some(((server, key), secret)) = config
135            .live_kit_server
136            .as_ref()
137            .zip(config.live_kit_key.as_ref())
138            .zip(config.live_kit_secret.as_ref())
139        {
140            Some(Arc::new(live_kit_server::api::LiveKitClient::new(
141                server.clone(),
142                key.clone(),
143                secret.clone(),
144            )) as Arc<dyn live_kit_server::api::Client>)
145        } else {
146            None
147        };
148
149        let this = Self {
150            db: Arc::new(db),
151            live_kit_client,
152            config,
153        };
154        Ok(Arc::new(this))
155    }
156}