Browse Source

Merge branch 'master' of https://github.com/jkelleyrtp/dioxus-studio

Jonathan Kelley 3 years ago
parent
commit
1e24b5b416
19 changed files with 291 additions and 178 deletions
  1. 1 0
      .gitignore
  2. 17 14
      Cargo.toml
  3. 39 10
      README.md
  4. 8 0
      rustfmt.toml
  5. 8 7
      src/assets/dioxus.toml
  6. 62 26
      src/builder.rs
  7. 17 12
      src/cli/build/mod.rs
  8. 15 18
      src/cli/cfg.rs
  9. 4 10
      src/cli/clean/mod.rs
  10. 5 8
      src/cli/config/mod.rs
  11. 9 24
      src/cli/create/mod.rs
  12. 25 11
      src/cli/mod.rs
  13. 22 11
      src/cli/serve/mod.rs
  14. 7 16
      src/cli/translate/mod.rs
  15. 7 7
      src/config.rs
  16. 37 0
      src/error.rs
  17. 2 2
      src/main.rs
  18. 2 2
      src/server/mod.rs
  19. 4 0
      tests/main.rs

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
 /target
 Cargo.lock
+.idea/

+ 17 - 14
Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "dioxus-cli"
-version = "0.1.2"
+version = "0.1.3"
 authors = ["Jonathan Kelley"]
 edition = "2018"
 description = "CLI tool for developing, testing, and publishing Dioxus apps"
@@ -9,31 +9,34 @@ license = "MIT/Apache-2.0"
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-thiserror = "1.0.23"
-log = "0.4.13"
-fern = { version = "0.6.0", features = ["colored"] }
+# cli core
+clap = {version = "3.0.14", features = ["derive"]}
+thiserror = "1.0.30"
 wasm-bindgen-cli-support = "0.2.79"
-anyhow = "1.0.38"
-serde = { version = "1.0.133", features = ["derive"] }
-serde_json = "1"
+# features
+log = "0.4.14"
+fern = { version = "0.6.0", features = ["colored"] }
+serde = { version = "1.0.136", features = ["derive"] }
+serde_json = "1.0.79"
 toml = "0.5.8"
 fs_extra = "1.2.0"
-cargo_toml = "0.10.0"
-futures = "0.3.12"
+cargo_toml = "0.11.4"
+futures = "0.3.21"
 notify = { version = "5.0.0-pre.13", features = ["serde"] }
 html_parser = "0.6.2"
 binary-install = "0.0.2"
 convert_case = "0.5.0"
-structopt = "0.3.25"
 cargo_metadata = "0.14.1"
-tokio = { version = "1.15.0", features = ["full"] }
+tokio = { version = "1.16.1", features = ["full"] }
 atty = "0.2.14"
 regex = "1.5.4"
 chrono = "0.4.19"
+anyhow = "1.0.53"
+hyper = "0.14.17"
 
-axum = { version = "0.4.4", features = ["ws", "headers"] }
-tower-http = { version = "0.2.0", features = ["fs", "trace"] }
-headers = "0.3"
+axum = { version = "0.4.5", features = ["ws", "headers"] }
+tower-http = { version = "0.2.2", features = ["fs", "trace"] }
+headers = "0.3.7"
 # hyper = { version = "0.14.11", features = ["full"] }
 
 [[bin]]

+ 39 - 10
README.md

@@ -1,22 +1,51 @@
 <div align="center">
   <h1>📦✨  dioxus-cli </h1>
-  <p>
-    <strong>Tooling to supercharge dioxus projects</strong>
-  </p>
+  <p><strong>Tooling to supercharge dioxus projects</strong></p>
 </div>
 
