base inertia setup

This commit is contained in:
LeNei
2025-03-28 10:00:09 +01:00
parent 1f38e1818b
commit 15e834060d
25 changed files with 4683 additions and 19 deletions

View File

@@ -1,28 +1,22 @@
use axum::{Router, routing::get};
use http::{Method, StatusCode};
use sqlx::PgPool;
use tower_http::cors::{Any, CorsLayer};
use tower_http::trace::TraceLayer;
use crate::config::ApiContext;
#[tracing::instrument(name = "Ping")]
async fn ping() -> StatusCode {
StatusCode::OK
}
#[derive(Clone)]
pub struct ApiContext {
pub db: PgPool,
}
pub fn build_routes(api_context: ApiContext) -> Router {
pub fn routes(api_context: ApiContext) -> Router {
let cors = CorsLayer::new()
// allow `GET` and `POST` when accessing the resource
.allow_methods([Method::GET, Method::POST])
// allow requests from any origin
.allow_origin(Any);
Router::new()
.route("/", get(ping))
.layer(TraceLayer::new_for_http())
.route("/ping", get(ping))
.layer(cors)
.with_state(api_context)
}

17
src/config/inertia.rs Normal file
View File

@@ -0,0 +1,17 @@
use axum_inertia::{InertiaConfig, vite};
pub fn get_inertia_config(is_dev: bool) -> InertiaConfig {
if !is_dev {
vite::Production::new("frontend/dist/.vite/manifest.json", "src/main.tsx")
.unwrap()
.lang("de")
.into_config()
} else {
vite::Development::default()
.port(5173)
.main("src/main.tsx")
.lang("de")
.react() // call if using react
.into_config()
}
}

View File

@@ -1,15 +1,20 @@
pub mod app;
pub mod database;
pub mod inertia;
pub mod logging;
use app::ApplicationSettings;
use axum::extract::FromRef;
use axum_inertia::InertiaConfig;
use database::DatabaseSettings;
use serde::Deserialize;
use sqlx::PgPool;
#[derive(Deserialize, Clone)]
pub struct Settings {
pub database: DatabaseSettings,
pub application: ApplicationSettings,
pub is_dev: bool,
}
pub fn get_configuration() -> Result<Settings, config::ConfigError> {
@@ -74,3 +79,15 @@ impl TryFrom<String> for Environment {
}
}
}
#[derive(Clone)]
pub struct ApiContext {
pub db: PgPool,
pub inertia: InertiaConfig,
}
impl FromRef<ApiContext> for InertiaConfig {
fn from_ref(app_state: &ApiContext) -> InertiaConfig {
app_state.inertia.clone()
}
}

View File

@@ -1,3 +1,4 @@
pub mod api;
pub mod config;
pub mod routes;
pub mod pages;
pub mod startup;

22
src/pages/mod.rs Normal file
View File

@@ -0,0 +1,22 @@
use axum::{Router, response::IntoResponse, routing::get};
use axum_inertia::Inertia;
use http::Method;
use serde_json::json;
use tower_http::cors::CorsLayer;
use crate::config::ApiContext;
#[tracing::instrument(name = "Home Page", skip(i))]
async fn home(i: Inertia) -> impl IntoResponse {
i.render("Home", json!({}))
}
pub fn routes(api_context: ApiContext) -> Router {
let cors = CorsLayer::new()
// allow `GET` and `POST` when accessing the resource
.allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE]);
Router::new()
.route("/", get(home))
.layer(cors)
.with_state(api_context)
}

View File

@@ -1,21 +1,49 @@
use crate::config::Settings;
use crate::routes::{build_routes, ApiContext};
use crate::api::routes as api_routes;
use crate::config::inertia::get_inertia_config;
use crate::config::{ApiContext, Settings};
use crate::pages::routes as page_routes;
use tower_http::services::ServeDir;
use anyhow::Context;
use axum::Router;
use tokio::net::TcpListener;
use tower_http::trace::TraceLayer;
pub async fn build(settings: Settings) -> anyhow::Result<()> {
let api_context = ApiContext {
db: settings.database.get_connection_pool(),
inertia: get_inertia_config(settings.is_dev),
};
let api_router = build_routes(api_context);
tracing::info!("Creating router...");
let mut router = Router::new()
.merge(page_routes(api_context.clone()))
.nest("/api", api_routes(api_context))
.layer(TraceLayer::new_for_http());
if !settings.is_dev {
// Serve static assets in production from the frontend/dist/assets directory instead of Vite
let service = ServeDir::new("frontend/dist/assets").precompressed_gzip();
router = router.nest_service("/assets", service);
}
let public_service = match settings.is_dev {
true => ServeDir::new("frontend/public"),
false => ServeDir::new("frontend/dist"),
};
router = router.fallback_service(public_service);
let address = format!(
"{}:{}",
settings.application.host, settings.application.port
);
let listener = TcpListener::bind(address).await.context("Failed to bind to port")?;
run(api_router, listener).await
tracing::info!("Binding to address: {}", address);
let listener = TcpListener::bind(address)
.await
.context("Failed to bind to port")?;
run(router, listener).await
}
async fn run(router: Router, listener: TcpListener) -> anyhow::Result<()> {