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