-![Dioxus Logo](https://dioxuslabs.com/guide/images/dioxuslogo_full.png)
+dioxus-cli (inspired by wasm-pack and webpack) is a tool to help get dioxus projects off the ground. It handles all the build, development, bundling, and publishing to make web development simple.
+
+## Installation
 
+```shell
+# for stable
+$ cargo install dioxus-cli
+# for latest
+$ cargo install --git https://github.com/DioxusLabs/cli
+# for developing
+$ cargo install --path . --debug
+```
 
-# About
+Now, `dioxus` is in your path, you can use `dioxus --help` to get the help document.
 
-dioxus-cli (inspired by wasm-pack and webpack) is a tool to help get dioxus projects off the ground. It handles all the build, development, bundling, and publishing to make web development simple.
+```
+dioxus 0.1.2
+Build, bundle, & ship your Dioxus app
+
+USAGE:
+    dioxus [FLAGS] <SUBCOMMAND>
+
+FLAGS:
+    -h, --help       Prints help information
+    -v               Enable verbose logging
+    -V, --version    Prints version information
+
+SUBCOMMANDS:
+    build        Build the Rust WASM app and all of its assets
+    clean        Clean output artifacts
+    config       Dioxus config file controls
+    create       Init a new project for Dioxus
+    help         Prints this message or the help of the given subcommand(s)
+    serve        Build, watch & serve the Rust WASM app and all of its assets
+    translate    Translate some source file into Dioxus code
+```
 
+## Get Started 
 
-## Installation
+You can use the `dioxus create project_name` to init a dioxus project, its will be clone from the [dioxus-template](https://github.com/DioxusLabs/dioxus-template).
+
+or you can assign the template path:
 
 ```
-$ cargo install dioxus-cli
+dioxus create hello --template gh:dioxuslabs/dioxus-template
 ```
-
-Now, `dioxus` is in your path.

+ 8 - 0
rustfmt.toml

@@ -0,0 +1,8 @@
+version = "Two"
+edition = "2018"
+
+imports_granularity = "Crate"
+#use_small_heuristics = "Max"
+#control_brace_style = "ClosingNextLine"
+normalize_comments = true
+format_code_in_doc_comments = true

+ 8 - 7
src/assets/dioxus.toml

@@ -1,23 +1,24 @@
 [application]
 
-# App (Project) Name
+# dioxus project name
 name = "{{project-name}}"
 
-# Dioxus App Support Platform
-# desktop, web, mobile, ssr
-platforms = ["web"]
+# default platfrom
+# you can also use `dioxus serve/build --platform XXX` to use other platform
+# value: web | desktop
+default_platform = "web"
 
 # Web `build` & `serve` dist path
 out_dir = "dist"
 
+# resource (static) file folder
+asset_dir = "public"
+
 [web.app]
 
 # HTML title tag content
 title = "dioxus | ⛺"
 
-# resource (static) file folder
-public_dir = "public"
-
 [web.watcher]
 
 watch_path = ["src"]

+ 62 - 26
src/builder.rs

@@ -5,25 +5,24 @@ use crate::{
 };
 use std::{
     fs::{copy, create_dir_all, remove_dir_all},
+    panic,
     path::PathBuf,
     process::Command,
 };
 use wasm_bindgen_cli_support::Bindgen;
 
 pub fn build(config: &CrateConfig) -> Result<()> {
-    /*
-    [1] Build the project with cargo, generating a wasm32-unknown-unknown target (is there a more specific, better target to leverage?)
-    [2] Generate the appropriate build folders
-    [3] Wasm-bindgen the .wasm fiile, and move it into the {builddir}/modules/xxxx/xxxx_bg.wasm
-    [4] Wasm-opt the .wasm file with whatever optimizations need to be done
-    [5] Link up the html page to the wasm module
-    */
+    // [1] Build the project with cargo, generating a wasm32-unknown-unknown target (is there a more specific, better target to leverage?)
+    // [2] Generate the appropriate build folders
+    // [3] Wasm-bindgen the .wasm fiile, and move it into the {builddir}/modules/xxxx/xxxx_bg.wasm
+    // [4] Wasm-opt the .wasm file with whatever optimizations need to be done
+    // [5] Link up the html page to the wasm module
 
     let CrateConfig {
         out_dir,
         crate_dir,
         target_dir,
-        public_dir,
+        asset_dir,
         executable,
         dioxus_config,
         ..
@@ -62,9 +61,6 @@ pub fn build(config: &CrateConfig) -> Result<()> {
     // [2] Establish the output directory structure
     let bindgen_outdir = out_dir.join("assets").join("dioxus");
 
-    // [3] Bindgen the final binary for use easy linking
-    let mut bindgen_builder = Bindgen::new();
-
     let release_type = match config.release {
         true => "release",
         false => "debug",
@@ -80,17 +76,27 @@ pub fn build(config: &CrateConfig) -> Result<()> {
             .join(format!("{}.wasm", name)),
     };
 
-    bindgen_builder
-        .input_path(input_path)
-        .web(true)?
-        .debug(true)
-        .demangle(true)
-        .keep_debug(true)
-        .remove_name_section(false)
-        .remove_producers_section(false)
-        .out_name(&dioxus_config.application.name)
-        .generate(&bindgen_outdir)?;
+    let bindgen_result = panic::catch_unwind(move || {
+        // [3] Bindgen the final binary for use easy linking
+        let mut bindgen_builder = Bindgen::new();
+
+        bindgen_builder
+            .input_path(input_path)
+            .web(true).unwrap()
+            .debug(true)
+            .demangle(true)
+            .keep_debug(true)
+            .remove_name_section(false)
+            .remove_producers_section(false)
+            .out_name(&dioxus_config.application.name)
+            .generate(&bindgen_outdir).unwrap();
+    });
+    if bindgen_result.is_err() {
+        log::error!("Bindgen build failed! \nThis is probably due to the Bindgen version, dioxus-cli using `0.2.79` Bindgen crate.");
+    }
+
 
+    // this code will copy all public file to the output dir
     let copy_options = fs_extra::dir::CopyOptions {
         overwrite: true,
         skip_exist: false,
@@ -99,8 +105,8 @@ pub fn build(config: &CrateConfig) -> Result<()> {
         content_only: false,
         depth: 0,
     };
-    if public_dir.is_dir() {
-        for entry in std::fs::read_dir(&public_dir)? {
+    if asset_dir.is_dir() {
+        for entry in std::fs::read_dir(&asset_dir)? {
             let path = entry?.path();
             if path.is_file() {
                 std::fs::copy(&path, out_dir.join(path.file_name().unwrap()))?;
@@ -120,7 +126,7 @@ pub fn build(config: &CrateConfig) -> Result<()> {
     Ok(())
 }
 
-pub fn build_desktop(config: &CrateConfig) -> Result<()> {
+pub fn build_desktop(config: &CrateConfig, is_serve: bool) -> Result<()> {
     log::info!("🚅 Running build [Desktop] command...");
 
     let mut cmd = Command::new("cargo");
@@ -146,7 +152,9 @@ pub fn build_desktop(config: &CrateConfig) -> Result<()> {
     }
 
     if output.status.success() {
-        if config.out_dir.is_dir() {
+        // this code will clean the output dir.
+        // if using the serve, we will not clean the out_dir.
+        if config.out_dir.is_dir() && !is_serve {
             remove_dir_all(&config.out_dir)?;
         }
 
@@ -181,9 +189,37 @@ pub fn build_desktop(config: &CrateConfig) -> Result<()> {
             file_name
         };
 
-        create_dir_all(&config.out_dir)?;
+        if !config.out_dir.is_dir() {
+            create_dir_all(&config.out_dir)?;
+        }
         copy(res_path, &config.out_dir.join(target_file))?;
 
+        // this code will copy all public file to the output dir
+        if config.asset_dir.is_dir() {
+            let copy_options = fs_extra::dir::CopyOptions {
+                overwrite: true,
+                skip_exist: false,
+                buffer_size: 64000,
+                copy_inside: false,
+                content_only: false,
+                depth: 0,
+            };
+
+            for entry in std::fs::read_dir(&config.asset_dir)? {
+                let path = entry?.path();
+                if path.is_file() {
+                    std::fs::copy(&path, &config.out_dir.join(path.file_name().unwrap()))?;
+                } else {
+                    match fs_extra::dir::copy(&path, &config.out_dir, &copy_options) {
+                        Ok(_) => {}
+                        Err(e) => {
+                            log::warn!("Error copying dir: {}", e);
+                        }
+                    }
+                }
+            }
+        }
+
         log::info!(
             "🚩 Build completed: [./{}]",
             config

+ 17 - 12
src/cli/build/mod.rs

@@ -1,36 +1,41 @@
-use std::{io::Write, path::PathBuf};
-
-use crate::{cfg::ConfigOptsBuild, gen_page};
-use structopt::StructOpt;
+use super::*;
 
 /// Build the Rust WASM app and all of its assets.
-#[derive(Clone, Debug, StructOpt)]
-#[structopt(name = "build")]
+#[derive(Clone, Debug, Parser)]
+#[clap(name = "build")]
 pub struct Build {
-    #[structopt(flatten)]
+    #[clap(flatten)]
     pub build: ConfigOptsBuild,
 }
 
 impl Build {
-    pub fn build(self) -> anyhow::Result<()> {
+    pub fn build(self) -> Result<()> {
         let mut crate_config = crate::CrateConfig::new()?;
 
-        // change the relase state.
+        // change the release state.
         crate_config.with_release(self.build.release);
 
         if self.build.example.is_some() {
             crate_config.as_example(self.build.example.unwrap());
         }
 
-        match self.build.platform.as_str() {
+        let platform = self.build.platform.unwrap_or_else(|| {
+            crate_config
+                .dioxus_config
+                .application
+                .default_platform
+                .clone()
+        });
+
+        match platform.as_str() {
             "web" => {
                 crate::builder::build(&crate_config)?;
             }
             "desktop" => {
-                crate::builder::build_desktop(&crate_config)?;
+                crate::builder::build_desktop(&crate_config, false)?;
             }
             _ => {
-                return Err(anyhow::anyhow!("Unsoppurt platform target."));
+                return custom_error!("Unsoppurt platform target.");
             }
         }
 

+ 15 - 18
src/cli/cfg.rs

@@ -1,47 +1,44 @@
-use std::path::PathBuf;
-use structopt::StructOpt;
-
-use serde::Deserialize;
+use super::*;
 
 /// Config options for the build system.
-#[derive(Clone, Debug, Default, Deserialize, StructOpt)]
+#[derive(Clone, Debug, Default, Deserialize, Parser)]
 pub struct ConfigOptsBuild {
     /// The index HTML file to drive the bundling process [default: index.html]
-    #[structopt(parse(from_os_str))]
+    #[clap(parse(from_os_str))]
     pub target: Option<PathBuf>,
 
     /// Build in release mode [default: false]
-    #[structopt(long)]
+    #[clap(long)]
     #[serde(default)]
     pub release: bool,
 
     /// Build a example [default: ""]
-    #[structopt(long)]
+    #[clap(long)]
     pub example: Option<String>,
 
-    /// Build platform: support Web & Desktop [default: "web"]
-    #[structopt(long, default_value = "web")]
-    pub platform: String,
+    /// Build platform: support Web & Desktop [default: "default_platform"]
+    #[clap(long)]
+    pub platform: Option<String>,
 }
 
-#[derive(Clone, Debug, Default, Deserialize, StructOpt)]
+#[derive(Clone, Debug, Default, Deserialize, Parser)]
 pub struct ConfigOptsServe {
     /// The index HTML file to drive the bundling process [default: index.html]
-    #[structopt(parse(from_os_str))]
+    #[clap(parse(from_os_str))]
     pub target: Option<PathBuf>,
 
     /// Build a example [default: ""]
-    #[structopt(long)]
+    #[clap(long)]
     pub example: Option<String>,
 
     /// Build in release mode [default: false]
-    #[structopt(long)]
+    #[clap(long)]
     #[serde(default)]
     pub release: bool,
 
-    /// Build platform: support Web & Desktop [default: "web"]
-    #[structopt(long, default_value = "web")]
-    pub platform: String,
+    /// Build platform: support Web & Desktop [default: "default_platform"]
+    #[clap(long)]
+    pub platform: Option<String>,
 }
 
 /// Ensure the given value for `--public-url` is formatted correctly.

+ 4 - 10
src/cli/clean/mod.rs

@@ -1,18 +1,12 @@
-use std::{
-    fs::remove_dir_all,
-    path::PathBuf,
-    process::{Command, Stdio},
-};
-
-use structopt::StructOpt;
+use super::*;
 
 /// Build the Rust WASM app and all of its assets.
-#[derive(Clone, Debug, StructOpt)]
-#[structopt(name = "clean")]
+#[derive(Clone, Debug, Parser)]
+#[clap(name = "clean")]
 pub struct Clean {}
 
 impl Clean {
-    pub fn clean(self) -> anyhow::Result<()> {
+    pub fn clean(self) -> Result<()> {
         let crate_config = crate::CrateConfig::new()?;
 
         let output = Command::new("cargo")

+ 5 - 8
src/cli/config/mod.rs

@@ -1,11 +1,8 @@
-use std::{fs::File, io::Write};
-
-use serde::Deserialize;
-use structopt::StructOpt;
+use super::*;
 
 /// Build the Rust WASM app and all of its assets.
-#[derive(Clone, Debug, Deserialize, StructOpt)]
-#[structopt(name = "config")]
+#[derive(Clone, Debug, Deserialize, Subcommand)]
+#[clap(name = "config")]
 pub enum Config {
     /// Init `Dioxus.toml` for project/folder.
     Init {
@@ -13,14 +10,14 @@ pub enum Config {
         name: String,
 
         /// Cover old config
-        #[structopt(long)]
+        #[clap(long)]
         #[serde(default)]
         force: bool,
     },
 }
 
 impl Config {
-    pub fn config(self) -> anyhow::Result<()> {
+    pub fn config(self) -> Result<()> {
         let crate_root = crate::cargo::crate_root()?;
         match self {
             Config::Init { name, force } => {

+ 9 - 24
src/cli/create/mod.rs

@@ -1,26 +1,16 @@
-use std::{
-    fs::File,
-    io::{Read, Write},
-    path::PathBuf,
-    process::{Command, Stdio},
-};
-
-use regex::Regex;
-use serde::Deserialize;
-use structopt::StructOpt;
-
-use crate::{error::Result, Error};
+use super::*;
+use crate::custom_error;
 
 /// Build the Rust WASM app and all of its assets.
-#[derive(Clone, Debug, Default, Deserialize, StructOpt)]
-#[structopt(name = "create")]
+#[derive(Clone, Debug, Default, Deserialize, Parser)]
+#[clap(name = "create")]
 pub struct Create {
     /// Init project name
-    #[structopt(default_value = ".")]
+    #[clap(default_value = ".")]
     name: String,
 
     /// Template path
-    #[structopt(default_value = "gh:dioxuslabs/dioxus-template", long)]
+    #[clap(default_value = "gh:dioxuslabs/dioxus-template", long)]
     template: String,
 }
 
@@ -34,10 +24,7 @@ impl Create {
         let project_path = PathBuf::from(&self.name);
 
         if project_path.join("Dioxus.toml").is_file() || project_path.join("Cargo.toml").is_file() {
-            return Err(Error::Other(anyhow::anyhow!(
-                "🧨 Folder '{}' is initialized.",
-                &self.name
-            )));
+            return custom_error!("🧨 Folder '{}' is initialized.", &self.name);
         }
 
         log::info!("🔧 Start to create a new project '{}'.", self.name);
@@ -58,9 +45,7 @@ impl Create {
                 .stderr(Stdio::inherit())
                 .output()?;
             if !install_output.status.success() {
-                return Err(Error::Other(anyhow::anyhow!(
-                    "Try to install cargo-generate failed."
-                )));
+                return custom_error!("Try to install cargo-generate failed.");
             }
         }
 
@@ -74,7 +59,7 @@ impl Create {
             .output()?;
 
         if !generate_output.status.success() {
-            return Err(Error::Other(anyhow::anyhow!("Generate project failed.")));
+            return custom_error!("Generate project failed.");
         }
 
         let mut dioxus_file = File::open(project_path.join("Dioxus.toml"))?;

+ 25 - 11
src/cli/mod.rs

@@ -1,5 +1,3 @@
-use structopt::StructOpt;
-
 pub mod build;
 pub mod cfg;
 pub mod clean;
@@ -8,26 +6,41 @@ pub mod create;
 pub mod serve;
 pub mod translate;
 
+use crate::{
+    cfg::{ConfigOptsBuild, ConfigOptsServe},
+    custom_error,
+    error::Result,
+    gen_page, server, CrateConfig, Error,
+};
+use clap::{Parser, Subcommand};
+use html_parser::{Dom, Element, Node};
+use regex::Regex;
+use serde::Deserialize;
+use std::{
+    fmt::{Display, Formatter},
+    fs::{remove_dir_all, File},
+    io::{Read, Write},
+    path::PathBuf,
+    process::{exit, Command, Stdio},
+};
+
 /// Build, bundle, & ship your Dioxus app.
-///
-///
-#[derive(StructOpt)]
-#[structopt(name = "dioxus")]
+#[derive(Parser)]
+#[clap(name = "dioxus")]
 pub struct Cli {
-    #[structopt(subcommand)]
+    #[clap(subcommand)]
     pub action: Commands,
 
     /// Enable verbose logging.
-    #[structopt(short)]
+    #[clap(short)]
     pub v: bool,
-    //
     // // note: dioxus is still roughly compatible with trunk
     // /// Path to the Trunk config file [default: Trunk.toml]
-    // #[structopt(long, parse(from_os_str), env = "TRUNK_CONFIG")]
+    // #[clap(long, parse(from_os_str), env = "TRUNK_CONFIG")]
     // pub config: Option<PathBuf>,
 }
 
-#[derive(StructOpt)]
+#[derive(Parser)]
 pub enum Commands {
     /// Build the Rust WASM app and all of its assets.
     Build(build::Build),
@@ -40,5 +53,6 @@ pub enum Commands {
     /// Clean output artifacts.
     Clean(clean::Clean),
     /// Dioxus config file controls.
+    #[clap(subcommand)]
     Config(config::Config),
 }

+ 22 - 11
src/cli/serve/mod.rs

@@ -1,17 +1,20 @@
-use crate::{cfg::ConfigOptsServe, gen_page, server, CrateConfig};
-use std::{io::Write, path::PathBuf, process::{Command, Stdio}};
-use structopt::StructOpt;
+use std::{
+    io::Write,
+    path::PathBuf,
+    process::{Command, Stdio},
+};
+use super::*;
 
 /// Run the WASM project on dev-server
-#[derive(Clone, Debug, StructOpt)]
-#[structopt(name = "serve")]
+#[derive(Clone, Debug, Parser)]
+#[clap(name = "serve")]
 pub struct Serve {
-    #[structopt(flatten)]
+    #[clap(flatten)]
     pub serve: ConfigOptsServe,
 }
 
 impl Serve {
-    pub async fn serve(self) -> anyhow::Result<()> {
+    pub async fn serve(self) -> Result<()> {
         let mut crate_config = crate::CrateConfig::new()?;
 
         // change the relase state.
@@ -21,12 +24,20 @@ impl Serve {
             crate_config.as_example(self.serve.example.unwrap());
         }
 
-        match self.serve.platform.as_str() {
+        let platform = self.serve.platform.unwrap_or_else(|| {
+            crate_config
+                .dioxus_config
+                .application
+                .default_platform
+                .clone()
+        });
+
+        match platform.as_str() {
             "web" => {
                 crate::builder::build(&crate_config)?;
             }
             "desktop" => {
-                crate::builder::build_desktop(&crate_config)?;
+                crate::builder::build_desktop(&crate_config, true)?;
 
                 match &crate_config.executable {
                     crate::ExecutableType::Binary(name)
@@ -51,7 +62,7 @@ impl Serve {
                 return Ok(());
             }
             _ => {
-                return Err(anyhow::anyhow!("Unsoppurt platform target."));
+                return custom_error!("Unsoppurt platform target.");
             }
         }
 
@@ -64,7 +75,7 @@ impl Serve {
         Ok(())
     }
 
-    pub fn regen_dev_page(crate_config: &CrateConfig) -> anyhow::Result<()> {
+    pub fn regen_dev_page(crate_config: &CrateConfig) -> Result<()> {
         let serve_html = gen_page(&crate_config.dioxus_config, true);
 
         let mut file = std::fs::File::create(

+ 7 - 16
src/cli/translate/mod.rs

@@ -1,34 +1,25 @@
-use anyhow::Result;
-use html_parser::Dom;
-use html_parser::Element;
-use html_parser::Node;
-#[allow(unused_imports)]
-use std::fmt::{Display, Formatter};
-use std::io::Read;
-use std::path::PathBuf;
-use std::process::exit;
-use structopt::StructOpt;
+use super::*;
 
 /// Build the Rust WASM app and all of its assets.
-#[derive(Clone, Debug, StructOpt)]
-#[structopt(name = "translate")]
+#[derive(Clone, Debug, Parser)]
+#[clap(name = "translate")]
 pub struct Translate {
     /// Activate debug mode
     // short and long flags (-d, --debug) will be deduced from the field's name
-    #[structopt(short, long)]
+    #[clap(short, long)]
     pub component: bool,
 
     /// Input file
-    #[structopt(short, long)]
+    #[clap(short, long)]
     pub file: Option<String>,
 
     /// Output file, stdout if not present
-    #[structopt(short, long)]
+    #[clap(parse(from_os_str))]
     pub output: Option<PathBuf>,
 }
 
 impl Translate {
-    pub fn translate(self) -> anyhow::Result<()> {
+    pub fn translate(self) -> Result<()> {
         let Translate {
             component,
             output,

+ 7 - 7
src/config.rs

@@ -31,13 +31,13 @@ impl Default for DioxusConfig {
         Self {
             application: ApplicationConfig {
                 name: "dioxus".into(),
-                platforms: vec![String::from("web")],
+                default_platform: "web".to_string(),
                 out_dir: Some(PathBuf::from("dist")),
+                asset_dir: Some(PathBuf::from("public")),
             },
             web: WebConfig {
                 app: WebAppConfing {
                     title: Some("dioxus | ⛺".into()),
-                    public_dir: Some(PathBuf::from("public")),
                 },
                 watcher: WebWatcherConfing {
                     watch_path: Some(vec![PathBuf::from("src")]),
@@ -59,8 +59,9 @@ impl Default for DioxusConfig {
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct ApplicationConfig {
     pub name: String,
-    pub platforms: Vec<String>,
+    pub default_platform: String,
     pub out_dir: Option<PathBuf>,
+    pub asset_dir: Option<PathBuf>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -73,7 +74,6 @@ pub struct WebConfig {
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct WebAppConfing {
     pub title: Option<String>,
-    pub public_dir: Option<PathBuf>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -101,7 +101,7 @@ pub struct CrateConfig {
     pub crate_dir: PathBuf,
     pub workspace_dir: PathBuf,
     pub target_dir: PathBuf,
-    pub public_dir: PathBuf,
+    pub asset_dir: PathBuf,
     pub manifest: cargo_toml::Manifest<cargo_toml::Value>,
     pub executable: ExecutableType,
     pub dioxus_config: DioxusConfig,
@@ -130,7 +130,7 @@ impl CrateConfig {
 
         let cargo_def = &crate_dir.join("Cargo.toml");
 
-        let public_dir = match dioxus_config.web.app.public_dir {
+        let asset_dir = match dioxus_config.application.asset_dir {
             Some(ref v) => crate_dir.join(v),
             None => crate_dir.join("public"),
         };
@@ -154,7 +154,7 @@ impl CrateConfig {
             crate_dir,
             workspace_dir,
             target_dir,
-            public_dir,
+            asset_dir,
             manifest,
             executable,
             release,

+ 37 - 0
src/error.rs

@@ -11,6 +11,15 @@ pub enum Error {
     #[error("I/O Error: {0}")]
     IO(#[from] std::io::Error),
 
+    #[error("Format Error: {0}")]
+    FormatError(#[from] std::fmt::Error),
+
+    #[error("Format failed: {0}")]
+    ParseError(String),
+
+    #[error("Runtime Error: {0}")]
+    RuntimeError(String),
+
     #[error("Failed to write error")]
     FailedToWrite,
 
@@ -20,6 +29,9 @@ pub enum Error {
     #[error("Failed to write error")]
     CargoError(String),
 
+    #[error("{0}")]
+    CustomError(String),
+
     #[error(transparent)]
     Other(#[from] anyhow::Error),
 }
@@ -35,3 +47,28 @@ impl From<String> for Error {
         Error::Unique(s)
     }
 }
+
+impl From<html_parser::Error> for Error {
+    fn from(e: html_parser::Error) -> Self {
+        Self::ParseError(e.to_string())
+    }
+}
+
+impl From<hyper::Error> for Error {
+    fn from(e: hyper::Error) -> Self {
+        Self::RuntimeError(e.to_string())
+    }
+}
+
+#[macro_export]
+macro_rules! custom_error {
+    ($msg:literal $(,)?) => {
+        Err(Error::CustomError($msg.to_string()))
+    };
+    ($err:expr $(,)?) => {
+        Err(Error::from($err))
+    };
+    ($fmt:expr, $($arg:tt)*) => {
+        Err(Error::CustomError(format!($fmt, $($arg)*)))
+    };
+}

+ 2 - 2
src/main.rs

@@ -1,9 +1,9 @@
+use clap::Parser;
 use dioxus_cli::*;
-use structopt::StructOpt;
 
 #[tokio::main]
 async fn main() -> Result<()> {
-    let args = Cli::from_args();
+    let args = Cli::parse();
     set_up_logging();
 
     match args.action {

+ 2 - 2
src/server/mod.rs

@@ -10,14 +10,14 @@ use notify::{RecommendedWatcher, Watcher};
 use std::{path::PathBuf, sync::Arc};
 use tower_http::services::ServeDir;
 
-use crate::{builder, serve::Serve, CrateConfig};
+use crate::{builder, serve::Serve, CrateConfig, Result};
 use tokio::sync::broadcast;
 
 struct WsRelodState {
     update: broadcast::Sender<String>,
 }
 
-pub async fn startup(config: CrateConfig) -> anyhow::Result<()> {
+pub async fn startup(config: CrateConfig) -> Result<()> {
     log::info!("🚀 Starting development server...");
 
     let dist_path = config.out_dir.clone();

+ 4 - 0
tests/main.rs

@@ -0,0 +1,4 @@
+#[test]
+fn ready() {
+    println!("Compiled successfully!")
+}