diff --git a/.gitignore b/.gitignore
index fbe21a725..2c66f7bb5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ blob.rs
Cargo.lock
**/*.rs.bk
.DS_Store
+.leptos.kdl
diff --git a/Cargo.toml b/Cargo.toml
index 1967f0de9..96547bba4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,6 +4,7 @@ members = [
"leptos",
"leptos_dom",
"leptos_core",
+ "leptos_config",
"leptos_macro",
"leptos_reactive",
"leptos_server",
diff --git a/examples/hackernews-axum/src/main.rs b/examples/hackernews-axum/src/main.rs
index 1bd111d56..28b10a78c 100644
--- a/examples/hackernews-axum/src/main.rs
+++ b/examples/hackernews-axum/src/main.rs
@@ -12,6 +12,7 @@ if #[cfg(feature = "ssr")] {
use http::StatusCode;
use std::net::SocketAddr;
use tower_http::services::ServeDir;
+ use leptos_axum::RenderOptions;
#[tokio::main]
async fn main() {
@@ -36,12 +37,14 @@ if #[cfg(feature = "ssr")] {
)
}
+ let render_options: RenderOptions = leptos_axum::RenderOptionsBuilder::default().client_pkg_path("/pkg/leptos_hackernews_axum").auto_reload(3001).build().expect("Failed to Parse RenderOptions");
+
// build our application with a route
let app = Router::new()
// `GET /` goes to `root`
.nest_service("/pkg", pkg_service)
.nest_service("/static", static_service)
- .fallback(leptos_axum::render_app_to_stream("/pkg/leptos_hackernews_axum", |cx| view! { cx, }));
+ .fallback(leptos_axum::render_app_to_stream(render_options, |cx| view! { cx, }));
// run our app with hyper
// `axum::Server` is a re-export of `hyper::Server`
diff --git a/examples/todo-app-sqlite-axum/src/main.rs b/examples/todo-app-sqlite-axum/src/main.rs
index b717b3d0b..1a5247214 100644
--- a/examples/todo-app-sqlite-axum/src/main.rs
+++ b/examples/todo-app-sqlite-axum/src/main.rs
@@ -14,7 +14,7 @@ if #[cfg(feature = "ssr")] {
use todo_app_sqlite_axum::*;
use http::StatusCode;
use tower_http::services::ServeDir;
- use leptos_axum::RenderOptions;
+ use std::env;
#[tokio::main]
async fn main() {
@@ -45,8 +45,9 @@ if #[cfg(feature = "ssr")] {
)
}
- let render_options: RenderOptions = leptos_axum::RenderOptionsBuilder::default().client_pkg_path("/pkg/todo_app_sqlite_axum").auto_reload(3001).build().expect("Failed to Parse RenderOptions");
+ let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/todo_app_sqlite_axum").reload_port(3001).environment(&env::var("RUST_ENV")).build();
+ render_options.write_to_file();
// build our application with a route
let app = Router::new()
.route("/api/*fn_name", post(leptos_axum::handle_server_fns))
diff --git a/examples/todo-app-sqlite-axum/src/todo.rs b/examples/todo-app-sqlite-axum/src/todo.rs
index c60af7fe9..fe8fcf7db 100644
--- a/examples/todo-app-sqlite-axum/src/todo.rs
+++ b/examples/todo-app-sqlite-axum/src/todo.rs
@@ -12,9 +12,9 @@ cfg_if! {
}
pub fn register_server_functions() {
- GetTodos::register();
- AddTodo::register();
- DeleteTodo::register();
+ _ = GetTodos::register();
+ _ = AddTodo::register();
+ _ = DeleteTodo::register();
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
@@ -34,7 +34,7 @@ cfg_if! {
}
#[server(GetTodos, "/api")]
-pub async fn get_todos(cx: Scope) -> Result, ServerFnError> {
+pub async fn get_todos(_cx: Scope) -> Result, ServerFnError> {
// this is just an example of how to access server context injected in the handlers
// http::Request doesn't implement Clone, so more work will be needed to do use_context() on this
// let req = use_context::>(cx)
@@ -70,7 +70,7 @@ pub async fn add_todo(title: String) -> Result<(), ServerFnError> {
.execute(&mut conn)
.await
{
- Ok(row) => Ok(()),
+ Ok(_row) => Ok(()),
Err(e) => Err(ServerFnError::ServerError(e.to_string())),
}
}
@@ -167,7 +167,7 @@ pub fn Todos(cx: Scope) -> Element {
{todo.title}
-
+
diff --git a/examples/todo-app-sqlite/src/main.rs b/examples/todo-app-sqlite/src/main.rs
index a352dad96..2e2621353 100644
--- a/examples/todo-app-sqlite/src/main.rs
+++ b/examples/todo-app-sqlite/src/main.rs
@@ -9,6 +9,7 @@ cfg_if! {
use actix_files::{Files};
use actix_web::*;
use crate::todo::*;
+ use std::env;
#[get("/style.css")]
async fn css() -> impl Responder {
@@ -26,11 +27,14 @@ cfg_if! {
crate::todo::register_server_functions();
HttpServer::new(|| {
+ let render_options: RenderOptions = RenderOptions::builder().pkg_path("/pkg/todo_app_sqlite").reload_port(3001).environment(&env::var("RUST_ENV")).build();
+ render_options.write_to_file();
+
App::new()
.service(Files::new("/pkg", "./pkg"))
.service(css)
.route("/api/{tail:.*}", leptos_actix::handle_server_fns())
- .route("/{tail:.*}", leptos_actix::render_app_to_stream("/pkg/todo_app_sqlite", |cx| view! { cx, }))
+ .route("/{tail:.*}", leptos_actix::render_app_to_stream(render_options, |cx| view! { cx, }))
//.wrap(middleware::Compress::default())
})
.bind(("127.0.0.1", 8083))?
diff --git a/integrations/actix/src/lib.rs b/integrations/actix/src/lib.rs
index c410a46ec..25c179b5d 100644
--- a/integrations/actix/src/lib.rs
+++ b/integrations/actix/src/lib.rs
@@ -138,10 +138,11 @@ pub fn handle_server_fns() -> Route {
/// # }
/// ```
pub fn render_app_to_stream(
- client_pkg_path: &'static str,
+ options: RenderOptions,
app_fn: impl Fn(leptos::Scope) -> Element + Clone + 'static,
) -> Route {
web::get().to(move |req: HttpRequest| {
+ let options = options.clone();
let app_fn = app_fn.clone();
async move {
let path = req.path();
@@ -165,12 +166,39 @@ pub fn render_app_to_stream(
}
};
- let head = format!(r#"
-
+ let pkg_path = &options.pkg_path;
+
+ let leptos_autoreload = match options.reload_port {
+ Some(port) => match &options.environment {
+ RustEnv::DEV => format!(
+ r#"
+
+ "#
+ ),
+ RustEnv::PROD => "".to_string(),
+ },
+ None => "".to_string(),
+ };
+
+ let head = format!(
+ r#"
+
- "#);
+
+ {leptos_autoreload}
+ "#
+ );
+
let tail = "";
HttpResponse::Ok().content_type("text/html").streaming(
diff --git a/integrations/axum/Cargo.toml b/integrations/axum/Cargo.toml
index faec4e628..3827eb4d9 100644
--- a/integrations/axum/Cargo.toml
+++ b/integrations/axum/Cargo.toml
@@ -11,6 +11,7 @@ description = "Axum integrations for the Leptos web framework."
axum = "0.6"
derive_builder = "0.12.0"
futures = "0.3"
+kdl = "4.6.0"
leptos = { path = "../../leptos", default-features = false, version = "0.0", features = [
"ssr",
] }
diff --git a/integrations/axum/src/lib.rs b/integrations/axum/src/lib.rs
index cb64f6757..d2453efa4 100644
--- a/integrations/axum/src/lib.rs
+++ b/integrations/axum/src/lib.rs
@@ -4,7 +4,6 @@ use axum::{
http::{HeaderMap, HeaderValue, Request, StatusCode},
response::{IntoResponse, Response},
};
-use derive_builder::Builder;
use futures::{Future, SinkExt, Stream, StreamExt};
use leptos::*;
use leptos_meta::MetaContext;
@@ -128,14 +127,6 @@ pub async fn handle_server_fns(
pub type PinnedHtmlStream = Pin> + Send>>;
-#[derive(Default, Builder, Clone)]
-pub struct RenderOptions {
- #[builder(setter(into))]
- client_pkg_path: String,
- #[builder(setter(strip_option), default)]
- auto_reload: Option,
-}
-
/// Returns an Axum [Handler](axum::handler::Handler) that listens for a `GET` request and tries
/// to route it using [leptos_router], serving an HTML stream of your application.
///
@@ -201,11 +192,12 @@ pub fn render_app_to_stream(
full_path = "http://leptos".to_string() + &path.to_string()
}
- let client_pkg_path = &options.client_pkg_path;
+ let pkg_path = &options.pkg_path;
- let leptos_autoreload = match options.auto_reload {
- Some(port) => format!(
- r#"
+ let leptos_autoreload = match options.reload_port {
+ Some(port) => match &options.environment {
+ RustEnv::DEV => format!(
+ r#"
"#
- ),
+ ),
+ RustEnv::PROD => "".to_string(),
+ },
None => "".to_string(),
};
@@ -226,7 +220,7 @@ pub fn render_app_to_stream(
-
+
{leptos_autoreload}
"#
);
diff --git a/leptos/Cargo.toml b/leptos/Cargo.toml
index 8c4f1c7d6..feb50c90c 100644
--- a/leptos/Cargo.toml
+++ b/leptos/Cargo.toml
@@ -10,6 +10,7 @@ readme = "../README.md"
[dependencies]
leptos_core = { path = "../leptos_core", default-features = false, version = "0.0.19" }
+leptos_config = { path = "../leptos_config", default-features = false, version = "0.0.1" }
leptos_dom = { path = "../leptos_dom", default-features = false, version = "0.0.19" }
leptos_macro = { path = "../leptos_macro", default-features = false, version = "0.0.19" }
leptos_reactive = { path = "../leptos_reactive", default-features = false, version = "0.0.19" }
diff --git a/leptos/src/lib.rs b/leptos/src/lib.rs
index 015886160..a24b92cc0 100644
--- a/leptos/src/lib.rs
+++ b/leptos/src/lib.rs
@@ -141,6 +141,7 @@
//! # }
//! ```
+pub use leptos_config::*;
pub use leptos_core::*;
pub use leptos_dom;
pub use leptos_dom::wasm_bindgen::{JsCast, UnwrapThrowExt};
diff --git a/leptos_config/Cargo.toml b/leptos_config/Cargo.toml
new file mode 100644
index 000000000..33f81c1e5
--- /dev/null
+++ b/leptos_config/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "leptos_config"
+version = "0.0.1"
+edition = "2021"
+authors = ["Greg Johnston"]
+license = "MIT"
+repository = "https://github.com/gbj/leptos"
+description = "Configuraiton for Leptos"
+
+[dependencies]
+typed-builder = "0.11.0"
diff --git a/leptos_config/src/lib.rs b/leptos_config/src/lib.rs
new file mode 100644
index 000000000..8b62f8969
--- /dev/null
+++ b/leptos_config/src/lib.rs
@@ -0,0 +1,83 @@
+use std::{env::VarError, str::FromStr};
+use typed_builder::TypedBuilder;
+
+#[derive(Default, TypedBuilder, Clone)]
+pub struct RenderOptions {
+ #[builder(setter(into))]
+ pub pkg_path: String,
+ #[builder(setter(into))]
+ pub environment: RustEnv,
+ #[builder(setter(strip_option), default)]
+ pub reload_port: Option,
+}
+
+impl RenderOptions {
+ /// Creates a hidden file at ./.leptos_toml so cargo-leptos can monitor settings
+ pub fn write_to_file(&self) {
+ use std::fs;
+ let options = format!(
+ r#"render_options: {{
+ pkg_path {}
+ environment {:?}
+ reload_port {:?}
+}}
+"#,
+ self.pkg_path, self.environment, self.reload_port
+ );
+ fs::write("./.leptos.kdl", options).expect("Unable to write file");
+ }
+}
+#[derive(Default, Debug, Clone)]
+pub enum RustEnv {
+ #[default]
+ PROD,
+ DEV,
+}
+
+impl FromStr for RustEnv {
+ type Err = ();
+ fn from_str(input: &str) -> Result {
+ let sanitized = input.to_lowercase();
+ match sanitized.as_ref() {
+ "dev" => Ok(Self::DEV),
+ "development" => Ok(Self::DEV),
+ "prod" => Ok(Self::PROD),
+ "production" => Ok(Self::PROD),
+ _ => Ok(Self::PROD),
+ }
+ }
+}
+
+impl From<&str> for RustEnv {
+ fn from(str: &str) -> Self {
+ let sanitized = str.to_lowercase();
+ match sanitized.as_str() {
+ "dev" => Self::DEV,
+ "development" => Self::DEV,
+ "prod" => Self::PROD,
+ "production" => Self::PROD,
+ _ => {
+ panic!("Environment var is not recognized. Maybe try `dev` or `prod`")
+ }
+ }
+ }
+}
+impl From<&Result> for RustEnv {
+ fn from(input: &Result) -> Self {
+ match input {
+ Ok(str) => {
+ let sanitized = str.to_lowercase();
+ match sanitized.as_ref() {
+ "dev" => Self::DEV,
+ "development" => Self::DEV,
+ "prod" => Self::PROD,
+ "production" => Self::PROD,
+ _ => {
+ panic!("Environment var is not recognized. Maybe try `dev` or `prod`")
+ }
+ }
+ }
+ Err(_) => Self::PROD,
+ }
+ }
+}