@repokit/core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/.vscode/settings.json +11 -0
  2. package/Cargo.lock +517 -0
  3. package/Cargo.toml +26 -0
  4. package/README.md +204 -0
  5. package/dist/cjs/CommandParser.js +68 -0
  6. package/dist/cjs/ConfigurationParser.js +46 -0
  7. package/dist/cjs/RepoKitCommand.js +16 -0
  8. package/dist/cjs/RepoKitConfig.js +10 -0
  9. package/dist/cjs/TaskPooler.js +42 -0
  10. package/dist/cjs/commands/parse_commands.js +15 -0
  11. package/dist/cjs/commands/parse_configuration.js +15 -0
  12. package/dist/cjs/index.js +19 -0
  13. package/dist/cjs/package.json +3 -0
  14. package/dist/cjs/types.js +2 -0
  15. package/dist/mjs/CommandParser.js +51 -0
  16. package/dist/mjs/ConfigurationParser.js +31 -0
  17. package/dist/mjs/RepoKitCommand.js +16 -0
  18. package/dist/mjs/RepoKitConfig.js +8 -0
  19. package/dist/mjs/TaskPooler.js +28 -0
  20. package/dist/mjs/commands/parse_commands.js +4 -0
  21. package/dist/mjs/commands/parse_configuration.js +4 -0
  22. package/dist/mjs/index.js +3 -0
  23. package/dist/mjs/package.json +4 -0
  24. package/dist/mjs/types.js +1 -0
  25. package/dist/types/CommandParser.d.ts +5 -0
  26. package/dist/types/ConfigurationParser.d.ts +4 -0
  27. package/dist/types/RepoKitCommand.d.ts +14 -0
  28. package/dist/types/RepoKitConfig.d.ts +6 -0
  29. package/dist/types/TaskPooler.d.ts +10 -0
  30. package/dist/types/commands/parse_commands.d.ts +1 -0
  31. package/dist/types/commands/parse_configuration.d.ts +1 -0
  32. package/dist/types/index.d.ts +3 -0
  33. package/dist/types/types.d.ts +18 -0
  34. package/install.sh +43 -0
  35. package/package.json +40 -0
  36. package/repokit.ts +36 -0
  37. package/src/CommandParser.ts +59 -0
  38. package/src/ConfigurationParser.ts +34 -0
  39. package/src/RepoKitCommand.ts +24 -0
  40. package/src/RepoKitConfig.ts +10 -0
  41. package/src/TaskPooler.ts +31 -0
  42. package/src/commands/parse_commands.ts +5 -0
  43. package/src/commands/parse_configuration.ts +5 -0
  44. package/src/index.ts +3 -0
  45. package/src/types.ts +22 -0
  46. package/tsconfig.json +24 -0
  47. package/workspaces/concurrency/mod.rs +1 -0
  48. package/workspaces/concurrency/thread_pool.rs +32 -0
  49. package/workspaces/configuration/configuration.rs +47 -0
  50. package/workspaces/configuration/configuration_template.ts +23 -0
  51. package/workspaces/configuration/mod.rs +1 -0
  52. package/workspaces/executables/external_executable.rs +4 -0
  53. package/workspaces/executables/intenal_executable.rs +9 -0
  54. package/workspaces/executables/internal_executable_definition.rs +8 -0
  55. package/workspaces/executables/mod.rs +3 -0
  56. package/workspaces/executor/executor.rs +62 -0
  57. package/workspaces/executor/mod.rs +1 -0
  58. package/workspaces/external_commands/external_commands.rs +125 -0
  59. package/workspaces/external_commands/mod.rs +1 -0
  60. package/workspaces/internal_commands/command_template.ts +24 -0
  61. package/workspaces/internal_commands/help.rs +146 -0
  62. package/workspaces/internal_commands/internal_registry.rs +59 -0
  63. package/workspaces/internal_commands/list_commands.rs +106 -0
  64. package/workspaces/internal_commands/list_owners.rs +74 -0
  65. package/workspaces/internal_commands/locate_command.rs +78 -0
  66. package/workspaces/internal_commands/mod.rs +10 -0
  67. package/workspaces/internal_commands/onboarder.rs +66 -0
  68. package/workspaces/internal_commands/register_command.rs +117 -0
  69. package/workspaces/internal_commands/search_commands.rs +189 -0
  70. package/workspaces/internal_commands/typescript_command.rs +63 -0
  71. package/workspaces/internal_commands/upgrade_repokit.rs +76 -0
  72. package/workspaces/logger/logger.rs +98 -0
  73. package/workspaces/logger/mod.rs +1 -0
  74. package/workspaces/main.rs +21 -0
  75. package/workspaces/repokit/interfaces.rs +41 -0
  76. package/workspaces/repokit/mod.rs +2 -0
  77. package/workspaces/repokit/repokit.rs +141 -0
  78. package/workspaces/validations/command_validations.rs +140 -0
  79. package/workspaces/validations/mod.rs +1 -0
