Add fullstack platform to serve and build commands
This commit is contained in:
1 parent
f652474a6e
commit
bd743fa2f9
7 files changed
+209
-49
No files matched your search
@@ -47,6 +47,32 @@ impl Build {
|
|||||||
Platform::Desktop => {
|
Platform::Desktop => {
|
||||||
crate::builder::build_desktop(&crate_config, false)?;
|
crate::builder::build_desktop(&crate_config, false)?;
|
||||||
}
|
}
|
||||||
|
Platform::Fullstack => {
|
||||||
|
{
|
||||||
|
let mut web_config = crate_config.clone();
|
||||||
|
let web_feature = self.build.client_feature;
|
||||||
|
let features = &mut web_config.features;
|
||||||
|
match features {
|
||||||
|
Some(features) => {
|
||||||
|
features.push(web_feature);
|
||||||
|
}
|
||||||
|
None => web_config.features = Some(vec![web_feature]),
|
||||||
|
};
|
||||||
|
crate::builder::build(&crate_config, false)?;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut desktop_config = crate_config.clone();
|
||||||
|
let desktop_feature = self.build.server_feature;
|
||||||
|
let features = &mut desktop_config.features;
|
||||||
|
match features {
|
||||||
|
Some(features) => {
|
||||||
|
features.push(desktop_feature);
|
||||||
|
}
|
||||||
|
None => desktop_config.features = Some(vec![desktop_feature]),
|
||||||
|
};
|
||||||
|
crate::builder::build_desktop(&desktop_config, false)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let temp = gen_page(&crate_config.dioxus_config, false);
|
let temp = gen_page(&crate_config.dioxus_config, false);
|
||||||
|
|||||||
@@ -35,6 +35,30 @@ pub struct ConfigOptsBuild {
|
|||||||
/// Space separated list of features to activate
|
/// Space separated list of features to activate
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub features: Option<Vec<String>>,
|
pub features: Option<Vec<String>>,
|
||||||
|
|
||||||
|
/// The feature to use for the client in a fullstack app [default: "web"]
|
||||||
|
#[clap(long, default_value_t = { "web".to_string() })]
|
||||||
|
pub client_feature: String,
|
||||||
|
|
||||||
|
/// The feature to use for the server in a fullstack app [default: "ssr"]
|
||||||
|
#[clap(long, default_value_t = { "ssr".to_string() })]
|
||||||
|
pub server_feature: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ConfigOptsServe> for ConfigOptsBuild {
|
||||||
|
fn from(serve: ConfigOptsServe) -> Self {
|
||||||
|
Self {
|
||||||
|
target: serve.target,
|
||||||
|
release: serve.release,
|
||||||
|
verbose: serve.verbose,
|
||||||
|
example: serve.example,
|
||||||
|
profile: serve.profile,
|
||||||
|
platform: serve.platform,
|
||||||
|
features: serve.features,
|
||||||
|
client_feature: serve.client_feature,
|
||||||
|
server_feature: serve.server_feature,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize, Parser)]
|
#[derive(Clone, Debug, Default, Deserialize, Parser)]
|
||||||
@@ -89,6 +113,14 @@ pub struct ConfigOptsServe {
|
|||||||
/// Space separated list of features to activate
|
/// Space separated list of features to activate
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
pub features: Option<Vec<String>>,
|
pub features: Option<Vec<String>>,
|
||||||
|
|
||||||
|
/// The feature to use for the client in a fullstack app [default: "web"]
|
||||||
|
#[clap(long, default_value_t = { "web".to_string() })]
|
||||||
|
pub client_feature: String,
|
||||||
|
|
||||||
|
/// The feature to use for the server in a fullstack app [default: "ssr"]
|
||||||
|
#[clap(long, default_value_t = { "ssr".to_string() })]
|
||||||
|
pub server_feature: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Serialize, Deserialize, Debug)]
|
||||||
@@ -99,6 +131,9 @@ pub enum Platform {
|
|||||||
#[clap(name = "desktop")]
|
#[clap(name = "desktop")]
|
||||||
#[serde(rename = "desktop")]
|
#[serde(rename = "desktop")]
|
||||||
Desktop,
|
Desktop,
|
||||||
|
#[clap(name = "fullstack")]
|
||||||
|
#[serde(rename = "fullstack")]
|
||||||
|
Fullstack,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Config options for the bundling system.
|
/// Config options for the bundling system.
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ pub struct Serve {
|
|||||||
impl Serve {
|
impl Serve {
|
||||||
pub async fn serve(self, bin: Option<PathBuf>) -> Result<()> {
|
pub async fn serve(self, bin: Option<PathBuf>) -> Result<()> {
|
||||||
let mut crate_config = crate::CrateConfig::new(bin)?;
|
let mut crate_config = crate::CrateConfig::new(bin)?;
|
||||||
|
let serve_cfg = self.serve.clone();
|
||||||
|
|
||||||
// change the relase state.
|
// change the relase state.
|
||||||
crate_config.with_hot_reload(self.serve.hot_reload);
|
crate_config.with_hot_reload(self.serve.hot_reload);
|
||||||
@@ -49,7 +50,10 @@ impl Serve {
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
cfg::Platform::Desktop => {
|
cfg::Platform::Desktop => {
|
||||||
server::desktop::startup(crate_config.clone()).await?;
|
server::desktop::startup(crate_config.clone(), &serve_cfg).await?;
|
||||||
|
}
|
||||||
|
cfg::Platform::Fullstack => {
|
||||||
|
server::fullstack::startup(crate_config.clone(), &serve_cfg).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
cfg::ConfigOptsServe,
|
||||||
server::{
|
server::{
|
||||||
output::{print_console_info, PrettierOptions},
|
output::{print_console_info, PrettierOptions},
|
||||||
setup_file_watcher, setup_file_watcher_hot_reload,
|
setup_file_watcher, setup_file_watcher_hot_reload,
|
||||||
@@ -19,7 +20,16 @@ use tokio::sync::broadcast::{self};
|
|||||||
#[cfg(feature = "plugin")]
|
#[cfg(feature = "plugin")]
|
||||||
use plugin::PluginManager;
|
use plugin::PluginManager;
|
||||||
|
|
||||||
pub async fn startup(config: CrateConfig) -> Result<()> {
|
use super::Platform;
|
||||||
|
|
||||||
|
pub async fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()> {
|
||||||
|
startup_with_platform::<DesktopPlatform>(config, serve).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn startup_with_platform<P: Platform + Send + 'static>(
|
||||||
|
config: CrateConfig,
|
||||||
|
serve: &ConfigOptsServe,
|
||||||
|
) -> Result<()> {
|
||||||
// ctrl-c shutdown checker
|
// ctrl-c shutdown checker
|
||||||
let _crate_config = config.clone();
|
let _crate_config = config.clone();
|
||||||
let _ = ctrlc::set_handler(move || {
|
let _ = ctrlc::set_handler(move || {
|
||||||
@@ -29,17 +39,19 @@ pub async fn startup(config: CrateConfig) -> Result<()> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
match config.hot_reload {
|
match config.hot_reload {
|
||||||
true => serve_hot_reload(config).await?,
|
true => serve_hot_reload::<P>(config, serve).await?,
|
||||||
false => serve_default(config).await?,
|
false => serve_default::<P>(config, serve).await?,
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start the server without hot reload
|
/// Start the server without hot reload
|
||||||
pub async fn serve_default(config: CrateConfig) -> Result<()> {
|
async fn serve_default<P: Platform + Send + 'static>(
|
||||||
let (child, first_build_result) = start_desktop(&config)?;
|
config: CrateConfig,
|
||||||
let currently_running_child: RwLock<Child> = RwLock::new(child);
|
serve: &ConfigOptsServe,
|
||||||
|
) -> Result<()> {
|
||||||
|
let platform = RwLock::new(P::start(&config, serve)?);
|
||||||
|
|
||||||
log::info!("🚀 Starting development server...");
|
log::info!("🚀 Starting development server...");
|
||||||
|
|
||||||
@@ -49,49 +61,29 @@ pub async fn serve_default(config: CrateConfig) -> Result<()> {
|
|||||||
{
|
{
|
||||||
let config = config.clone();
|
let config = config.clone();
|
||||||
|
|
||||||
move || {
|
move || platform.write().unwrap().rebuild(&config)
|
||||||
let mut current_child = currently_running_child.write().unwrap();
|
|
||||||
current_child.kill()?;
|
|
||||||
let (child, result) = start_desktop(&config)?;
|
|
||||||
*current_child = child;
|
|
||||||
Ok(result)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
&config,
|
&config,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Print serve info
|
|
||||||
print_console_info(
|
|
||||||
&config,
|
|
||||||
PrettierOptions {
|
|
||||||
changed: vec![],
|
|
||||||
warnings: first_build_result.warnings,
|
|
||||||
elapsed_time: first_build_result.elapsed_time,
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
|
|
||||||
std::future::pending::<()>().await;
|
std::future::pending::<()>().await;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start the server without hot reload
|
|
||||||
|
|
||||||
/// Start dx serve with hot reload
|
/// Start dx serve with hot reload
|
||||||
pub async fn serve_hot_reload(config: CrateConfig) -> Result<()> {
|
async fn serve_hot_reload<P: Platform + Send + 'static>(
|
||||||
let (_, first_build_result) = start_desktop(&config)?;
|
config: CrateConfig,
|
||||||
|
serve: &ConfigOptsServe,
|
||||||
println!("🚀 Starting development server...");
|
) -> Result<()> {
|
||||||
|
let platform = RwLock::new(P::start(&config, serve)?);
|
||||||
|
|
||||||
// Setup hot reload
|
// Setup hot reload
|
||||||
let FileMapBuildResult { map, errors } =
|
let FileMapBuildResult { map, errors } =
|
||||||
FileMap::<HtmlCtx>::create(config.crate_dir.clone()).unwrap();
|
FileMap::<HtmlCtx>::create(config.crate_dir.clone()).unwrap();
|
||||||
|
|
||||||
println!("🚀 Starting development server...");
|
|
||||||
|
|
||||||
for err in errors {
|
for err in errors {
|
||||||
log::error!("{}", err);
|
log::error!("{}", err);
|
||||||
}
|
}
|
||||||
@@ -119,24 +111,13 @@ pub async fn serve_hot_reload(config: CrateConfig) -> Result<()> {
|
|||||||
for channel in &mut *channels.lock().unwrap() {
|
for channel in &mut *channels.lock().unwrap() {
|
||||||
send_msg(HotReloadMsg::Shutdown, channel);
|
send_msg(HotReloadMsg::Shutdown, channel);
|
||||||
}
|
}
|
||||||
Ok(start_desktop(&config)?.1)
|
Ok(platform.write().unwrap().rebuild(&config)?)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Print serve info
|
|
||||||
print_console_info(
|
|
||||||
&config,
|
|
||||||
PrettierOptions {
|
|
||||||
changed: vec![],
|
|
||||||
warnings: first_build_result.warnings,
|
|
||||||
elapsed_time: first_build_result.elapsed_time,
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
|
|
||||||
clear_paths();
|
clear_paths();
|
||||||
|
|
||||||
match LocalSocketListener::bind("@dioxusin") {
|
match LocalSocketListener::bind("@dioxusin") {
|
||||||
@@ -228,7 +209,7 @@ fn send_msg(msg: HotReloadMsg, channel: &mut impl std::io::Write) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_desktop(config: &CrateConfig) -> Result<(Child, BuildResult)> {
|
fn start_desktop(config: &CrateConfig) -> Result<(Child, BuildResult)> {
|
||||||
// Run the desktop application
|
// Run the desktop application
|
||||||
let result = crate::builder::build_desktop(config, true)?;
|
let result = crate::builder::build_desktop(config, true)?;
|
||||||
|
|
||||||
@@ -246,3 +227,37 @@ pub fn start_desktop(config: &CrateConfig) -> Result<(Child, BuildResult)> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct DesktopPlatform {
|
||||||
|
currently_running_child: Child,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Platform for DesktopPlatform {
|
||||||
|
fn start(config: &CrateConfig, _serve: &ConfigOptsServe) -> Result<Self> {
|
||||||
|
let (child, first_build_result) = start_desktop(&config)?;
|
||||||
|
|
||||||
|
log::info!("🚀 Starting development server...");
|
||||||
|
|
||||||
|
// Print serve info
|
||||||
|
print_console_info(
|
||||||
|
&config,
|
||||||
|
PrettierOptions {
|
||||||
|
changed: vec![],
|
||||||
|
warnings: first_build_result.warnings,
|
||||||
|
elapsed_time: first_build_result.elapsed_time,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
currently_running_child: child,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rebuild(&mut self, config: &CrateConfig) -> Result<BuildResult> {
|
||||||
|
self.currently_running_child.kill()?;
|
||||||
|
let (child, result) = start_desktop(&config)?;
|
||||||
|
self.currently_running_child = child;
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
use crate::{
|
||||||
|
cfg::{ConfigOptsBuild, ConfigOptsServe},
|
||||||
|
CrateConfig, Result,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{desktop, Platform};
|
||||||
|
|
||||||
|
pub async fn startup(config: CrateConfig, serve: &ConfigOptsServe) -> Result<()> {
|
||||||
|
desktop::startup_with_platform::<FullstackPlatform>(config, serve).await
|
||||||
|
}
|
||||||
|
|
||||||
|
struct FullstackPlatform {
|
||||||
|
serve: ConfigOptsServe,
|
||||||
|
desktop: desktop::DesktopPlatform,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Platform for FullstackPlatform {
|
||||||
|
fn start(config: &CrateConfig, serve: &ConfigOptsServe) -> Result<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
{
|
||||||
|
{
|
||||||
|
build_web(serve.clone())?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut desktop_config = config.clone();
|
||||||
|
let desktop_feature = serve.server_feature.clone();
|
||||||
|
let features = &mut desktop_config.features;
|
||||||
|
match features {
|
||||||
|
Some(features) => {
|
||||||
|
features.push(desktop_feature);
|
||||||
|
}
|
||||||
|
None => desktop_config.features = Some(vec![desktop_feature]),
|
||||||
|
};
|
||||||
|
let desktop = desktop::DesktopPlatform::start(&desktop_config, serve)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
desktop,
|
||||||
|
serve: serve.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rebuild(&mut self, crate_config: &CrateConfig) -> Result<crate::BuildResult> {
|
||||||
|
build_web(self.serve.clone())?;
|
||||||
|
{
|
||||||
|
let mut desktop_config = crate_config.clone();
|
||||||
|
let desktop_feature = self.serve.server_feature.clone();
|
||||||
|
let features = &mut desktop_config.features;
|
||||||
|
match features {
|
||||||
|
Some(features) => {
|
||||||
|
features.push(desktop_feature);
|
||||||
|
}
|
||||||
|
None => desktop_config.features = Some(vec![desktop_feature]),
|
||||||
|
};
|
||||||
|
self.desktop.rebuild(&desktop_config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_web(serve: ConfigOptsServe) -> Result<()> {
|
||||||
|
let mut web_config: ConfigOptsBuild = serve.into();
|
||||||
|
let web_feature = web_config.client_feature.clone();
|
||||||
|
let features = &mut web_config.features;
|
||||||
|
match features {
|
||||||
|
Some(features) => {
|
||||||
|
features.push(web_feature);
|
||||||
|
}
|
||||||
|
None => web_config.features = Some(vec![web_feature]),
|
||||||
|
};
|
||||||
|
web_config.platform = Some(crate::cfg::Platform::Web);
|
||||||
|
crate::cli::build::Build { build: web_config }.build(None)
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{BuildResult, CrateConfig, Result};
|
use crate::{cfg::ConfigOptsServe, BuildResult, CrateConfig, Result};
|
||||||
|
|
||||||
use cargo_metadata::diagnostic::Diagnostic;
|
use cargo_metadata::diagnostic::Diagnostic;
|
||||||
use dioxus_core::Template;
|
use dioxus_core::Template;
|
||||||
@@ -14,6 +14,7 @@ use tokio::sync::broadcast::Sender;
|
|||||||
mod output;
|
mod output;
|
||||||
use output::*;
|
use output::*;
|
||||||
pub mod desktop;
|
pub mod desktop;
|
||||||
|
pub mod fullstack;
|
||||||
pub mod web;
|
pub mod web;
|
||||||
|
|
||||||
/// Sets up a file watcher
|
/// Sets up a file watcher
|
||||||
@@ -180,3 +181,10 @@ async fn setup_file_watcher_hot_reload<F: Fn() -> Result<BuildResult> + Send + '
|
|||||||
|
|
||||||
Ok(watcher)
|
Ok(watcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) trait Platform {
|
||||||
|
fn start(config: &CrateConfig, serve: &ConfigOptsServe) -> Result<Self>
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
fn rebuild(&mut self, config: &CrateConfig) -> Result<BuildResult>;
|
||||||
|
}
|
||||||
@@ -67,7 +67,7 @@ pub async fn startup(port: u16, config: CrateConfig, start_browser: bool) -> Res
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Start the server without hot reload
|
/// Start the server without hot reload
|
||||||
pub async fn serve_default(
|
async fn serve_default(
|
||||||
ip: String,
|
ip: String,
|
||||||
port: u16,
|
port: u16,
|
||||||
config: CrateConfig,
|
config: CrateConfig,
|
||||||
@@ -128,7 +128,7 @@ pub async fn serve_default(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Start dx serve with hot reload
|
/// Start dx serve with hot reload
|
||||||
pub async fn serve_hot_reload(
|
async fn serve_hot_reload(
|
||||||
ip: String,
|
ip: String,
|
||||||
port: u16,
|
port: u16,
|
||||||
config: CrateConfig,
|
config: CrateConfig,
|
||||||
|
|||||||
Reference in new issue
Block a user