Skip to content

Commit

Permalink
Merge pull request #6 from metacall/metassr-create
Browse files Browse the repository at this point in the history
complete: metassr-create
  • Loading branch information
hulxv authored Aug 21, 2024
2 parents 80244af + 3785f5f commit 1efbb9e
Show file tree
Hide file tree
Showing 18 changed files with 463 additions and 592 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ html-generator = { path = "crates/html-generator" }
serde = "1.0.207"
tower-layer = "0.3.3"
tower-service = "0.3.3"
metassr-create = { version = "0.1.0", path = "crates/metassr-create" }

[workspace]
members = [
Expand Down
1 change: 1 addition & 0 deletions crates/metassr-create/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests
3 changes: 3 additions & 0 deletions crates/metassr-create/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ build = "build.rs"

[build-dependencies]
walkdir = "2.5.0"

[dependencies]
anyhow = "1.0.86"
6 changes: 3 additions & 3 deletions crates/metassr-create/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn main() {

generated_code.push_str("use std::collections::HashMap;\n\n");
generated_code
.push_str("pub fn load_templates() -> HashMap<String, HashMap<String, String>> {\n");
.push_str("pub fn load_templates() -> HashMap<String, HashMap<String, Vec<u8>>> {\n");
generated_code.push_str(" let mut templates = HashMap::new();\n");

for entry in WalkDir::new(templates_dir)
Expand All @@ -30,10 +30,10 @@ fn main() {
.join("/");

generated_code.push_str(&format!(
" templates.entry(\"{}\".to_string()).or_insert_with(HashMap::new).insert(\"{}\".to_string(), include_str!(r#\"{}\"#).to_string());\n",
" templates.entry(\"{}\".to_string()).or_insert_with(HashMap::new).insert(\"{}\".to_string(), include_bytes!(r#\"{}\"#).to_vec());\n",
template_name,
file_name,
path.display()
path.canonicalize().unwrap().display()
));
}

Expand Down
114 changes: 107 additions & 7 deletions crates/metassr-create/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,114 @@
pub fn add(left: usize, right: usize) -> usize {
left + right
include!(concat!(env!("OUT_DIR"), "/templates.rs"));

use std::{
fs::{create_dir_all, File},
io::Write,
path::PathBuf,
};

use anyhow::{anyhow, Result};
use templates::Template;

mod templates;

pub mod tags {
pub const VERSION: &str = "%VER%";
pub const NAME: &str = "%NAME%";
pub const DESC: &str = "%DESC%";
}

pub struct Creator {
project_name: String,
version: String,
description: String,
template: Template,
}
impl Creator {
pub fn new(project_name: &str, version: &str, desc: &str, template: &str) -> Self {
Self {
project_name: project_name.to_string(),
version: version.to_string(),
description: desc.to_string(),
template: Template::from(template),
}
}
pub fn generate(&self) -> Result<()> {
let template = self.template.load(&self)?;

Check warning on line 36 in crates/metassr-create/src/lib.rs

View workflow job for this annotation

GitHub Actions / clippy

this expression creates a reference which is immediately dereferenced by the compiler

warning: this expression creates a reference which is immediately dereferenced by the compiler --> crates/metassr-create/src/lib.rs:36:43 | 36 | let template = self.template.load(&self)?; | ^^^^^ help: change this to: `self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#needless_borrow = note: `#[warn(clippy::needless_borrow)]` on by default
let root = PathBuf::from(&self.project_name);

if root.exists() {
return Err(anyhow!("Path already exists."));
}
for (file, buf) in template {
let path = root.join(&file);
create_dir_all(path.parent().unwrap())?;

let _ = File::create(path)?.write(&buf)?;
}

Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;
mod test {
use crate::{tags, Creator};
use anyhow::Result;
use std::{
env::set_current_dir,
fs::create_dir,
path::Path,
str::from_utf8,
time::{SystemTime, UNIX_EPOCH},
};

fn init_test_dir() -> Result<()> {
let path = Path::new("tests");
if !path.exists() {
create_dir(path)?;
}
set_current_dir(path)?;
Ok(())
}

include!(concat!(env!("OUT_DIR"), "/templates.rs"));
#[test]
fn load_template() {
dbg!(&from_utf8(
load_templates()
.get("typescript")
.unwrap()
.get("src/_head.tsx")
.unwrap()
)
.unwrap()
.replace(tags::VERSION, "1.0.0")
.replace(tags::NAME, "MetaSSR"));
}
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
fn generate_templates() -> Result<()> {
init_test_dir()?;
let project_name = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
.to_string();
dbg!(&project_name);
Creator::new(
&format!("{}-javascript", project_name),
"1.0.0",
"Hello World!",
"js",
)
.generate()?;
Creator::new(
&format!("{}-typescript", project_name),
"1.0.0",
"Hello World!",
"ts",
)
.generate()?;

Ok(())
}
}
55 changes: 55 additions & 0 deletions crates/metassr-create/src/templates.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use crate::{load_templates, tags, Creator};
use anyhow::Result;
use std::{collections::HashMap, str::from_utf8};

pub enum Template {
Javascript,
Typescript,
}

impl From<&str> for Template {
fn from(value: &str) -> Self {
match value.to_lowercase().as_str() {
"javascript" | "js" => Self::Javascript,
"typescript" | "ts" => Self::Typescript,
_ => unreachable!("Template isn't detected."),
}
}
}

impl ToString for Template {
fn to_string(&self) -> String {
match *self {
Self::Javascript => "javascript",
Self::Typescript => "typescript",
}
.to_string()
}
}

Check warning on line 28 in crates/metassr-create/src/templates.rs

View workflow job for this annotation

GitHub Actions / clippy

direct implementation of `ToString`

warning: direct implementation of `ToString` --> crates/metassr-create/src/templates.rs:20:1 | 20 | / impl ToString for Template { 21 | | fn to_string(&self) -> String { 22 | | match *self { 23 | | Self::Javascript => "javascript", ... | 27 | | } 28 | | } | |_^ | = help: prefer implementing `Display` instead = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#to_string_trait_impl = note: `#[warn(clippy::to_string_trait_impl)]` on by default

impl Template {
pub fn load(&self, creator: &Creator) -> Result<HashMap<String, Vec<u8>>> {
let template = load_templates();
let template = template.get(&self.to_string()).unwrap();
let mut template = template.clone();
let package_json = from_utf8(template.get("package.json").unwrap())?
.replace(tags::NAME, &creator.project_name)
.replace(tags::VERSION, &creator.version)
.replace(tags::DESC, &creator.description)
.as_bytes()
.to_vec();
template.insert("package.json".to_string(), package_json);
let ext = match *self {
Template::Javascript => "jsx",
Template::Typescript => "tsx",
};
let head = from_utf8(template.get(&format!("src/_head.{ext}")).unwrap())?
.replace(tags::NAME, &creator.project_name)
.replace(tags::VERSION, &creator.version)
.as_bytes()
.to_vec();
template.insert(format!("src/_head.{ext}"), head);

Ok(template)
}
}
Loading

0 comments on commit 1efbb9e

Please sign in to comment.