Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

complete: metassr-create #6

Merged
merged 6 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading