lib.rs

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