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}