@@ -0,0 +1,117 @@
1
+ use normalize_path::NormalizePath;
2
+ use std::{
3
+ collections::HashMap,
4
+ fs::{File, create_dir_all},
5
+ io,
6
+ path::{Path, PathBuf},
7
+ process,
8
+ };
9
+
10
+ use crate::{
11
+ repokit::interfaces::RepoKitConfig,
12
+ executables::{
13
+ intenal_executable::InternalExecutable,
14
+ internal_executable_definition::InternalExecutableDefinition,
15
+ },
16
+ internal_commands::help::Help,
17
+ logger::logger::Logger,
18
+ };
19
+
20
+ pub struct RegisterCommand {
21
+ pub root: String,
22
+ pub configuration: RepoKitConfig,
23
+ pub definition: InternalExecutableDefinition,
24
+ }
25
+
26
+ impl RegisterCommand {
27
+ pub fn new(root: String, configuration: RepoKitConfig) -> RegisterCommand {
28
+ RegisterCommand {
29
+ root,
30
+ configuration,
31
+ definition: InternalExecutableDefinition {
32
+ name: "register",
33
+ description: "Creates new Repokit commands",
34
+ args: HashMap::from([(
35
+ "<path>",
36
+ "A relative path to your preferred command location",
37
+ )]),
38
+ },
39
+ }
40
+ }
41
+
42
+ fn validate_path(&self, args: Vec<String>) -> PathBuf {
43
+ if args.is_empty() {
44
+ RegisterCommand::exit_on_missing_path();
45
+ }
46
+ let path_arg = args[0].clone();
47
+ if path_arg.is_empty() {
48
+ RegisterCommand::exit_on_missing_path();
49
+ }
50
+ let path = Path::new(&self.root).join(&path_arg).normalize();
51
+ if !path.exists() {
52
+ Logger::info(
53
+ format!(
54
+ "Creating the path {} in your file system",
55
+ Logger::blue_bright(path_arg.as_str())
56
+ )
57
+ .as_str(),
58
+ );
59
+ create_dir_all(&path).expect("");
60
+ }
61
+ if !path.is_dir() {
62
+ RegisterCommand::exit_on_missing_path();
63
+ }
64
+ let command_path = &path.join("Commands.ts");
65
+ if command_path.exists() {
66
+ Logger::error(
67
+ format!(
68
+ "A {} file already exists in this directory",
69
+ Logger::blue_bright("Commands.ts")
70
+ )
71
+ .as_str(),
72
+ );
73
+ Logger::info(format!(
74
+ "You can append additional commands to the existing {} instance or export another one",
75
+ Logger::blue_bright("RepoKitCommand")
76
+ ).as_str());
77
+ process::exit(0);
78
+ }
79
+ command_path.clone()
80
+ }
81
+
82
+ fn exit_on_missing_path() {
83
+ Logger::exit_with_error(
84
+ "Please specify a path to a directory relative to the root of your repository",
85
+ );
86
+ }
87
+
88
+ pub fn template_path() -> PathBuf {
89
+ let file_path = file!();
90
+ let dir = Path::new(file_path)
91
+ .parent()
92
+ .expect("Failed to get parent directory");
93
+ dir.join("command_template.ts")
94
+ }
95
+ }
96
+
97
+ impl InternalExecutable for RegisterCommand {
98
+ fn run(&self, args: Vec<String>, _: &HashMap<String, Box<dyn InternalExecutable>>) {
99
+ Logger::info("Registering a new command");
100
+ let command_path = self.validate_path(args);
101
+ let mut source = File::open(RegisterCommand::template_path()).expect("Template");
102
+ let mut target = File::create(&command_path).expect("creating");
103
+ io::copy(&mut source, &mut target).expect("writing");
104
+ target.sync_all().expect("Flushing");
105
+ Logger::info("Creating command file");
106
+ Logger::info("Please fill out your command file located at:");
107
+ Logger::log_file_path(command_path.to_str().expect("path"));
108
+ }
109
+
110
+ fn help(&self) {
111
+ Help::log_internal_command(&self.definition);
112
+ }
113
+
114
+ fn get_definition(&self) -> &InternalExecutableDefinition {
115
+ &self.definition
116
+ }
117
+ }
@@ -0,0 +1,189 @@
1
+ use alphanumeric_sort::sort_slice_by_str_key;
2
+ use std::collections::HashMap;
3
+
4
+ use crate::{
5
+ repokit::interfaces::{Command, RepoKitCommand, RepoKitConfig},
6
+ executables::{
7
+ intenal_executable::InternalExecutable,
8
+ internal_executable_definition::InternalExecutableDefinition,
9
+ },
10
+ internal_commands::help::Help,
11
+ logger::logger::Logger,
12
+ validations::command_validations::CommandValidations,
13
+ };
14
+
15
+ pub struct SearchCommands {
16
+ pub root: String,
17
+ pub configuration: RepoKitConfig,
18
+ pub definition: InternalExecutableDefinition,
19
+ }
20
+
21
+ impl SearchCommands {
22
+ pub fn new(root: String, configuration: RepoKitConfig) -> SearchCommands {
23
+ SearchCommands {
24
+ root,
25
+ configuration,
26
+ definition: InternalExecutableDefinition {
27
+ name: "search",
28
+ description: "Retrieve commands that match any search query",
29
+ args: HashMap::from([(
30
+ "<query>",
31
+ "A search string to match against command names, descriptions, arguments, or owner",
32
+ )]),
33
+ },
34
+ }
35
+ }
36
+
37
+ fn search_internal(&self, query: &str, command: &Box<dyn InternalExecutable>) -> bool {
38
+ let config = command.get_definition();
39
+ if config.name.to_lowercase().contains(query) {
40
+ return true;
41
+ }
42
+ if config.description.to_lowercase().contains(query) {
43
+ return true;
44
+ }
45
+ for (arg, description) in &config.args {
46
+ if arg.to_lowercase().contains(query) || description.to_lowercase().contains(query) {
47
+ return true;
48
+ }
49
+ }
50
+ false
51
+ }
52
+
53
+ fn search_external(&self, query: &str, command: &RepoKitCommand) -> bool {
54
+ if command.name.to_lowercase().contains(query) {
55
+ return true;
56
+ }
57
+ if command.owner.to_lowercase().contains(query) {
58
+ return true;
59
+ }
60
+ if command
61
+ .location
62
+ .replace(self.root.as_str(), "")
63
+ .to_lowercase()
64
+ .contains(query)
65
+ {
66
+ return true;
67
+ }
68
+ if command.description.to_lowercase().contains(query) {
69
+ return true;
70
+ }
71
+ for (arg, sub_command) in &command.commands {
72
+ if arg.to_lowercase().contains(query) || self.search_command(query, sub_command) {
73
+ return true;
74
+ }
75
+ }
76
+ false
77
+ }
78
+
79
+ fn search_command(&self, query: &str, command: &Command) -> bool {
80
+ if command.command.to_lowercase().contains(query)
81
+ || command.description.to_lowercase().contains(query)
82
+ {
83
+ return true;
84
+ }
85
+ false
86
+ }
87
+
88
+ fn log_root_results(&self, root_results: &HashMap<String, Command>) {
89
+ let total = root_results.len();
90
+ let plural_appendage = if total == 1 { "" } else { "s" };
91
+ if !root_results.is_empty() {
92
+ Help::log_root_commands(root_results);
93
+ }
94
+ Logger::info(
95
+ format!(
96
+ "Matched {} command{} in your repokit config",
97
+ Logger::blue_bright(total.to_string().as_str()),
98
+ plural_appendage,
99
+ )
100
+ .as_str(),
101
+ );
102
+ }
103
+
104
+ fn log_internal_results(
105
+ &self,
106
+ internal_results: &HashMap<String, &Box<dyn InternalExecutable>>,
107
+ ) {
108
+ let total = internal_results.len();
109
+ let plural_appendage = if total == 1 { "" } else { "s" };
110
+ if !internal_results.is_empty() {
111
+ let mut sorted_internals: Vec<&&Box<dyn InternalExecutable>> =
112
+ internal_results.values().collect();
113
+ sort_slice_by_str_key(&mut sorted_internals, |x| &x.get_definition().name);
114
+ Logger::space_around("Internal Commands:");
115
+ for internal in sorted_internals {
116
+ internal.help();
117
+ println!();
118
+ }
119
+ }
120
+ Logger::info(
121
+ format!(
122
+ "Matched {} internal command{}",
123
+ Logger::blue_bright(total.to_string().as_str()),
124
+ plural_appendage,
125
+ )
126
+ .as_str(),
127
+ );
128
+ }
129
+
130
+ fn log_external_results(&self, external_commands: &HashMap<String, RepoKitCommand>) {
131
+ let total = external_commands.len();
132
+ let plural_appendage = if total == 1 { "" } else { "s" };
133
+ if !external_commands.is_empty() {
134
+ Help::log_external_commands(external_commands);
135
+ }
136
+ Logger::info(
137
+ format!(
138
+ "Matched {} registered command{}",
139
+ Logger::blue_bright(total.to_string().as_str()),
140
+ plural_appendage,
141
+ )
142
+ .as_str(),
143
+ );
144
+ }
145
+ }
146
+
147
+ impl InternalExecutable for SearchCommands {
148
+ fn run(&self, args: Vec<String>, internals: &HashMap<String, Box<dyn InternalExecutable>>) {
149
+ Logger::info("Searching commands");
150
+ if args.is_empty() {
151
+ Logger::exit_with_error("Please specify a search string to query with");
152
+ }
153
+ let query = args.join(" ").to_lowercase();
154
+ let externals = CommandValidations::new(self.root.clone(), self.configuration.clone())
155
+ .collect_and_validate_externals();
156
+ let mut root_results: HashMap<String, Command> = HashMap::new();
157
+ let mut internal_results: HashMap<String, &Box<dyn InternalExecutable>> = HashMap::new();
158
+ let mut external_results: HashMap<String, RepoKitCommand> = HashMap::new();
159
+ for (command, script) in &self.configuration.commands {
160
+ if self.search_command(&query, script) {
161
+ root_results.insert(command.clone(), script.clone());
162
+ }
163
+ }
164
+ for (name, command) in internals {
165
+ if self.search_internal(&query, command) {
166
+ internal_results.insert(name.clone(), command);
167
+ }
168
+ }
169
+ for (name, command) in externals {
170
+ if self.search_external(&query, &command) {
171
+ external_results.insert(name, command);
172
+ }
173
+ }
174
+ if root_results.is_empty() && internal_results.is_empty() && external_results.is_empty() {
175
+ Logger::exit_with_info("No matched commands");
176
+ }
177
+ self.log_root_results(&root_results);
178
+ self.log_internal_results(&internal_results);
179
+ self.log_external_results(&external_results);
180
+ }
181
+
182
+ fn help(&self) {
183
+ Help::log_internal_command(&self.definition);
184
+ }
185
+
186
+ fn get_definition(&self) -> &InternalExecutableDefinition {
187
+ &self.definition
188
+ }
189
+ }
@@ -0,0 +1,63 @@
1
+ use std::path::{Path, PathBuf};
2
+
3
+ use normalize_path::NormalizePath;
4
+ use serde_json::from_str;
5
+
6
+ use crate::{
7
+ configuration::configuration::Configuration,
8
+ repokit::interfaces::{RepoKitCommand, RepoKitConfig},
9
+ executor::executor::Executor,
10
+ };
11
+
12
+ pub struct TypescriptCommand {
13
+ root: String,
14
+ }
15
+
16
+ impl TypescriptCommand {
17
+ pub fn new(root: String) -> TypescriptCommand {
18
+ TypescriptCommand { root }
19
+ }
20
+
21
+ pub fn parse_configuration(&self) -> RepoKitConfig {
22
+ let executable = self.path_to_command("parse_configuration.ts");
23
+ let stdout = self.execute(format!("{executable} --root {}", &self.root).as_str());
24
+ if stdout.is_empty() {
25
+ Configuration::create(&self.root);
26
+ }
27
+ let RepoKitConfig { project, commands } =
28
+ from_str(stdout.as_str()).expect("Error parsing stdout");
29
+ RepoKitConfig { project, commands }
30
+ }
31
+
32
+ pub fn parse_commands(&self, path_list: Vec<String>) -> Vec<RepoKitCommand> {
33
+ let paths = path_list.join(",");
34
+ let executable = self.path_to_command("parse_commands.ts");
35
+ let stdout =
36
+ self.execute(format!("{executable} --paths {paths} --root {}", self.root).as_str());
37
+ let commands: Vec<RepoKitCommand> = serde_json::from_str(&stdout).expect("parse");
38
+ commands
39
+ }
40
+
41
+ fn commands_dir(&self) -> PathBuf {
42
+ let file_path = file!();
43
+ let dir = Path::new(file_path)
44
+ .parent()
45
+ .expect("Failed to get parent directory");
46
+ let resolved = Path::new(&self.root).join(dir);
47
+ resolved.join("../../src/commands").normalize()
48
+ }
49
+
50
+ fn path_to_command(&self, command_file: &str) -> String {
51
+ self.commands_dir()
52
+ .join(command_file)
53
+ .into_os_string()
54
+ .into_string()
55
+ .expect("Cannot construct path")
56
+ }
57
+
58
+ fn execute(&self, args: &str) -> String {
59
+ Executor::exec(format!("npx tsx {}", args), |cmd| {
60
+ cmd.current_dir(Path::new(&self.root))
61
+ })
62
+ }
63
+ }
@@ -0,0 +1,76 @@
1
+ use normalize_path::NormalizePath;
2
+ use std::{collections::HashMap, path::Path, process::exit};
3
+
4
+ use crate::{
5
+ executables::{
6
+ intenal_executable::InternalExecutable,
7
+ internal_executable_definition::InternalExecutableDefinition,
8
+ },
9
+ executor::executor::Executor,
10
+ internal_commands::help::Help,
11
+ logger::logger::Logger,
12
+ repokit::interfaces::RepoKitConfig,
13
+ };
14
+
15
+ pub struct UpgradeRepoKit {
16
+ pub root: String,
17
+ pub configuration: RepoKitConfig,
18
+ pub definition: InternalExecutableDefinition,
19
+ }
20
+
21
+ impl UpgradeRepoKit {
22
+ pub fn new(root: String, configuration: RepoKitConfig) -> UpgradeRepoKit {
23
+ UpgradeRepoKit {
24
+ root,
25
+ configuration,
26
+ definition: InternalExecutableDefinition {
27
+ name: "upgrade",
28
+ description: "Upgrades your installation of repokit to the latest stable version",
29
+ args: HashMap::from([]),
30
+ },
31
+ }
32
+ }
33
+
34
+ fn get_package_manager(&self) -> &str {
35
+ let manager_map = HashMap::from([
36
+ ("npm", ("package-lock.json", "npm i -D")),
37
+ ("yarn", ("yarn.lock", "yarn add -D")),
38
+ ("pnpm", ("pnpm-lock.yaml", "pnpm i -D")),
39
+ ("bun", ("bun.lockb", "bun add -d")),
40
+ ]);
41
+ for (manager, (lock_file, command_prefix)) in manager_map {
42
+ let path = Path::new(&self.root).join(lock_file).normalize();
43
+ if path.exists() && path.is_file() {
44
+ Logger::info(
45
+ format!("Detected {} installation", Logger::blue_bright(manager)).as_str(),
46
+ );
47
+ return command_prefix;
48
+ }
49
+ }
50
+ Logger::info("A node package manager was not detected");
51
+ Logger::info(
52
+ "To upgrade repokit install the latest version using the package manager of your choosing",
53
+ );
54
+ exit(0);
55
+ }
56
+ }
57
+
58
+ impl InternalExecutable for UpgradeRepoKit {
59
+ fn run(&self, _: Vec<String>, _: &HashMap<String, Box<dyn InternalExecutable>>) {
60
+ Logger::info("Upgrading installation");
61
+ let command_prefix = self.get_package_manager();
62
+ Executor::exec(
63
+ format!("{} @repokit/core@latest", command_prefix).as_str(),
64
+ |cmd| cmd.current_dir(&self.root),
65
+ );
66
+ Logger::info("Upgrade complete!");
67
+ }
68
+
69
+ fn help(&self) {
70
+ Help::log_internal_command(&self.definition);
71
+ }
72
+
73
+ fn get_definition(&self) -> &InternalExecutableDefinition {
74
+ &self.definition
75
+ }
76
+ }
@@ -0,0 +1,98 @@
1
+ use std::sync::Mutex;
2
+ use std::{process, sync::LazyLock};
3
+
4
+ use colored::{ColoredString, Colorize, CustomColor};
5
+
6
+ static REGISTERED_NAME: LazyLock<Mutex<String>> =
7
+ LazyLock::new(|| Mutex::new("Repokit".to_string()));
8
+
9
+ pub struct Logger {}
10
+
11
+ impl Logger {
12
+ pub fn set_name(value: &str) {
13
+ *REGISTERED_NAME.lock().unwrap() = value.to_string();
14
+ }
15
+
16
+ pub fn info(message: &str) {
17
+ println!("{}{}", Logger::info_prefix(), message);
18
+ }
19
+
20
+ pub fn error(message: &str) {
21
+ eprintln!("{}{}", Logger::error_prefix(), message);
22
+ }
23
+
24
+ pub fn exit_with_info(message: &str) {
25
+ Logger::info(message);
26
+ process::exit(0);
27
+ }
28
+
29
+ pub fn exit_with_error(message: &str) {
30
+ Logger::error(message);
31
+ process::exit(0);
32
+ }
33
+
34
+ pub fn space_around(message: &str) {
35
+ println!("\n{}{}\n", Logger::info_prefix(), message);
36
+ }
37
+
38
+ pub fn log_file_path(path: &str) {
39
+ println!("\n{}{}\n", Logger::indent(None), Logger::blue_bright(path));
40
+ }
41
+
42
+ pub fn indent(times: Option<i32>) -> String {
43
+ let indentation: i32 = times.unwrap_or(5);
44
+ " ".repeat(indentation.try_into().unwrap())
45
+ }
46
+
47
+ pub fn blue(message: &str) -> ColoredString {
48
+ message.bright_blue()
49
+ }
50
+
51
+ pub fn blue_bright(message: &str) -> ColoredString {
52
+ message.bright_blue().bold()
53
+ }
54
+
55
+ pub fn magenta_bright(message: &str) -> ColoredString {
56
+ message.bright_magenta().bold()
57
+ }
58
+
59
+ pub fn magenta(message: &str) -> ColoredString {
60
+ message.magenta()
61
+ }
62
+
63
+ pub fn green(message: &str) -> ColoredString {
64
+ message.green()
65
+ }
66
+
67
+ pub fn green_bright(message: &str) -> ColoredString {
68
+ message.bright_green()
69
+ }
70
+
71
+ pub fn cyan(message: &str) -> ColoredString {
72
+ message.cyan()
73
+ }
74
+
75
+ pub fn cyan_bright(message: &str) -> ColoredString {
76
+ message.bright_cyan().bold()
77
+ }
78
+
79
+ pub fn gray(message: &str) -> ColoredString {
80
+ message.custom_color(CustomColor {
81
+ r: 128,
82
+ g: 128,
83
+ b: 128,
84
+ })
85
+ }
86
+
87
+ fn info_prefix() -> ColoredString {
88
+ format!("{}: ", *REGISTERED_NAME.lock().unwrap())
89
+ .bright_magenta()
90
+ .bold()
91
+ }
92
+
93
+ fn error_prefix() -> ColoredString {
94
+ format!("{}: ", *REGISTERED_NAME.lock().unwrap())
95
+ .red()
96
+ .bold()
97
+ }
98
+ }
@@ -0,0 +1 @@
1
+ pub mod logger;
@@ -0,0 +1,21 @@
1
+ use crate::{
2
+ executor::executor::Executor, internal_commands::typescript_command::TypescriptCommand,
3
+ repokit::repokit::RepoKit,
4
+ };
5
+
6
+ mod concurrency;
7
+ mod configuration;
8
+ mod executables;
9
+ mod executor;
10
+ mod external_commands;
11
+ mod internal_commands;
12
+ mod logger;
13
+ mod repokit;
14
+ mod validations;
15
+
16
+ fn main() {
17
+ let root = Executor::exec("git rev-parse --show-toplevel", |cmd| cmd);
18
+ let config = TypescriptCommand::new(root.clone()).parse_configuration();
19
+ let kit = RepoKit::new(root, config);
20
+ kit.invoke();
21
+ }
@@ -0,0 +1,41 @@
1
+ use std::collections::HashMap;
2
+
3
+ use serde::Deserialize;
4
+
5
+ #[derive(Debug, Deserialize, Clone)]
6
+ pub struct Command {
7
+ pub command: String,
8
+ pub description: String,
9
+ }
10
+
11
+ #[derive(Debug, Deserialize, Clone)]
12
+ pub struct ParsedCommand {
13
+ pub name: String,
14
+ pub command: String,
15
+ pub description: String,
16
+ }
17
+
18
+ impl ParsedCommand {
19
+ pub fn from(name: &str, command: &Command) -> ParsedCommand {
20
+ ParsedCommand {
21
+ name: name.to_string(),
22
+ command: command.command.to_string(),
23
+ description: command.description.to_string(),
24
+ }
25
+ }
26
+ }
27
+
28
+ #[derive(Debug, Deserialize, Clone)]
29
+ pub struct RepoKitConfig {
30
+ pub project: String,
31
+ pub commands: HashMap<String, Command>,
32
+ }
33
+
34
+ #[derive(Debug, Deserialize, Clone)]
35
+ pub struct RepoKitCommand {
36
+ pub name: String,
37
+ pub owner: String,
38
+ pub location: String,
39
+ pub description: String,
40
+ pub commands: HashMap<String, Command>,
41
+ }
@@ -0,0 +1,2 @@
1
+ pub mod interfaces;
2
+ pub mod repokit;