Add multiple targets for server and agent, start implementing migrations
This commit is contained in:
parent
0a3b14b942
commit
2789850f5b
10
Cargo.toml
10
Cargo.toml
|
@ -3,7 +3,13 @@ name = "janky"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
[[bin]]
|
||||||
|
name = "janky-server"
|
||||||
|
path = "src/server/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "janky-agent"
|
||||||
|
path = "src/agent/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-std = { version = "1", features = ["attributes"] }
|
async-std = { version = "1", features = ["attributes"] }
|
||||||
|
@ -16,6 +22,6 @@ html-escape = "~0.2.6"
|
||||||
log = "~0.4.8"
|
log = "~0.4.8"
|
||||||
pretty_env_logger = "~0.3.1"
|
pretty_env_logger = "~0.3.1"
|
||||||
serde_json = "~1.0.0"
|
serde_json = "~1.0.0"
|
||||||
sqlx = { version = "~0.5.1", features = ["chrono", "json", "offline", "sqlite", "uuid", "runtime-async-std-rustls"] }
|
sqlx = { version = "~0.5.1", features = ["chrono", "json", "migrate", "offline", "sqlite", "uuid", "runtime-async-std-rustls"] }
|
||||||
tide = "0"
|
tide = "0"
|
||||||
uuid = { version = "~0.8.1", features = ["v4", "serde"]}
|
uuid = { version = "~0.8.1", features = ["v4", "serde"]}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
CREATE TABLE agents (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
uuid UUID NOT NULL UNIQUE,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
capabilities TEXT,
|
||||||
|
url TEXT NOT NUll,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX uuid_idx ON agents(uuid);
|
|
@ -0,0 +1,4 @@
|
||||||
|
fn main() {
|
||||||
|
println!("Janky agent!");
|
||||||
|
todo!();
|
||||||
|
}
|
11
src/main.rs
11
src/main.rs
|
@ -89,11 +89,12 @@ async fn main() -> Result<(), tide::Error> {
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
|
|
||||||
let database_url = std::env::var("DATABASE_URL").unwrap_or(":memory:".to_string());
|
let database_url = std::env::var("DATABASE_URL").unwrap_or(":memory:".to_string());
|
||||||
let state = AppState::new(
|
let pool = SqlitePool::connect(&database_url).await?;
|
||||||
SqlitePool::connect(&database_url)
|
if database_url == ":memory:" {
|
||||||
.await
|
sqlx::migrate!().run(&pool).await?;
|
||||||
.expect("Failed to open SqlitePool"),
|
}
|
||||||
);
|
|
||||||
|
let state = AppState::new(pool);
|
||||||
state.register_templates().await;
|
state.register_templates().await;
|
||||||
let mut app = tide::with_state(state);
|
let mut app = tide::with_state(state);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* This is the main Janky entrypoint for the server"
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
use async_std::sync::{Arc, RwLock};
|
||||||
|
use dotenv::dotenv;
|
||||||
|
use handlebars::Handlebars;
|
||||||
|
use log::*;
|
||||||
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct AppState<'a> {
|
||||||
|
pub db: SqlitePool,
|
||||||
|
hb: Arc<RwLock<Handlebars<'a>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppState<'_> {
|
||||||
|
fn new(db: SqlitePool) -> Self {
|
||||||
|
Self {
|
||||||
|
db: db,
|
||||||
|
hb: Arc::new(RwLock::new(Handlebars::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn register_templates(&self) -> Result<(), handlebars::TemplateFileError> {
|
||||||
|
let mut hb = self.hb.write().await;
|
||||||
|
hb.clear_templates();
|
||||||
|
hb.register_templates_directory(".hbs", "views")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn render(
|
||||||
|
&self,
|
||||||
|
name: &str,
|
||||||
|
data: &serde_json::Value,
|
||||||
|
) -> Result<tide::Body, tide::Error> {
|
||||||
|
/*
|
||||||
|
* In debug mode, reload the templates on ever render to avoid
|
||||||
|
* needing a restart
|
||||||
|
*/
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
self.register_templates().await;
|
||||||
|
}
|
||||||
|
let hb = self.hb.read().await;
|
||||||
|
let view = hb.render(name, data)?;
|
||||||
|
Ok(tide::Body::from_string(view))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The routes module contains all the tide routes and the logic to fulfill the responses for each
|
||||||
|
* route.
|
||||||
|
*
|
||||||
|
* Modules are nested for cleaner organization here
|
||||||
|
*/
|
||||||
|
mod routes {
|
||||||
|
use crate::AppState;
|
||||||
|
use log::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use tide::{Body, Request, StatusCode};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /
|
||||||
|
*/
|
||||||
|
pub async fn index(req: Request<AppState<'_>>) -> Result<Body, tide::Error> {
|
||||||
|
let params = json!({
|
||||||
|
"page": "home"
|
||||||
|
});
|
||||||
|
let mut body = req.state().render("index", ¶ms).await?;
|
||||||
|
body.set_mime("text/html");
|
||||||
|
Ok(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub mod api {
|
||||||
|
use log::*;
|
||||||
|
use tide::{Body, Request, Response, StatusCode};
|
||||||
|
|
||||||
|
use crate::AppState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[async_std::main]
|
||||||
|
async fn main() -> Result<(), tide::Error> {
|
||||||
|
pretty_env_logger::init();
|
||||||
|
dotenv().ok();
|
||||||
|
|
||||||
|
let database_url = std::env::var("DATABASE_URL").unwrap_or(":memory:".to_string());
|
||||||
|
let state = AppState::new(
|
||||||
|
SqlitePool::connect(&database_url)
|
||||||
|
.await
|
||||||
|
.expect("Failed to open SqlitePool"),
|
||||||
|
);
|
||||||
|
state.register_templates().await;
|
||||||
|
let mut app = tide::with_state(state);
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
{
|
||||||
|
info!("Activating RELEASE mode configuration");
|
||||||
|
app.with(driftwood::ApacheCombinedLogger);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
{
|
||||||
|
info!("Activating DEBUG mode configuration");
|
||||||
|
info!("Enabling a very liberal CORS policy for debug purposes");
|
||||||
|
use tide::security::{CorsMiddleware, Origin};
|
||||||
|
let cors = CorsMiddleware::new()
|
||||||
|
.allow_methods(
|
||||||
|
"GET, POST, PUT, OPTIONS"
|
||||||
|
.parse::<tide::http::headers::HeaderValue>()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.allow_origin(Origin::from("*"))
|
||||||
|
.allow_credentials(false);
|
||||||
|
|
||||||
|
app.with(cors);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* All builds will have apidocs, since they're handy
|
||||||
|
*/
|
||||||
|
app.at("/static").serve_dir("static/")?;
|
||||||
|
debug!("Configuring routes");
|
||||||
|
app.at("/").get(routes::index);
|
||||||
|
app.listen("0.0.0.0:8000").await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
Reference in New Issue