1mod api;
2mod auth;
3mod db;
4mod env;
5mod rpc;
6
7use ::rpc::Peer;
8use anyhow::Result;
9use async_trait::async_trait;
10use db::{Db, PostgresDb};
11use serde::Deserialize;
12use std::sync::Arc;
13use tokio::net::TcpListener;
14
15// type Request = tide::Request<Arc<AppState>>;
16
17#[derive(Default, Deserialize)]
18pub struct Config {
19 pub http_port: u16,
20 pub database_url: String,
21 pub api_token: String,
22}
23
24pub struct AppState {
25 db: Arc<dyn Db>,
26 config: Config,
27}
28
29impl AppState {
30 async fn new(config: Config) -> Result<Arc<Self>> {
31 let db = PostgresDb::new(&config.database_url, 5).await?;
32
33 let this = Self {
34 db: Arc::new(db),
35 config,
36 };
37 Ok(Arc::new(this))
38 }
39}
40
41// #[async_trait]
42// trait RequestExt {
43// fn db(&self) -> &Arc<dyn Db>;
44// }
45
46// #[async_trait]
47// impl RequestExt for Request {
48// fn db(&self) -> &Arc<dyn Db> {
49// &self.state().db
50// }
51// }
52
53#[tokio::main]
54async fn main() -> Result<()> {
55 if std::env::var("LOG_JSON").is_ok() {
56 json_env_logger::init();
57 } else {
58 env_logger::init();
59 }
60
61 if let Err(error) = env::load_dotenv() {
62 log::error!(
63 "error loading .env.toml (this is expected in production): {}",
64 error
65 );
66 }
67
68 let config = envy::from_env::<Config>().expect("error loading config");
69 let state = AppState::new(config).await?;
70 let rpc = Peer::new();
71 run_server(
72 state.clone(),
73 rpc,
74 TcpListener::bind(&format!("0.0.0.0:{}", state.config.http_port)).await?,
75 )
76 .await?;
77 Ok(())
78}
79
80pub async fn run_server(state: Arc<AppState>, rpc: Arc<Peer>, listener: TcpListener) -> Result<()> {
81 // let mut app = tide::with_state(state.clone());
82 // rpc::add_routes(&mut app, &rpc);
83
84 // let mut web = tide::with_state(state.clone());
85 // web.with(CompressMiddleware::new());
86 // api::add_routes(&mut web);
87
88 // app.at("/").nest(web);
89
90 // app.listen(listener).await?;
91
92 Ok(())
93}