feat: init use cargo-generate
This commit is contained in:
1 parent
7343af2089
commit
bdcc06648b
8 files changed
+74
-103
No files matched your search
+2
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "dioxus-cli"
|
name = "dioxus-cli"
|
||||||
version = "0.1.1"
|
version = "0.1.2"
|
||||||
authors = ["Jonathan Kelley"]
|
authors = ["Jonathan Kelley"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "CLI tool for developing, testing, and publishing Dioxus apps"
|
description = "CLI tool for developing, testing, and publishing Dioxus apps"
|
||||||
@@ -28,6 +28,7 @@ structopt = "0.3.25"
|
|||||||
cargo_metadata = "0.14.1"
|
cargo_metadata = "0.14.1"
|
||||||
tokio = { version = "1.15.0", features = ["full"] }
|
tokio = { version = "1.15.0", features = ["full"] }
|
||||||
atty = "0.2.14"
|
atty = "0.2.14"
|
||||||
|
regex = "1.5.4"
|
||||||
|
|
||||||
axum = { version = "0.4.4", features = ["ws", "headers"] }
|
axum = { version = "0.4.4", features = ["ws", "headers"] }
|
||||||
tower-http = { version = "0.2.0", features = ["fs", "trace"] }
|
tower-http = { version = "0.2.0", features = ["fs", "trace"] }
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ platforms = ["web"]
|
|||||||
out_dir = "dist"
|
out_dir = "dist"
|
||||||
|
|
||||||
# resource (static) file folder
|
# resource (static) file folder
|
||||||
static_dir = "static"
|
public_dir = "public"
|
||||||
|
|
||||||
[web.watcher]
|
[web.watcher]
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ impl Build {
|
|||||||
// change the relase state.
|
// change the relase state.
|
||||||
crate_config.with_release(self.build.release);
|
crate_config.with_release(self.build.release);
|
||||||
|
|
||||||
|
if self.build.example.is_some() {
|
||||||
|
crate_config.as_example(self.build.example.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
crate::builder::build(&crate_config)?;
|
crate::builder::build(&crate_config)?;
|
||||||
|
|
||||||
let temp = gen_page(&crate_config.dioxus_config, false);
|
let temp = gen_page(&crate_config.dioxus_config, false);
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ pub struct ConfigOptsBuild {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub release: bool,
|
pub release: bool,
|
||||||
|
|
||||||
|
/// Build a example [default: ""]
|
||||||
|
#[structopt(long)]
|
||||||
|
pub example: Option<String>,
|
||||||
|
|
||||||
/// Optional pattern for the app loader script [default: None]
|
/// Optional pattern for the app loader script [default: None]
|
||||||
///
|
///
|
||||||
/// Patterns should include the sequences `{base}`, `{wasm}`, and `{js}` in order to
|
/// Patterns should include the sequences `{base}`, `{wasm}`, and `{js}` in order to
|
||||||
@@ -62,6 +66,10 @@ pub struct ConfigOptsServe {
|
|||||||
#[structopt(parse(from_os_str))]
|
#[structopt(parse(from_os_str))]
|
||||||
pub target: Option<PathBuf>,
|
pub target: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// Build a example [default: ""]
|
||||||
|
#[structopt(long)]
|
||||||
|
pub example: Option<String>,
|
||||||
|
|
||||||
/// Build in release mode [default: false]
|
/// Build in release mode [default: false]
|
||||||
#[structopt(long)]
|
#[structopt(long)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|||||||
+54
-43
@@ -1,16 +1,18 @@
|
|||||||
use std::{
|
use std::{
|
||||||
fs::{File, OpenOptions},
|
fs::File,
|
||||||
io::Write,
|
io::{Read, Write},
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
process::{Command, Stdio},
|
process::{Command, Stdio},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
use serde::Deserialize;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
use crate::error::{Error, Result};
|
use crate::{error::Result, Error};
|
||||||
|
|
||||||
/// Build the Rust WASM app and all of its assets.
|
/// Build the Rust WASM app and all of its assets.
|
||||||
#[derive(Clone, Debug, StructOpt)]
|
#[derive(Clone, Debug, Default, Deserialize, StructOpt)]
|
||||||
#[structopt(name = "init")]
|
#[structopt(name = "init")]
|
||||||
pub struct Init {
|
pub struct Init {
|
||||||
/// Init project name
|
/// Init project name
|
||||||
@@ -18,69 +20,73 @@ pub struct Init {
|
|||||||
name: String,
|
name: String,
|
||||||
|
|
||||||
/// Template path
|
/// Template path
|
||||||
#[structopt(default_value = "default", long)]
|
#[structopt(default_value = "gh:dioxuslabs/dioxus-template", long)]
|
||||||
template: String,
|
template: String,
|
||||||
|
|
||||||
|
/// Create a `lib` project, include a `hello-world` example.
|
||||||
|
#[structopt(long)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub lib: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Init {
|
impl Init {
|
||||||
pub fn init(self) -> Result<()> {
|
pub fn init(self) -> Result<()> {
|
||||||
if self.name.contains(".") {
|
if Self::name_vaild_check(self.name.clone()) {
|
||||||
log::error!("❗Unsupported project name.");
|
log::error!("❗Unsupported project name.");
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("🔧 Start to init a new project '{}'.", self.name);
|
|
||||||
|
|
||||||
let project_path = PathBuf::from(&self.name);
|
let project_path = PathBuf::from(&self.name);
|
||||||
|
|
||||||
if project_path.join("Cargo.toml").is_file() {
|
if project_path.join("Dioxus.toml").is_file() || project_path.join("Cargo.toml").is_file() {
|
||||||
log::warn!("Folder '{}' is initialized.", self.name);
|
return Err(Error::Other(anyhow::anyhow!(
|
||||||
return Ok(());
|
"🧨 Folder '{}' is initialized.",
|
||||||
|
&self.name
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log::info!("🔧 Start to init a new project '{}'.", self.name);
|
||||||
|
|
||||||
let output = Command::new("cargo")
|
let output = Command::new("cargo")
|
||||||
.arg("init")
|
.arg("generate")
|
||||||
.arg(&format!("./{}", self.name))
|
.arg("--help")
|
||||||
.arg("--bin")
|
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
.output()?;
|
.output()?;
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return Err(Error::CargoError("Cargo init failed".into()));
|
log::warn!("Tool is not installed: cargo-generate, try to install it.");
|
||||||
|
let install_output = Command::new("cargo")
|
||||||
|
.arg("install")
|
||||||
|
.arg("cargo-generate")
|
||||||
|
.stdout(Stdio::inherit())
|
||||||
|
.stderr(Stdio::inherit())
|
||||||
|
.output()?;
|
||||||
|
if !install_output.status.success() {
|
||||||
|
return Err(Error::Other(anyhow::anyhow!(
|
||||||
|
"Try to install cargo-generate failed."
|
||||||
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the template code
|
let generate_output = Command::new("cargo")
|
||||||
let template_str = match self.template {
|
.arg("generate")
|
||||||
_ => include_str!("../../template/default.rs"),
|
.arg(&self.template)
|
||||||
};
|
.arg("--name")
|
||||||
|
.arg(&self.name)
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.stderr(Stdio::inherit())
|
||||||
|
.output()?;
|
||||||
|
|
||||||
let main_rs_file = project_path.join("src").join("main.rs");
|
if !generate_output.status.success() {
|
||||||
if !main_rs_file.is_file() {
|
return Err(Error::Other(anyhow::anyhow!("Generate project failed.")));
|
||||||
return Err(Error::FailedToWrite);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut file = File::create(main_rs_file)?;
|
let mut dioxus_file = File::open(project_path.join("Dioxus.toml"))?;
|
||||||
file.write_all(&template_str.as_bytes())?;
|
let mut meta_file = String::new();
|
||||||
|
dioxus_file.read_to_string(&mut meta_file)?;
|
||||||
let mut file = File::create(project_path.join("Dioxus.toml"))?;
|
meta_file = meta_file.replace("{{project-name}}", &self.name);
|
||||||
let dioxus_conf = String::from(include_str!("../../template/config.toml"))
|
File::create(project_path.join("Dioxus.toml"))?.write_all(meta_file.as_bytes())?;
|
||||||
.replace("{project-name}", &self.name);
|
|
||||||
file.write_all(dioxus_conf.as_bytes())?;
|
|
||||||
|
|
||||||
// log::info!("🎯 Project initialization completed.");
|
|
||||||
|
|
||||||
if !Command::new("cargo")
|
|
||||||
.args(["add", "dioxus", "--features web"])
|
|
||||||
.output()?
|
|
||||||
.status
|
|
||||||
.success()
|
|
||||||
{
|
|
||||||
let mut file = OpenOptions::new()
|
|
||||||
.append(true)
|
|
||||||
.open(project_path.join("Cargo.toml"))?;
|
|
||||||
file.write_all("dioxus = { version = \"0.1.7\", features = [\"web\"] }".as_bytes())?;
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("");
|
println!("");
|
||||||
log::info!("💡 Project initialized:");
|
log::info!("💡 Project initialized:");
|
||||||
@@ -89,4 +95,9 @@ impl Init {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn name_vaild_check(name: String) -> bool {
|
||||||
|
let r = Regex::new(r"^[a-zA-Z][a-zA-Z0-9\-_]$").unwrap();
|
||||||
|
r.is_match(&name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -13,9 +13,14 @@ pub struct Serve {
|
|||||||
impl Serve {
|
impl Serve {
|
||||||
pub async fn serve(self) -> anyhow::Result<()> {
|
pub async fn serve(self) -> anyhow::Result<()> {
|
||||||
let mut crate_config = crate::CrateConfig::new()?;
|
let mut crate_config = crate::CrateConfig::new()?;
|
||||||
|
|
||||||
// change the relase state.
|
// change the relase state.
|
||||||
crate_config.with_release(self.serve.release);
|
crate_config.with_release(self.serve.release);
|
||||||
|
|
||||||
|
if self.serve.example.is_some() {
|
||||||
|
crate_config.as_example(self.serve.example.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
crate::builder::build(&crate_config).expect("build failed");
|
crate::builder::build(&crate_config).expect("build failed");
|
||||||
|
|
||||||
// generate dev-index page
|
// generate dev-index page
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
[application]
|
|
||||||
|
|
||||||
# App (Project) Name
|
|
||||||
name = "{project-name}"
|
|
||||||
|
|
||||||
# Dioxus App Support Platform
|
|
||||||
# desktop, web, mobile, ssr
|
|
||||||
platforms = ["web"]
|
|
||||||
|
|
||||||
[web.app]
|
|
||||||
|
|
||||||
# HTML title tag content
|
|
||||||
title = "dioxus | ⛺"
|
|
||||||
|
|
||||||
# Web `build` & `serve` dist path
|
|
||||||
out_dir = "dist"
|
|
||||||
|
|
||||||
# resource (public) file folder
|
|
||||||
public_dir = "public"
|
|
||||||
|
|
||||||
[web.watcher]
|
|
||||||
|
|
||||||
# when watcher trigger, regenerate the `index.html`
|
|
||||||
reload_html = true
|
|
||||||
|
|
||||||
# which files or dirs will be watcher monitoring
|
|
||||||
watch_path = ["src"]
|
|
||||||
|
|
||||||
# include `assets` in web platform
|
|
||||||
[web.resource]
|
|
||||||
|
|
||||||
# CSS style file
|
|
||||||
style = []
|
|
||||||
|
|
||||||
# Javascript code file
|
|
||||||
script = []
|
|
||||||
|
|
||||||
[web.resource.dev]
|
|
||||||
|
|
||||||
# Javascript code file
|
|
||||||
# serve: [dev-server] only
|
|
||||||
script = []
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
use dioxus::prelude::*;
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
dioxus::web::launch(app);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
|
||||||
cx.render(rsx! (
|
|
||||||
div {
|
|
||||||
style: "text-align: center;",
|
|
||||||
h1 { "🌗 Dioxus 🚀" }
|
|
||||||
h3 { "Frontend that scales." }
|
|
||||||
p { "Dioxus is a portable, performant, and ergonomic framework for building cross-platform user interfaces in Rust." }
|
|
||||||
}
|
|
||||||
))
|
|
||||||
}
|
|
||||||
Reference in new issue
Block a user