From 6c351efbf027cb298fc08871d8b66d6a64761169 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Sat, 8 Jan 2022 22:57:47 -0500 Subject: [PATCH] wip: restructure the entire CLI --- Cargo.toml | 5 +- README.md | 12 -- src/builder.rs | 1 - src/buildsystem/assets.rs | 4 + src/{cmd/build.rs => buildsystem/wasm.rs} | 0 src/cli.rs | 101 --------------- src/cli/build/mod.rs | 12 ++ src/cli/cfg.rs | 75 +++++++++++ src/cli/clean/mod.rs | 9 ++ src/cli/config/mod.rs | 9 ++ src/cli/mod.rs | 47 +++++++ src/{develop => cli/serve}/develop.rs | 3 - src/{develop => cli/serve}/draw.rs | 0 src/{develop => cli/serve}/events.rs | 0 src/cli/serve/mod.rs | 9 ++ src/{develop => cli/serve}/studio.rs | 0 .../translate}/extract_svgs.rs | 0 src/cli/translate/mod.rs | 13 ++ .../translate}/to_component.rs | 2 +- src/{helpers => cli/translate}/translate.rs | 0 src/{cmd => cli/watch}/mod.rs | 0 src/cmd/studio.rs | 0 src/cmd/watch.rs | 11 -- src/config.rs | 34 +++-- src/lib.rs | 27 ++++ src/main.rs | 117 ++++++------------ src/{cmd/serve.rs => watch.rs} | 0 27 files changed, 259 insertions(+), 232 deletions(-) create mode 100644 src/buildsystem/assets.rs rename src/{cmd/build.rs => buildsystem/wasm.rs} (100%) delete mode 100644 src/cli.rs create mode 100644 src/cli/build/mod.rs create mode 100644 src/cli/cfg.rs create mode 100644 src/cli/clean/mod.rs create mode 100644 src/cli/config/mod.rs create mode 100644 src/cli/mod.rs rename src/{develop => cli/serve}/develop.rs (98%) rename src/{develop => cli/serve}/draw.rs (100%) rename src/{develop => cli/serve}/events.rs (100%) create mode 100644 src/cli/serve/mod.rs rename src/{develop => cli/serve}/studio.rs (100%) rename src/{helpers => cli/translate}/extract_svgs.rs (100%) create mode 100644 src/cli/translate/mod.rs rename src/{helpers => cli/translate}/to_component.rs (98%) rename src/{helpers => cli/translate}/translate.rs (100%) rename src/{cmd => cli/watch}/mod.rs (100%) delete mode 100644 src/cmd/studio.rs delete mode 100644 src/cmd/watch.rs create mode 100644 src/lib.rs rename src/{cmd/serve.rs => watch.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index 71bcbfc4d..02302fd89 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,13 +15,13 @@ fern = { version = "0.6.0", features = ["colored"] } wasm-bindgen-cli-support = "0.2.78" anyhow = "1.0.38" -serde = "1" +serde = { version = "1.0.133", features = ["derive"] } serde_json = "1" fs_extra = "1.2.0" cargo_toml = "0.10.0" futures = "0.3.12" -notify = "5.0.0-pre.4" +notify = "4.0.17" html_parser = "0.6.2" tui = { version = "0.16.0", features = ["crossterm"] } crossterm = "0.22.1" @@ -29,6 +29,7 @@ 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"] } [[bin]] path = "src/main.rs" diff --git a/README.md b/README.md index 055797dc1..079f663a3 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,3 @@ dioxus-studio (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. - -## Features - -Just install Rust, dioxus-cli, and you're good to go. -`cargo install --git github.com/jkelleyrtp/dioxus-cli` - -Need a development server? -`dioxus develop` - -Need to run an example? -`dioxus develop --example textbox` - diff --git a/src/builder.rs b/src/builder.rs index 96317beb2..b80c3dd36 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,5 +1,4 @@ use crate::{ - cli::BuildOptions, config::{CrateConfig, ExecutableType}, error::{Error, Result}, }; diff --git a/src/buildsystem/assets.rs b/src/buildsystem/assets.rs new file mode 100644 index 000000000..e35ac1005 --- /dev/null +++ b/src/buildsystem/assets.rs @@ -0,0 +1,4 @@ +/* + +todo: wasm splitting +*/ diff --git a/src/cmd/build.rs b/src/buildsystem/wasm.rs similarity index 100% rename from src/cmd/build.rs rename to src/buildsystem/wasm.rs diff --git a/src/cli.rs b/src/cli.rs deleted file mode 100644 index 6b4b0a58a..000000000 --- a/src/cli.rs +++ /dev/null @@ -1,101 +0,0 @@ -use argh::FromArgs; - -#[derive(FromArgs, PartialEq, Debug)] -/// Top-level command. -pub struct LaunchOptions { - #[argh(subcommand)] - pub command: LaunchCommand, -} - -/// The various kinds of commands that `wasm-pack` can execute. -#[derive(FromArgs, PartialEq, Debug, Clone)] -#[argh(subcommand)] -pub enum LaunchCommand { - Develop(DevelopOptions), - Build(BuildOptions), - Translate(TranslateOptions), - Test(TestOptions), - Publish(PublishOptions), - Studio(StudioOptions), -} - -/// Publish your yew application to Github Pages, Netlify, or S3 -#[derive(FromArgs, PartialEq, Debug, Clone)] -#[argh(subcommand, name = "publish")] -pub struct PublishOptions {} - -/// 🔬 test your yew application! -#[derive(FromArgs, PartialEq, Debug, Clone)] -#[argh(subcommand, name = "test")] -pub struct TestOptions { - /// an example in the crate - #[argh(option)] - pub example: Option, -} - -/// 🏗️ Build your yew application -#[derive(FromArgs, PartialEq, Debug, Clone)] -#[argh(subcommand, name = "build")] -pub struct BuildOptions { - /// the directory output - #[argh(option, short = 'o', default = "String::from(\"public\")")] - pub outdir: String, - - /// an example in the crate - #[argh(option)] - pub example: Option, - - /// develop in release mode - #[argh(switch, short = 'r')] - pub release: bool, - - /// hydrate the `dioxusroot` element with this content - #[argh(option, short = 'h')] - pub hydrate: Option, - - /// custom template - #[argh(option, short = 't')] - pub template: Option, -} - -/// 🛠 Start a development server -#[derive(FromArgs, PartialEq, Debug, Clone)] -#[argh(subcommand, name = "develop")] -pub struct DevelopOptions { - /// an example in the crate - #[argh(option)] - pub example: Option, - - /// develop in release mode - #[argh(switch, short = 'r')] - pub release: bool, - - /// hydrate the `dioxusroot` element with this content - #[argh(option, short = 'h')] - pub hydrate: Option, - - /// custom template - #[argh(option, short = 't')] - pub template: Option, -} - -/// 🛠 Translate some 3rd party template into rsx -#[derive(FromArgs, PartialEq, Debug, Clone)] -#[argh(subcommand, name = "translate")] -pub struct TranslateOptions { - /// an example in the crate - #[argh(option, short = 'f')] - pub file: Option, - - /// an example in the crate - #[argh(option, short = 't')] - pub text: Option, - - /// whether or not to jump - #[argh(switch, short = 'c')] - pub component: bool, -} -/// 🛠 Translate some 3rd party template into rsx -#[derive(FromArgs, PartialEq, Debug, Clone)] -#[argh(subcommand, name = "studio")] -pub struct StudioOptions {} diff --git a/src/cli/build/mod.rs b/src/cli/build/mod.rs new file mode 100644 index 000000000..adb233c33 --- /dev/null +++ b/src/cli/build/mod.rs @@ -0,0 +1,12 @@ +use crate::cfg::ConfigOptsBuild; +use anyhow::Result; +use std::path::PathBuf; +use structopt::StructOpt; + +/// Build the Rust WASM app and all of its assets. +#[derive(Clone, Debug, StructOpt)] +#[structopt(name = "build")] +pub struct Build { + #[structopt(flatten)] + pub build: ConfigOptsBuild, +} diff --git a/src/cli/cfg.rs b/src/cli/cfg.rs new file mode 100644 index 000000000..feab0e61f --- /dev/null +++ b/src/cli/cfg.rs @@ -0,0 +1,75 @@ +use anyhow::Result; +use std::path::PathBuf; +use structopt::StructOpt; + +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::str::FromStr; +use std::sync::Arc; + +/// Config options for the build system. +#[derive(Clone, Debug, Default, Deserialize, StructOpt)] +pub struct ConfigOptsBuild { + /// The index HTML file to drive the bundling process [default: index.html] + #[structopt(parse(from_os_str))] + pub target: Option, + + /// Build in release mode [default: false] + #[structopt(long)] + #[serde(default)] + pub release: bool, + + /// The output dir for all final assets [default: dist] + #[structopt(short, long, parse(from_os_str))] + pub dist: Option, + + /// The public URL from which assets are to be served [default: /] + #[structopt(long, parse(from_str=parse_public_url))] + pub public_url: Option, + + /// Optional pattern for the app loader script [default: None] + /// + /// Patterns should include the sequences `{base}`, `{wasm}`, and `{js}` in order to + /// properly load the application. Other sequences may be included corresponding + /// to key/value pairs provided in `pattern_params`. + /// + /// These values can only be provided via config file. + #[structopt(skip)] + #[serde(default)] + pub pattern_script: Option, + + /// Optional pattern for the app preload element [default: None] + /// + /// Patterns should include the sequences `{base}`, `{wasm}`, and `{js}` in order to + /// properly preload the application. Other sequences may be included corresponding + /// to key/value pairs provided in `pattern_params`. + /// + /// These values can only be provided via config file. + #[structopt(skip)] + #[serde(default)] + pub pattern_preload: Option, + + #[structopt(skip)] + #[serde(default)] + /// Optional replacement parameters corresponding to the patterns provided in + /// `pattern_script` and `pattern_preload`. + /// + /// When a pattern is being replaced with its corresponding value from this map, if the value is + /// prefixed with the symbol `@`, then the value is expected to be a file path, and the pattern + /// will be replaced with the contents of the target file. This allows insertion of some big JSON + /// state or even HTML files as a part of the `index.html` build. + /// + /// Trunk will automatically insert the `base`, `wasm` and `js` key/values into this map. In order + //// for the app to be loaded properly, the patterns `{base}`, `{wasm}` and `{js}` should be used + /// in `pattern_script` and `pattern_preload`. + /// + /// These values can only be provided via config file. + pub pattern_params: Option>, +} + +/// Ensure the given value for `--public-url` is formatted correctly. +pub fn parse_public_url(val: &str) -> String { + let prefix = if !val.starts_with('/') { "/" } else { "" }; + let suffix = if !val.ends_with('/') { "/" } else { "" }; + format!("{}{}{}", prefix, val, suffix) +} diff --git a/src/cli/clean/mod.rs b/src/cli/clean/mod.rs new file mode 100644 index 000000000..aeeedf523 --- /dev/null +++ b/src/cli/clean/mod.rs @@ -0,0 +1,9 @@ +use crate::cfg::ConfigOptsBuild; +use anyhow::Result; +use std::path::PathBuf; +use structopt::StructOpt; + +/// Build the Rust WASM app and all of its assets. +#[derive(Clone, Debug, StructOpt)] +#[structopt(name = "clean")] +pub struct Clean {} diff --git a/src/cli/config/mod.rs b/src/cli/config/mod.rs new file mode 100644 index 000000000..616c9bc78 --- /dev/null +++ b/src/cli/config/mod.rs @@ -0,0 +1,9 @@ +use crate::cfg::ConfigOptsBuild; +use anyhow::Result; +use std::path::PathBuf; +use structopt::StructOpt; + +/// Build the Rust WASM app and all of its assets. +#[derive(Clone, Debug, StructOpt)] +#[structopt(name = "config")] +pub struct Config {} diff --git a/src/cli/mod.rs b/src/cli/mod.rs new file mode 100644 index 000000000..55e722d80 --- /dev/null +++ b/src/cli/mod.rs @@ -0,0 +1,47 @@ +use anyhow::{Context, Result}; +use std::path::PathBuf; +use structopt::StructOpt; + +pub mod build; +pub mod cfg; +pub mod clean; +pub mod config; +pub mod serve; +pub mod translate; +pub mod watch; + +/// Build, bundle & ship your Rust WASM application to the web. +#[derive(StructOpt)] +#[structopt(name = "trunk")] +pub struct Trunk { + #[structopt(subcommand)] + pub action: TrunkSubcommands, + + /// Path to the Trunk config file [default: Trunk.toml] + #[structopt(long, parse(from_os_str), env = "TRUNK_CONFIG")] + pub config: Option, + + /// Enable verbose logging. + #[structopt(short)] + pub v: bool, +} + +#[derive(StructOpt)] +pub enum TrunkSubcommands { + /// Build the Rust WASM app and all of its assets. + Build(build::Build), + + /// Translate some source file into Dioxus code. + Translate(translate::Translate), + + /// Build, watch & serve the Rust WASM app and all of its assets. + /// + /// + Serve(serve::Serve), + + /// Clean output artifacts. + Clean(clean::Clean), + + /// Trunk config controls. + Config(config::Config), +} diff --git a/src/develop/develop.rs b/src/cli/serve/develop.rs similarity index 98% rename from src/develop/develop.rs rename to src/cli/serve/develop.rs index 2777880c4..dd386b14e 100644 --- a/src/develop/develop.rs +++ b/src/cli/serve/develop.rs @@ -44,12 +44,9 @@ async fn watch_directory(config: CrateConfig, is_err: ErrStatus) -> Result<()> { // Automatically select the best implementation for your platform. // You can also access each implementation directly e.g. INotifyWatcher. let mut watcher: RecommendedWatcher = Watcher::new(move |res| { -<<<<<<< HEAD async_std::task::block_on(watcher_tx.send(res)); -======= // send an event let _ = async_std::task::block_on(watcher_tx.send(res)); ->>>>>>> 9451713 (wip: studio upgrades) }) .expect("failed to make watcher"); diff --git a/src/develop/draw.rs b/src/cli/serve/draw.rs similarity index 100% rename from src/develop/draw.rs rename to src/cli/serve/draw.rs diff --git a/src/develop/events.rs b/src/cli/serve/events.rs similarity index 100% rename from src/develop/events.rs rename to src/cli/serve/events.rs diff --git a/src/cli/serve/mod.rs b/src/cli/serve/mod.rs new file mode 100644 index 000000000..9695870c0 --- /dev/null +++ b/src/cli/serve/mod.rs @@ -0,0 +1,9 @@ +use crate::cfg::ConfigOptsBuild; +use anyhow::Result; +use std::path::PathBuf; +use structopt::StructOpt; + +/// Build the Rust WASM app and all of its assets. +#[derive(Clone, Debug, StructOpt)] +#[structopt(name = "serve")] +pub struct Serve {} diff --git a/src/develop/studio.rs b/src/cli/serve/studio.rs similarity index 100% rename from src/develop/studio.rs rename to src/cli/serve/studio.rs diff --git a/src/helpers/extract_svgs.rs b/src/cli/translate/extract_svgs.rs similarity index 100% rename from src/helpers/extract_svgs.rs rename to src/cli/translate/extract_svgs.rs diff --git a/src/cli/translate/mod.rs b/src/cli/translate/mod.rs new file mode 100644 index 000000000..1251f9ae6 --- /dev/null +++ b/src/cli/translate/mod.rs @@ -0,0 +1,13 @@ +use crate::cfg::ConfigOptsBuild; +use anyhow::Result; +use std::path::PathBuf; +use structopt::StructOpt; + +pub mod extract_svgs; +pub mod to_component; +pub mod translate; + +/// Build the Rust WASM app and all of its assets. +#[derive(Clone, Debug, StructOpt)] +#[structopt(name = "translate")] +pub struct Translate {} diff --git a/src/helpers/to_component.rs b/src/cli/translate/to_component.rs similarity index 98% rename from src/helpers/to_component.rs rename to src/cli/translate/to_component.rs index 8643e1c77..b08161e9c 100644 --- a/src/helpers/to_component.rs +++ b/src/cli/translate/to_component.rs @@ -169,7 +169,7 @@ fn write_tabs(f: &mut Formatter, num: u32) -> std::fmt::Result { #[test] fn generates_svgs() { - let st = include_str!("../../tests/svg.html"); + let st = include_str!("../../../tests/svg.html"); let out = format!("{:}", convert_html_to_component(st).unwrap()); dbg!(&out); diff --git a/src/helpers/translate.rs b/src/cli/translate/translate.rs similarity index 100% rename from src/helpers/translate.rs rename to src/cli/translate/translate.rs diff --git a/src/cmd/mod.rs b/src/cli/watch/mod.rs similarity index 100% rename from src/cmd/mod.rs rename to src/cli/watch/mod.rs diff --git a/src/cmd/studio.rs b/src/cmd/studio.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/cmd/watch.rs b/src/cmd/watch.rs deleted file mode 100644 index ae39bc670..000000000 --- a/src/cmd/watch.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub struct Watcher {} - -impl Watcher { - // Spawns a new notify instance that alerts us of changes - pub fn new() -> Self { - Self {} - } - - /// Subsribe to the watcher - pub fn subscribe() {} -} diff --git a/src/config.rs b/src/config.rs index 754d1043c..47920c583 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,8 +1,4 @@ -use crate::{ - cli::{BuildOptions, DevelopOptions}, - error::Result, - LaunchCommand, -}; +use crate::error::Result; use std::{io::Write, path::PathBuf, process::Command}; #[derive(Debug, Clone)] @@ -75,19 +71,19 @@ impl CrateConfig { self } - pub fn with_build_options(&mut self, options: &BuildOptions) { - if let Some(name) = &options.example { - self.as_example(name.clone()); - } - self.release = options.release; - self.out_dir = options.outdir.clone().into(); - } + // pub fn with_build_options(&mut self, options: &BuildOptions) { + // if let Some(name) = &options.example { + // self.as_example(name.clone()); + // } + // self.release = options.release; + // self.out_dir = options.outdir.clone().into(); + // } - pub fn with_develop_options(&mut self, options: &DevelopOptions) { - if let Some(name) = &options.example { - self.as_example(name.clone()); - } - self.release = options.release; - self.out_dir = tempfile::Builder::new().tempdir().expect("").into_path(); - } + // pub fn with_develop_options(&mut self, options: &DevelopOptions) { + // if let Some(name) = &options.example { + // self.as_example(name.clone()); + // } + // self.release = options.release; + // self.out_dir = tempfile::Builder::new().tempdir().expect("").into_path(); + // } } diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 000000000..4cc4f2d75 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,27 @@ +pub mod builder; +pub use builder::*; + +pub mod cargo; +pub use cargo::*; + +pub mod cli; +pub use cli::*; + +pub mod config; +pub use config::*; + +pub mod error; +pub use error::*; + +pub mod logging; +pub use logging::*; + +pub mod watch; + +pub mod buildsystem { + pub mod wasm; + pub use wasm::*; + + pub mod assets; + pub use assets::*; +} diff --git a/src/main.rs b/src/main.rs index a36413dd9..043767af6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,97 +1,50 @@ -mod builder; -mod cargo; -mod cli; -mod config; -mod error; -mod logging; -mod helpers { - pub mod extract_svgs; - pub mod to_component; - pub mod translate; -} - -mod watch; -mod develop { - pub mod develop; - pub mod draw; - pub mod events; - pub mod studio; -} - -use std::path::PathBuf; +use dioxus_studio::*; use structopt::StructOpt; -#[async_std::main] +#[tokio::main] async fn main() -> Result<()> { + let args = Trunk::from_args(); set_up_logging(); - let args = Args::from_args(); - match args.command { - LaunchCommand::Develop(cfg) => { - develop::develop::develop(cfg).await?; - } - // LaunchCommand::Develop(cfg) => develop::studio::start(cfg).await?, - LaunchCommand::Build(opts) => { - let mut cfg = CrateConfig::new()?; - cfg.with_build_options(&opts); - builder::build(&cfg)?; + match args.action { + TrunkSubcommands::Build(_) => { + // } - LaunchCommand::Translate(cfg) => { - let TranslateOptions { - file, - text, - component, - } = cfg; + TrunkSubcommands::Translate(opts) => { + // let TranslateOptions { + // file, + // text, + // component, + // } = cfg; - match component { - true => { - let f = helpers::to_component::convert_html_to_component(&text.unwrap())?; - println!("{}", f); - } - false => { - let renderer = match (file, text) { - (None, Some(text)) => translate::translate_from_html_to_rsx(&text, false)?, - (Some(file), None) => translate::translate_from_html_file(&file)?, - _ => panic!("Must select either file or text - not both or none!"), - }; + // match component { + // true => { + // let f = helpers::to_component::convert_html_to_component(&text.unwrap())?; + // println!("{}", f); + // } + // false => { + // let renderer = match (file, text) { + // (None, Some(text)) => translate::translate_from_html_to_rsx(&text, false)?, + // (Some(file), None) => translate::translate_from_html_file(&file)?, + // _ => panic!("Must select either file or text - not both or none!"), + // }; - println!("{}", renderer); - } - } + // println!("{}", renderer); + // } + // } } - _ => { - todo!("Those commands are not yet supported"); + + TrunkSubcommands::Clean(_) => { + // + } + TrunkSubcommands::Config(_) => { + // + } + TrunkSubcommands::Serve(_) => { + // } } Ok(()) } - -/// Build, bundle & ship your Rust WASM application to the web. -#[derive(StructOpt)] -#[structopt(name = "trunk")] -struct Args { - #[structopt(subcommand)] - command: TrunkSubcommands, - /// Path to the Trunk config file [default: Trunk.toml] - #[structopt(long, parse(from_os_str), env = "TRUNK_CONFIG")] - pub config: Option, - /// Enable verbose logging. - #[structopt(short)] - pub v: bool, -} - -#[derive(StructOpt)] -enum TrunkSubcommands { - /// Build the Rust WASM app and all of its assets. - Build(cmd::build::Build), - /// Build & watch the Rust WASM app and all of its assets. - Watch(cmd::watch::Watch), - /// Build, watch & serve the Rust WASM app and all of its assets. - Serve(cmd::serve::Serve), - /// Clean output artifacts. - Clean(cmd::clean::Clean), - /// Trunk config controls. - Config(cmd::config::Config), -} diff --git a/src/cmd/serve.rs b/src/watch.rs similarity index 100% rename from src/cmd/serve.rs rename to src/watch.rs