use crate::database::traits::DatabaseProvider;
use axum::{routing::get, routing::post, Router};
use std::sync::Arc;
use tower_http::cors::CorsLayer;
#[cfg(feature = "sqlite")]
use crate::database::sqlite::SqliteProvider;
#[cfg(feature = "postgres")]
use crate::database::postgres::PostgresProvider;
use crate::api::{
count_rows_handler, execute_query_handler, get_rows_handler, get_table_schema_handler,
list_tables_handler,
};
use crate::frontend::create_frontend_router;
pub struct SqlViewerLayer<DB: DatabaseProvider> {
base_path: String,
database: Arc<DB>,
}
impl<DB: DatabaseProvider> SqlViewerLayer<DB> {
pub fn new(base_path: impl Into<String>, database: DB) -> Self {
Self {
base_path: base_path.into(),
database: Arc::new(database),
}
}
pub fn into_router(self) -> Router {
let database = self.database.clone();
let base_path = self.base_path.clone();
let api_router = Router::new()
.route("/tables", get(list_tables_handler::<DB>))
.route("/tables/{name}", get(get_table_schema_handler::<DB>))
.route("/tables/{name}/rows", get(get_rows_handler::<DB>))
.route("/tables/{name}/count", get(count_rows_handler::<DB>))
.route("/query", post(execute_query_handler::<DB>))
.with_state(database);
let frontend_router = create_frontend_router(base_path.clone());
Router::new()
.nest(&format!("{}/api", base_path), api_router)
.nest(&base_path, frontend_router)
.layer(
CorsLayer::permissive(), )
}
}
#[cfg(feature = "sqlite")]
impl SqlViewerLayer<SqliteProvider> {
pub fn sqlite(base_path: impl Into<String>, pool: sqlx::SqlitePool) -> Self {
Self::new(base_path, SqliteProvider::new(pool))
}
}
#[cfg(feature = "postgres")]
impl SqlViewerLayer<PostgresProvider> {
pub fn postgres(base_path: impl Into<String>, pool: sqlx::PgPool) -> Self {
Self::new(base_path, PostgresProvider::new(pool))
}
}