Skip to content
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
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ name = "tb"
path = "src/main.rs"

[dependencies]
boa_engine = "0.21.0"
chrono = "0.4.40"
clap = { version = "4.5.32", features = ["cargo", "unstable-doc"] }
config = "0.15.19"
confy = "2.0.0"
console = "0.15.11"
dialoguer = { version = "0.10.4", features = ["fuzzy-select", "completion"] }
dialoguer = { version = "0.10.4", features = ["fuzzy-select", "completion", "editor"] }
dirs = "5.0.1"
include_dir = "0.7.4"
lazy_static = "1.5.0"
Expand Down
1 change: 1 addition & 0 deletions scripts/create-justfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# create Justfile for Server, Tauri and Custom setup
28 changes: 26 additions & 2 deletions src/commands/script.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
use clap::{arg, Command};
use clap::{arg, Arg, Command};

pub fn script_command() -> Command {
let configure_scripts_cmd = Command::new("configure")
.about("configure the script runner and the scripts directory")
.aliases(["cg", "cfg", "-cg", "-cfg", "cc", "-cc"])
.arg(arg!(-o --overwrite "overwrite existing"));

let add_scripts_cmd = Command::new("add")
.about("add a new script to the configured scripts directory")
.aliases(["a", "-a"])
.arg(Arg::new("path").help("path of the new script"))
.arg(arg!(-o --overwrite "overwrite existing"));

let remove_scripts_cmd = Command::new("remove")
.about("add a new script to the configured scripts directory")
.aliases(["r", "rm"])
.arg(Arg::new("name").help("name of the script"));

let execute_scripts_cmd = Command::new("execute")
.about("execute a dynamic script")
.aliases(["-e", "exc"])
.arg(Arg::new("name").help("name of the script"));

Command::new("script")
.visible_aliases(["sc", "-sc"])
.about("run a script file")
.arg(arg!(-f --file <FILE> "script file path").required(true))
.subcommand(configure_scripts_cmd)
.subcommand(add_scripts_cmd)
.subcommand(remove_scripts_cmd)
.subcommand(execute_scripts_cmd)
}
6 changes: 5 additions & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use include_dir::{include_dir, Dir};

pub const SOURCE_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates");
pub const TEMPLATES_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates");

pub const APP_RUNTIME_CONFIG_DIR: &str = ".dev_toolbox";
pub const APP_RUNTIME_SCRIPTS_DIR: &str = ".dev_toolbox/scripts";
pub const APP_RUNTIME_CONFIG_FILE_NAME: &str = "Toolbox.toml";

