106 lines
2.7 KiB
Rust
106 lines
2.7 KiB
Rust
mod db;
|
|
mod server;
|
|
|
|
use std::sync::Arc;
|
|
|
|
use r2d2_sqlite::{rusqlite, SqliteConnectionManager};
|
|
use tera::Tera;
|
|
use tower_http::compression::CompressionLayer;
|
|
|
|
const MIGRATIONS: [&str; 2] = [
|
|
include_str!("migrations/000_initial.sql"),
|
|
include_str!("migrations/001_plants.sql"),
|
|
];
|
|
const STATIC_FILES: [(&str, &'static str); 1] = [(
|
|
"htmx_2.0.4.min.js",
|
|
include_str!("static/htmx_2.0.4.min.js"),
|
|
)];
|
|
|
|
#[derive(Clone)]
|
|
pub struct Context {
|
|
pool: db::DbPool,
|
|
tera: Arc<Tera>,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
tracing_subscriber::fmt::init();
|
|
|
|
let manager = SqliteConnectionManager::file("db.sqlite");
|
|
let pool = r2d2::Pool::new(manager).unwrap();
|
|
run_migrations(&pool).unwrap();
|
|
|
|
let tera = load_templates();
|
|
let ctx = Context {
|
|
pool,
|
|
tera: Arc::new(tera),
|
|
};
|
|
let app = server::app(ctx).layer(CompressionLayer::new().br(true).gzip(true));
|
|
|
|
let address = "0.0.0.0:8000";
|
|
|
|
tracing::info!("Starting server on {address}");
|
|
|
|
let listener = tokio::net::TcpListener::bind(address).await.unwrap();
|
|
axum::serve(listener, app.into_make_service())
|
|
.await
|
|
.unwrap();
|
|
}
|
|
|
|
fn run_migrations(pool: &db::DbPool) -> rusqlite::Result<()> {
|
|
let mut conn = pool.get().unwrap();
|
|
|
|
// If the migration version query fails, we assume it's because the table isn't there yet so we
|
|
// try to run the first migration
|
|
let mut next_version = conn
|
|
.query_row("select max(version) from migration_version", (), |row| {
|
|
row.get::<_, usize>(0).map(|n| n + 1)
|
|
})
|
|
.unwrap_or(0);
|
|
|
|
while next_version < MIGRATIONS.len() {
|
|
let tx = conn.transaction()?;
|
|
|
|
tx.execute(MIGRATIONS[next_version], ())?;
|
|
|
|
let cur_time = chrono::Local::now().timestamp();
|
|
tx.execute(
|
|
"insert into migration_version values ($1, $2)",
|
|
(next_version, cur_time),
|
|
)?;
|
|
|
|
tx.commit()?;
|
|
|
|
tracing::info!("Applied migration {next_version}");
|
|
|
|
next_version += 1;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn load_templates() -> Tera {
|
|
let mut tera = Tera::default();
|
|
|
|
tera.add_raw_templates(vec![
|
|
("base.html", include_str!("templates/base.html")),
|
|
("index.html", include_str!("templates/index.html")),
|
|
(
|
|
"partials/plants_ul.html",
|
|
include_str!("templates/partials/plants_ul.html"),
|
|
),
|
|
(
|
|
"partials/plant_li.html",
|
|
include_str!("templates/partials/plant_li.html"),
|
|
),
|
|
("plant_page.html", include_str!("templates/plant_page.html")),
|
|
(
|
|
"partials/plant_info.html",
|
|
include_str!("templates/partials/plant_info.html"),
|
|
),
|
|
])
|
|
.unwrap();
|
|
|
|
tera
|
|
}
|