Owows so many new files
This commit is contained in:
@@ -3,10 +3,40 @@ name = "erplt-api"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
|
||||
[features]
|
||||
hydrate=["leptos/hydrate"]
|
||||
ssr=[
|
||||
"dep:erplt-db",
|
||||
"dep:erplt-config",
|
||||
"dep:leptos_axum",
|
||||
"dep:tokio",
|
||||
"dep:anyhow",
|
||||
"dep:any_spawner",
|
||||
"dep:tracing",
|
||||
"dep:axum",
|
||||
]
|
||||
|
||||
|
||||
[dependencies]
|
||||
erplt-db.path="../erplt-db"
|
||||
erplt-config.path = "../erplt-config"
|
||||
anyhow.workspace = true
|
||||
axum.workspace = true
|
||||
tokio.workspace = true
|
||||
tracing.workspace = true
|
||||
leptos.workspace = true
|
||||
leptos_meta.workspace = true
|
||||
leptos_router.workspace = true
|
||||
console_error_panic_hook.workspace = true
|
||||
wasm-bindgen.workspace = true
|
||||
|
||||
axum = { workspace = true, optional = true }
|
||||
erplt-db = { path = "../erplt-db", optional = true }
|
||||
erplt-config = { path = "../erplt-config", optional = true }
|
||||
leptos_axum = { workspace = true, optional = true }
|
||||
tokio = { workspace = true, optional = true }
|
||||
anyhow = { workspace = true, optional = true }
|
||||
any_spawner = { workspace = true, optional = true }
|
||||
tracing = { workspace = true, optional = true }
|
||||
|
||||
[package.metadata.cargo-all-features]
|
||||
denylist = ["axum", "tokio", "tower", "tower-http", "leptos_axum"]
|
||||
skip_feature_sets = [["ssr", "hydrate"], []]
|
||||
@@ -1,5 +1,21 @@
|
||||
mod routes;
|
||||
#[cfg(feature="ssr")]
|
||||
mod state;
|
||||
#[cfg(feature="ssr")]
|
||||
mod server;
|
||||
#[cfg(feature="ssr")]
|
||||
pub use server::start;
|
||||
|
||||
pub use server::start;
|
||||
#[cfg(feature="ssr")]
|
||||
use leptos::config::LeptosOptions;
|
||||
|
||||
#[cfg(feature="ssr")]
|
||||
type Router = axum::Router<LeptosOptions>;
|
||||
|
||||
#[cfg(feature = "hydrate")]
|
||||
#[wasm_bindgen::prelude::wasm_bindgen]
|
||||
pub fn hydrate() {
|
||||
use routes::pages::App;
|
||||
console_error_panic_hook::set_once();
|
||||
leptos::mount::hydrate_body(App);
|
||||
}
|
||||
8
crates/erplt-api/src/routes/api/mod.rs
Normal file
8
crates/erplt-api/src/routes/api/mod.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
mod v1;
|
||||
|
||||
|
||||
pub fn router() -> crate::Router {
|
||||
crate::Router::new()
|
||||
.merge(v1::router())
|
||||
.nest("/v1", v1::router())
|
||||
}
|
||||
9
crates/erplt-api/src/routes/api/v1/mod.rs
Normal file
9
crates/erplt-api/src/routes/api/v1/mod.rs
Normal file
@@ -0,0 +1,9 @@
|
||||
use axum::routing::get;
|
||||
|
||||
mod health;
|
||||
|
||||
|
||||
pub fn router() -> crate::Router {
|
||||
crate::Router::new()
|
||||
.route("/health", get(health::get))
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
use axum::{routing::get, Router};
|
||||
pub mod pages;
|
||||
|
||||
mod health;
|
||||
#[cfg(feature="ssr")]
|
||||
mod api;
|
||||
|
||||
pub fn router() -> Router {
|
||||
Router::new()
|
||||
.route("/health", get(health::get))
|
||||
#[cfg(feature="ssr")]
|
||||
pub fn router() -> crate::Router {
|
||||
crate::Router::new()
|
||||
.nest("/api", api::router())
|
||||
}
|
||||
11
crates/erplt-api/src/routes/pages/home.rs
Normal file
11
crates/erplt-api/src/routes/pages/home.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn HomePage() -> impl IntoView {
|
||||
view! {
|
||||
<main>
|
||||
<h1>"ERPLT"</h1>
|
||||
<p>"Welcome to ERPLT."</p>
|
||||
</main>
|
||||
}
|
||||
}
|
||||
32
crates/erplt-api/src/routes/pages/layout.rs
Normal file
32
crates/erplt-api/src/routes/pages/layout.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use leptos::prelude::*;
|
||||
|
||||
#[component]
|
||||
pub fn Layout(children: Children) -> impl IntoView {
|
||||
view! {
|
||||
<div class="flex min-h-screen">
|
||||
<aside class="w-64 border-r p-4">
|
||||
<h1 class="mb-6 text-xl font-bold">
|
||||
"ERPLT"
|
||||
</h1>
|
||||
|
||||
<nav class="space-y-2">
|
||||
<a href="/">"Dashboard"</a>
|
||||
<a href="/sales">"Sales"</a>
|
||||
<a href="/purchases">"Purchases"</a>
|
||||
<a href="/inventory">"Inventory"</a>
|
||||
<a href="/accounting">"Accounting"</a>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<div class="flex flex-1 flex-col">
|
||||
<header class="border-b p-4">
|
||||
"ERPLT"
|
||||
</header>
|
||||
|
||||
<main class="flex-1 p-6">
|
||||
{children()}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
50
crates/erplt-api/src/routes/pages/mod.rs
Normal file
50
crates/erplt-api/src/routes/pages/mod.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use leptos::prelude::*;
|
||||
use leptos_meta::*;
|
||||
use leptos_router::{
|
||||
SsrMode, StaticSegment, components::{FlatRoutes, Route, Router},
|
||||
};
|
||||
|
||||
mod home;
|
||||
mod layout;
|
||||
|
||||
#[cfg(feature="ssr")]
|
||||
pub fn shell(options: LeptosOptions) -> impl IntoView {
|
||||
view! {
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<AutoReload options=options.clone() />
|
||||
<HydrationScripts options/>
|
||||
<link rel="stylesheet" id="leptos" href="/pkg/erplt.css"/>
|
||||
<link rel="shortcut icon" type="image/ico" href="/favicon.ico"/>
|
||||
<MetaTags/>
|
||||
</head>
|
||||
<body>
|
||||
<App/>
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
pub fn App() -> impl IntoView {
|
||||
provide_meta_context();
|
||||
|
||||
view! {
|
||||
<Router>
|
||||
<FlatRoutes fallback=|| "Page not found.">
|
||||
<Route
|
||||
path=StaticSegment("")
|
||||
view=|| view! {
|
||||
<layout::Layout>
|
||||
<home::HomePage/>
|
||||
</layout::Layout>
|
||||
}
|
||||
ssr=SsrMode::Async
|
||||
/>
|
||||
</FlatRoutes>
|
||||
</Router>
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,41 @@
|
||||
use std::{net::{Ipv4Addr, SocketAddr, SocketAddrV4}, str::FromStr};
|
||||
|
||||
use anyhow::Context;
|
||||
use axum::http::StatusCode;
|
||||
use leptos::prelude::*;
|
||||
use leptos_axum::{LeptosRoutes, generate_route_list};
|
||||
|
||||
use erplt_db::DbPool;
|
||||
|
||||
#[axum::debug_handler]
|
||||
async fn fallback() -> (StatusCode, &'static str) {
|
||||
(StatusCode::NOT_FOUND, "Not Found")
|
||||
}
|
||||
use crate::routes;
|
||||
|
||||
|
||||
|
||||
pub async fn start(db: DbPool) -> anyhow::Result<()> {
|
||||
let config = erplt_config::get();
|
||||
|
||||
|
||||
// Need this because tokio has threading panics otherwise
|
||||
any_spawner::Executor::init_tokio().unwrap();
|
||||
|
||||
let leptos_options = LeptosOptions::builder()
|
||||
.output_name("erplt")
|
||||
.site_root("target/site")
|
||||
.site_pkg_dir("pkg")
|
||||
.reload_external_port(Some((config.web.port+1) as u32))
|
||||
.site_addr(SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from_str(&config.web.host)?, config.web.port)))
|
||||
.build();
|
||||
|
||||
let routes = generate_route_list(routes::pages::App);
|
||||
|
||||
let app = axum::Router::new()
|
||||
.merge(crate::routes::router())
|
||||
.fallback(fallback);
|
||||
//.merge(crate::routes::router())
|
||||
.merge(routes::router())
|
||||
.leptos_routes(&leptos_options, routes, {
|
||||
let leptos_options = leptos_options.clone();
|
||||
move || routes::pages::shell(leptos_options.clone())
|
||||
})
|
||||
.fallback(leptos_axum::file_and_error_handler(routes::pages::shell))
|
||||
.with_state(leptos_options)
|
||||
.with_state(db);
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +46,7 @@ pub async fn start(db: DbPool) -> anyhow::Result<()> {
|
||||
|
||||
tracing::info!("Web server listening on http://{}", listener.local_addr()?);
|
||||
|
||||
axum::serve(listener, app)
|
||||
axum::serve(listener, app.into_make_service())
|
||||
.await
|
||||
.context("Web server stopped unexpectedly")?;
|
||||
|
||||
|
||||
1
crates/erplt-api/style/tailwind.css
Normal file
1
crates/erplt-api/style/tailwind.css
Normal file
@@ -0,0 +1 @@
|
||||
@import "tailwindcss";
|
||||
@@ -2,7 +2,6 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::Context;
|
||||
use camino::Utf8PathBuf;
|
||||
use serde::de;
|
||||
|
||||
pub mod cli;
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use anyhow::Context;
|
||||
use diesel::r2d2::ConnectionManager;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub type DbBackend = diesel::pg::Pg;
|
||||
pub type DbConnection = diesel::PgConnection;
|
||||
pub type DbPool = diesel::r2d2::Pool<
|
||||
@@ -25,6 +26,8 @@ pub fn connect(url: &str) -> anyhow::Result<DbPool> {
|
||||
|
||||
pool.get()
|
||||
.context("Failed to connect to PostgreSQL")?;
|
||||
|
||||
tracing::info!("Connected to database");
|
||||
// crate::migrations::run_migrations(&pool)?;
|
||||
Ok(pool)
|
||||
}
|
||||
@@ -1,19 +1,41 @@
|
||||
[package]
|
||||
name = "erplt"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
[package]
|
||||
name = "erplt"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
erplt-db.path="../erplt-db"
|
||||
erplt-api.path="../erplt-api"
|
||||
erplt-config.path="../erplt-config"
|
||||
camino.workspace = true
|
||||
clap.workspace = true
|
||||
serde.workspace = true
|
||||
toml.workspace = true
|
||||
anyhow.workspace = true
|
||||
tracing-subscriber.workspace = true
|
||||
tracing.workspace = true
|
||||
humantime.workspace = true
|
||||
humantime-serde.workspace = true
|
||||
tokio.workspace = true
|
||||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
[features]
|
||||
default = ["ssr", "erplt-api/ssr"]
|
||||
hydrate=["erplt-api/hydrate"]
|
||||
ssr=[
|
||||
"erplt-api/ssr",
|
||||
"dep:erplt-db",
|
||||
"dep:erplt-config",
|
||||
"dep:camino",
|
||||
"dep:clap",
|
||||
"dep:serde",
|
||||
"dep:toml",
|
||||
"dep:anyhow",
|
||||
"dep:tracing",
|
||||
"dep:tracing-subscriber",
|
||||
"dep:humantime",
|
||||
"dep:humantime-serde",
|
||||
"dep:tokio",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
erplt-api.path="../erplt-api"
|
||||
erplt-db = { path="../erplt-db", optional = true }
|
||||
erplt-config = { path="../erplt-config", optional = true }
|
||||
camino = { workspace = true, optional = true }
|
||||
clap = { workspace = true, optional = true }
|
||||
serde = { workspace = true, optional = true }
|
||||
toml = { workspace = true, optional = true }
|
||||
anyhow = { workspace = true, optional = true }
|
||||
tracing-subscriber = { workspace = true, optional = true }
|
||||
tracing = { workspace = true, optional = true }
|
||||
humantime = { workspace = true, optional = true }
|
||||
humantime-serde = { workspace = true, optional = true }
|
||||
tokio = { workspace = true, optional = true }
|
||||
|
||||
2
crates/erplt/src/lib.rs
Normal file
2
crates/erplt/src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
#[cfg(feature = "hydrate")]
|
||||
pub use erplt_api::hydrate;
|
||||
Reference in New Issue
Block a user