lazy_static::lazy_static! {
pub static ref DATABASE_PATH: std::string::String = {
Expand Down
6 changes: 4 additions & 2 deletions src/database/repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use rusqlite::Connection;
use super::store::KvStore;
use crate::errors::database::DatabaseError;


#[allow(dead_code)]
pub trait KvRepositoryTrait {
fn new(connection: Connection) -> Self;

Expand Down Expand Up @@ -111,7 +113,7 @@ impl KvRepositoryTrait for KvRepository {
.collect::<Vec<_>>()
}

fn find_by_key(&self, key: &String) -> Option<KvStore> {
fn find_by_key(&self, _key: &String) -> Option<KvStore> {
todo!()
}

Expand All @@ -124,7 +126,7 @@ impl KvRepositoryTrait for KvRepository {
let Some(mut stmt) = stmt else {
return None;
};
let stored_data = stmt
let _stored_data = stmt
.query_map([id], |row| {
Ok(KvStore {
id: row.get(0).unwrap_or_default(),
Expand Down
7 changes: 4 additions & 3 deletions src/database/store.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[allow(dead_code)]
use chrono::Local;
use rusqlite::Connection;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -27,11 +28,11 @@ impl KvStore {
}
}

pub fn save(&self) {}
pub fn _save(&self) {}
}

pub fn stored_data_handler() {}
pub fn run_store_tui() -> Result<(), DatabaseError> {
// pub fn stored_data_handler() {}
pub fn _run_store_tui() -> Result<(), DatabaseError> {
let _security_questions = vec![
"What is your mother's maiden name?",
"What is the name of your first pet?",
Expand Down
4 changes: 3 additions & 1 deletion src/errors/file_system.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use thiserror::Error;

#[derive(Error, Debug)]
pub enum FsError {
pub enum FileSystemError {
#[error("{0}")]
OperationError(String),
#[error(transparent)]
IoError(#[from] std::io::Error),
}
4 changes: 4 additions & 0 deletions src/helpers/file_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ use std::path::Path;
pub fn file_exists_in_path(base_path: &Path, file_name: &str) -> bool {
Path::new(base_path).join(file_name).exists()
}

pub fn create_file_in_path() {}

pub fn remove_file_in_path() {}
File renamed without changes.
1 change: 1 addition & 0 deletions src/helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod console;
pub mod file_system;
pub mod parser;
pub mod input;
Empty file added src/helpers/templates.rs
Empty file.
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use lib_toolbox::{

fn main() -> Result<(), AppError> {
let matches = Command::new("toolbox")
.display_name("Dev toolbox")
.about("lightweight extensible, command line toolchain for software builders")
.subcommand_required(true)
.arg_required_else_help(true)
Expand Down
3 changes: 1 addition & 2 deletions src/parsers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
pub mod app;
pub mod generator;
pub mod scripts;
pub mod store;

// pub mod scripts;
54 changes: 24 additions & 30 deletions src/parsers/scripts.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,33 @@
// Copyright 2018-2025 the Deno authors. MIT license.
// NOTE:
// Here we are deserializing to `serde_json::Value` but you can
// deserialize to any other type that implements the `Deserialize` trait.
use deno_core::v8;
use deno_core::JsRuntime;
use deno_core::RuntimeOptions;
use clap::ArgMatches;

fn main() {
let mut runtime = JsRuntime::new(RuntimeOptions::default());
use crate::{helpers::console::LogMessage, workers::scripts::configure_scripts};

// Evaluate some code
let code = "let a = 1+4; a*2";
let output: serde_json::Value = eval(&mut runtime, code).expect("Eval failed");
pub fn parse_script_options(sub_matches: &ArgMatches) {
match sub_matches.subcommand() {
Some(("configure", args)) => {
let override_existing = *args.get_one::<bool>("overwrite").unwrap_or(&false);

println!("Output: {output:?}");
let _ = configure_scripts();
}
Some(("add", args)) => {
println!("add new scripts")
}

let expected_output = serde_json::json!(10);
assert_eq!(expected_output, output);
}
Some(("remove", args)) => {
println!("remove new scripts")
}
Some(("execute", args)) => {
println!("execute new scripts")
}

fn eval(context: &mut JsRuntime, code: &'static str) -> Result<serde_json::Value, String> {
let res = context.execute_script("<anon>", code);
match res {
Ok(global) => {
deno_core::scope!(scope, context);
let local = v8::Local::new(scope, global);
// Deserialize a `v8` object into a Rust type using `serde_v8`,
// in this case deserialize to a JSON `Value`.
let deserialized_value = serde_v8::from_v8::<serde_json::Value>(scope, local);
Some((other, _)) => {
LogMessage::warning(&format!("Unknown subcommand '{}'", other));
std::process::exit(1);
}

match deserialized_value {
Ok(value) => Ok(value),
Err(err) => Err(format!("Cannot deserialize value: {err:?}")),
}
None => {
LogMessage::error("No subcommand provided. Use `--help` to see available options.");
std::process::exit(1);
}
Err(err) => Err(format!("Evaling error: {err:?}")),
}
}
2 changes: 2 additions & 0 deletions src/toolbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use clap::ArgMatches;
use rusqlite::Connection;

use crate::helpers::console::LogMessage;
use crate::parsers::scripts::parse_script_options;
use crate::parsers::{
app::{parse_uninstall_options, parse_upgrade_options},
generator::parse_generator_options,
Expand All @@ -14,6 +15,7 @@ pub fn parse_commands(matches: ArgMatches, database_connection: Connection) {
Some(("uninstall", sub_matches)) => parse_uninstall_options(sub_matches),
Some(("upgrade", sub_matches)) => parse_upgrade_options(sub_matches),
Some(("generate", sub_matches)) => parse_generator_options(sub_matches),
Some(("script", sub_matches)) => parse_script_options(sub_matches),
_ => {
LogMessage::error("Invalid command");
std::process::exit(1)
Expand Down
40 changes: 20 additions & 20 deletions src/workers/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use console::Term;
use dialoguer::{theme::ColorfulTheme, Confirm, FuzzySelect};
use serde::{Deserialize, Serialize};

use crate::constants::SOURCE_DIR;
use crate::errors::file_system::FsError;
use crate::constants::TEMPLATES_DIR;
use crate::errors::file_system::FileSystemError;
use crate::helpers::{console::LogMessage, file_system::file_exists_in_path};

#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -45,14 +45,14 @@ impl GeneratorConfig {
}
}

pub fn generate_readme(&self) -> Result<(), FsError> {
pub fn generate_readme(&self) -> Result<(), FileSystemError> {
let file_exists = file_exists_in_path(self.base_path.as_path(), "README.md");
let file_path = self.base_path.join("README.md");
let backup_path = self.base_path.join("README.md.bak");

// Case 1: File exists but overwriting not allowed
if file_exists && !self.force {
return Err(FsError::OperationError(
return Err(FileSystemError::OperationError(
"README.md already exists — use --force to overwrite".to_string(),
));
}
Expand All @@ -61,7 +61,7 @@ impl GeneratorConfig {
if file_exists && self.force {
if self.back_up {
if let Err(error) = fs::copy(&file_path, &backup_path) {
return Err(FsError::OperationError(error.to_string()));
return Err(FileSystemError::OperationError(error.to_string()));
}
LogMessage::info(&format!("Backup created at {:?}", backup_path));
} else {
Expand All @@ -78,7 +78,7 @@ impl GeneratorConfig {
}

fs::remove_file(&file_path).map_err(|err| {
FsError::OperationError(format!("Failed to remove file: {}", err))
FileSystemError::OperationError(format!("Failed to remove file: {}", err))
})?;
LogMessage::info("Old README.md removed.");
}
Expand All @@ -88,7 +88,7 @@ impl GeneratorConfig {
Ok(())
}

pub fn generate_ignore_file(&self) -> Result<(), FsError> {
pub fn generate_ignore_file(&self) -> Result<(), FileSystemError> {
let file_exists = file_exists_in_path(self.base_path.as_path(), ".gitignore");
let file_path = self.base_path.join(".gitignore");
let backup_path = self.base_path.join(".gitignore.bak");
Expand All @@ -97,20 +97,21 @@ impl GeneratorConfig {
LogMessage::warning(
"A .gitignore file already exists in the selected path. Use the '--force' flag to overwrite it.",
);
return Err(FsError::OperationError(
return Err(FileSystemError::OperationError(
".gitignore already exists — use --force to overwrite".to_string(),
));
}

if file_exists && self.force {
if self.back_up {
fs::copy(&file_path, &backup_path)
.map_err(|err| FsError::OperationError(format!("Backup failed: {}", err)))?;
fs::copy(&file_path, &backup_path).map_err(|err| {
FileSystemError::OperationError(format!("Backup failed: {}", err))
})?;
LogMessage::info(&format!("Backup created at {:?}", backup_path));
}

fs::remove_file(&file_path).map_err(|err| {
FsError::OperationError(format!("Failed to remove file: {}", err))
FileSystemError::OperationError(format!("Failed to remove file: {}", err))
})?;
LogMessage::info("Old .gitignore removed.");
}
Expand Down Expand Up @@ -151,7 +152,7 @@ impl GeneratorConfig {
}
}

fn create_git_ignore_template(full_path: &Path) -> Result<(), FsError> {
fn create_git_ignore_template(full_path: &Path) -> Result<(), FileSystemError> {
let supported_technologies = vec![
"AL",
"Actionscript",
Expand Down Expand Up @@ -306,7 +307,7 @@ impl GeneratorConfig {

fn generate_ignore_file_to_path(technology: &str, path: &Path) {
let src_path = format!("gitignore/{}.gitignore", technology);
if let Some(file) = SOURCE_DIR.get_file(src_path) {
if let Some(file) = TEMPLATES_DIR.get_file(src_path) {
if let Ok(mut output) = File::create(path) {
if let Err(err) = output.write_all(file.contents()) {
LogMessage::error(&format!("Failed to write .gitignore: {}", err));
Expand All @@ -321,10 +322,9 @@ impl GeneratorConfig {
));
}
}
fn create_readme_template(full_path: &Path) -> Result<(), FsError> {
let content=r#"

# Project Title
fn create_readme_template(full_path: &Path) -> Result<(), FileSystemError> {
let content = r#"
# Project Title

Simple overview of use/purpose.

Expand Down Expand Up @@ -387,10 +387,10 @@ Inspiration, code snippets, etc.
* [zenorocha](https://gist.github.com/zenorocha/4526327)
* [fvcproductions](https://gist.github.com/fvcproductions/1bfc2d4aecb01a834b46)
"#;
let mut file = std::fs::File::create(full_path)
.map_err(|err| FsError::OperationError(err.to_string()))?;
let mut file = std::fs::File::create(full_path)
.map_err(|err| FileSystemError::OperationError(err.to_string()))?;
file.write_all(content.as_bytes())
.map_err(|err| FsError::OperationError(err.to_string()))?;
.map_err(|err| FileSystemError::OperationError(err.to_string()))?;
Ok(())
}
}
2 changes: 1 addition & 1 deletion src/workers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub mod generator;
pub mod scripts;
pub mod store;
pub mod store;
Loading