feat: make db stateful + read scripts from disk

This commit is contained in:
itsscb 2025-05-25 21:05:56 +02:00
parent 6416c45d12
commit eb098ea0fd
6 changed files with 87 additions and 11 deletions

View File

@ -18,3 +18,4 @@ tower-http = { version = "0.6.4", features = ["fs"] }
tracing = { version = "0.1.41", features = ["async-await"] } tracing = { version = "0.1.41", features = ["async-await"] }
tracing-subscriber = "0.3.19" tracing-subscriber = "0.3.19"
uuid = { version = "1.16.0", features = ["v4"] } uuid = { version = "1.16.0", features = ["v4"] }
walkdir = "2.5.0"

View File

@ -46,4 +46,9 @@
[bool]$IsEnabled [bool]$IsEnabled
) )
process {} process {
0..20 | %{
Write-Output "Info: $($_)"
Write-Warning "Warning: $($_)"
}
}

View File

@ -12,6 +12,30 @@ pub async fn init_db(pool: &SqlitePool) -> Result<(), String> {
Ok(()) Ok(())
} }
pub async fn open<T: AsRef<str>>(path: T) -> Result<SqlitePool, String> {
let db_url = format!("sqlite://{}", path.as_ref());
SqlitePool::connect(&db_url)
.await
.map_err(|e| e.to_string())
}
pub async fn new<T: AsRef<str>>(path: T) -> Result<SqlitePool, String> {
std::fs::File::create_new(path.as_ref()).map_err(|e| e.to_string())?;
let db_url = format!("sqlite://{}", path.as_ref());
SqlitePool::connect(&db_url)
.await
.map_err(|e| e.to_string())
}
pub async fn import_scripts(pool: &SqlitePool, scripts: Vec<Script>) -> Result<(), String> {
for script in scripts {
add_script(pool, &script).await?;
}
Ok(())
}
// TODO: Write the whole Script into the DB // TODO: Write the whole Script into the DB
// TODO: Add Custom Error type // TODO: Add Custom Error type
#[allow(dead_code)] #[allow(dead_code)]

View File

@ -1,21 +1,64 @@
#![allow(clippy::unwrap_used)] #![allow(clippy::expect_used)]
use db::import_scripts;
use router::new_router; use router::new_router;
use script::Script;
use sqlx::SqlitePool;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tracing::info; use tracing::info;
use walkdir::WalkDir;
mod db; mod db;
mod router; mod router;
mod script; mod script;
pub fn run() { pub fn run<T: AsRef<str>>(db_path: T, script_path: T) {
let rt = tokio::runtime::Runtime::new().unwrap(); let rt = tokio::runtime::Runtime::new().expect("async runtime should always be available");
rt.block_on(async { rt.block_on(async {
tracing_subscriber::fmt::init(); tracing_subscriber::fmt::init();
let app = new_router(); let db = if let Ok(db) = db::open(db_path.as_ref()).await {
db
} else {
db::new(db_path.as_ref())
.await
.expect("should always be able to create database")
};
let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap(); let scripts = read_scripts(script_path.as_ref()).expect("failed to read scripts from dir");
info!("listening"=?listener.local_addr().unwrap());
axum::serve(listener, app).await.unwrap(); import_scripts(&db, scripts)
.await
.expect("failed to write scripts to db");
let app = new_router(db);
let listener = TcpListener::bind("0.0.0.0:3000")
.await
.expect("could not attach listener");
info!(
"listening" = format!(
"http://{}",
listener
.local_addr()
.expect("should always return local address")
)
);
axum::serve(listener, app)
.await
.expect("should always serve app");
}); });
} }
fn read_scripts<T: AsRef<str>>(dir: T) -> Result<Vec<Script>, String> {
WalkDir::new(dir.as_ref())
.into_iter()
.flatten()
.filter(|e| {
let p = e.path();
p.is_file() && p.extension().is_some_and(|ext| ext == "ps1")
})
.map(|e| format!("{}", e.path().to_string_lossy()))
.map(Script::from_file)
.collect()
}

View File

@ -18,7 +18,9 @@ use tokio::sync::mpsc; // Use std::process::Stdio
type Tx = tokio::sync::mpsc::UnboundedSender<Message>; type Tx = tokio::sync::mpsc::UnboundedSender<Message>;
fn main() { fn main() {
befehlswerk::run(); let db_path = "db_dev.db";
let script_path = "powershell";
befehlswerk::run(db_path, script_path);
} }
// #[tokio::main] // #[tokio::main]
// async fn main() { // async fn main() {

View File

@ -1,11 +1,12 @@
use axum::routing::{get, get_service}; use axum::routing::{get, get_service};
use routes::scripts::get_scripts; use routes::scripts::get_scripts;
use sqlx::SqlitePool;
use tower_http::services::ServeDir; use tower_http::services::ServeDir;
mod routes; mod routes;
pub fn new_router() -> axum::Router { pub fn new_router(db: SqlitePool) -> axum::Router {
axum::Router::new() axum::Router::new()
.fallback_service(get_service(ServeDir::new("assets"))) .fallback_service(get_service(ServeDir::new("assets")))
// .nest_service("/", ServeDir::new("assets"))
.route("/scripts", get(get_scripts)) .route("/scripts", get(get_scripts))
.with_state(db)
} }