Skip to content

Commit

Permalink
support clientside
Browse files Browse the repository at this point in the history
  • Loading branch information
jondot committed Nov 13, 2024
1 parent 0abe489 commit 01fd0ec
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 25 deletions.
10 changes: 10 additions & 0 deletions loco-new/setup.rhai
Original file line number Diff line number Diff line change
Expand Up @@ -105,3 +105,13 @@ if background {
if asset {
gen.copy_dir("assets"); // Static assets directory
}


// =====================
// Client side
// =====================

if settings.clientside {
gen.copy_dir("frontend");
gen.create_file("frontend/dist/index.html", "this is a placeholder. please run your frontend build (npm build)");
}
33 changes: 29 additions & 4 deletions loco-new/src/generator/executer/filesystem.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use super::Executer;
use crate::{generator, settings::Settings};
use fs_extra::file::{move_file, write_all};
use std::path::{Path, PathBuf};

use fs_extra::file::{move_file, write_all};
use walkdir::WalkDir;

use super::Executer;
use crate::{generator, settings::Settings};

#[derive(Debug, Default, Clone)]
pub struct FileSystem {
pub source_dir: PathBuf,
Expand Down Expand Up @@ -83,6 +85,28 @@ impl Executer for FileSystem {
Ok(target_path)
}

fn create_file(&self, path: &Path, content: String) -> super::Result<PathBuf> {
let target_path = self.target_dir.join(path);
if let Some(parent) = path.parent() {
fs_extra::dir::create_all(parent, false)?;
}

let span = tracing::info_span!("create_file", target_path = %target_path.display());
let _guard = span.enter();

tracing::debug!("starting file copy operation");

fs_extra::dir::create_all(target_path.parent().unwrap(), false).map_err(|error| {
tracing::debug!(error = %error, "error creating target parent directory");
error
})?;

fs_extra::file::write_all(&target_path, &content)?;
tracing::debug!("file created successfully");

Ok(target_path)
}

fn copy_dir(&self, directory_path: &Path) -> super::Result<()> {
let source_path = self.source_dir.join(directory_path);
let target_path = self.target_dir.join(directory_path);
Expand Down Expand Up @@ -144,9 +168,10 @@ impl Executer for FileSystem {

#[cfg(test)]
mod tests {
use super::*;
use tree_fs::TreeBuilder;

use super::*;

fn init_filesystem() -> FileSystem {
let source_path = TreeBuilder::default()
.add("test/foo.txt", "bar")
Expand Down
16 changes: 14 additions & 2 deletions loco-new/src/generator/executer/inmem.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use std::{
collections::BTreeMap,
path::{Path, PathBuf},
sync::Mutex,
};

use super::Executer;
use crate::{generator, settings::Settings};
use std::path::{Path, PathBuf};
use std::{collections::BTreeMap, sync::Mutex};

pub struct Inmem {
pub source_path: PathBuf,
Expand Down Expand Up @@ -45,6 +49,14 @@ impl Executer for Inmem {
Ok(file_path.to_path_buf())
}

fn create_file(&self, path: &Path, content: String) -> super::Result<PathBuf> {
self.file_store
.lock()
.unwrap()
.insert(path.to_path_buf(), content);
Ok(path.to_path_buf())
}

fn copy_dir(&self, directory_path: &Path) -> super::Result<()> {
let directory_content = fs_extra::dir::get_dir_content(directory_path)?;
for file in directory_content.files {
Expand Down
28 changes: 20 additions & 8 deletions loco-new/src/generator/executer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
use crate::settings::Settings;
mod filesystem;
mod inmem;
use std::path::{Path, PathBuf};

pub use filesystem::FileSystem;
pub use inmem::Inmem;
#[cfg(test)]
use mockall::{automock, predicate::*};
use std::path::{Path, PathBuf};

pub type Result<T> = std::result::Result<T, Error>;

Expand Down Expand Up @@ -41,29 +42,40 @@ pub trait Executer: Send + Sync {
///
/// # Errors
///
/// Returns an error if the file cannot be copied, such as if the path is invalid
/// or if a file system error occurs.
/// Returns an error if the file cannot be copied, such as if the path is
/// invalid or if a file system error occurs.
fn copy_file(&self, path: &Path) -> Result<PathBuf>;

/// Copies a single file from the specified path.
///
/// # Errors
///
/// Returns an error if the file cannot be copied, such as if the path is
/// invalid or if a file system error occurs.
fn create_file(&self, path: &Path, content: String) -> Result<PathBuf>;

/// Copies an entire directory from the specified path.
///
/// # Errors
///
/// Returns an error if the directory cannot be copied, such as if the path is invalid
/// or if a file system error occurs.
/// Returns an error if the directory cannot be copied, such as if the path
/// is invalid or if a file system error occurs.
fn copy_dir(&self, path: &Path) -> Result<()>;

/// Copies a template file from the specified path, applying settings.
///
/// # Errors
///
/// Returns an error if the template cannot be copied or if any settings-related error occurs.
/// Returns an error if the template cannot be copied or if any
/// settings-related error occurs.
fn copy_template(&self, path: &Path, data: &Settings) -> Result<()>;

/// Copies an entire template directory from the specified path, applying settings.
/// Copies an entire template directory from the specified path, applying
/// settings.
///
/// # Errors
///
/// Returns an error if the template directory cannot be copied or if any settings-related error occurs.
/// Returns an error if the template directory cannot be copied or if any
/// settings-related error occurs.
fn copy_template_dir(&self, path: &Path, data: &Settings) -> Result<()>;
}
48 changes: 37 additions & 11 deletions loco-new/src/generator/mod.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
//! This module defines the `Generator` struct, which is responsible for executing
//! scripted commands for file and template operations. It integrates with an
//! executor to perform file manipulations and uses a scripting engine to run
//! custom scripts based on application settings.
//! This module defines the `Generator` struct, which is responsible for
//! executing scripted commands for file and template operations. It integrates
//! with an executor to perform file manipulations and uses a scripting engine
//! to run custom scripts based on application settings.
use std::path::{Path, PathBuf};
pub mod executer;
pub mod template;
use crate::settings;
use std::sync::Arc;

use include_dir::{include_dir, Dir};
use rhai::{Engine, Scope};
use std::sync::Arc;

use crate::settings;

static APP_TEMPLATE: Dir<'_> = include_dir!("loco-new/base_template");

/// Extracts a default template to a temporary directory for use by the application.
/// Extracts a default template to a temporary directory for use by the
/// application.
///
/// # Errors
/// when could not extract the the base template
Expand All @@ -29,8 +32,9 @@ pub fn extract_default_template() -> std::io::Result<PathBuf> {
Ok(generator_tmp_folder)
}

/// The `Generator` struct provides functionality to execute scripted operations,
/// such as copying files and templates, based on the current settings.
/// The `Generator` struct provides functionality to execute scripted
/// operations, such as copying files and templates, based on the current
/// settings.
#[derive(Clone)]
pub struct Generator {
pub executer: Arc<dyn executer::Executer>,
Expand Down Expand Up @@ -68,6 +72,7 @@ impl Generator {
.build_type::<settings::Settings>()
.build_type::<settings::Initializers>()
.register_fn("copy_file", Self::copy_file)
.register_fn("create_file", Self::create_file)
.register_fn("copy_files", Self::copy_files)
.register_fn("copy_dir", Self::copy_dir)
.register_fn("copy_dirs", Self::copy_dirs)
Expand Down Expand Up @@ -107,6 +112,25 @@ impl Generator {
Ok(())
}

pub fn create_file(
&mut self,
path: &str,
content: &str,
) -> Result<(), Box<rhai::EvalAltResult>> {
let span = tracing::info_span!("create_file", path);
let _guard = span.enter();

self.executer
.create_file(Path::new(path), content.to_string())
.map_err(|err| {
Box::new(rhai::EvalAltResult::ErrorSystem(
"create_file".to_string(),
err.into(),
))
})?;
Ok(())
}

/// Copies list of files from the specified path.
///
/// # Errors
Expand Down Expand Up @@ -184,7 +208,8 @@ impl Generator {
})
}

/// Copies an entire template directory from the specified path, applying settings.
/// Copies an entire template directory from the specified path, applying
/// settings.
///
/// # Errors
///
Expand All @@ -205,10 +230,11 @@ impl Generator {

#[cfg(test)]
mod tests {
use super::*;
use executer::MockExecuter;
use mockall::predicate::*;

use super::*;

#[test]
pub fn can_copy_file() {
let mut executor = MockExecuter::new();
Expand Down
3 changes: 3 additions & 0 deletions loco-new/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub struct Settings {
pub asset: Option<Asset>,
pub auth: bool,
pub mailer: bool,
pub clientside: bool,
pub initializers: Option<Initializers>,
pub features: Features,
pub loco_version_text: String,
Expand Down Expand Up @@ -75,6 +76,7 @@ impl Settings {
db: prompt_selection.db.clone().into(),
background: prompt_selection.background.clone().into(),
asset: prompt_selection.asset.clone().into(),
clientside: prompt_selection.asset.enable(),
initializers: if prompt_selection.asset.enable() {
Some(Initializers { view_engine: true })
} else {
Expand All @@ -95,6 +97,7 @@ impl Default for Settings {
asset: Default::default(),
auth: Default::default(),
mailer: Default::default(),
clientside: Default::default(),
initializers: Default::default(),
features: Default::default(),
loco_version_text: get_loco_version_text(),
Expand Down

0 comments on commit 01fd0ec

Please sign in to comment.