@repokit/core 3.0.6 → 4.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 (51) hide show
  1. package/Cargo.lock +96 -11
  2. package/Cargo.toml +2 -2
  3. package/installation/install.sh +49 -26
  4. package/internals/caches/crawl_cache.rs +124 -0
  5. package/internals/caches/file_cache.rs +104 -0
  6. package/internals/caches/mod.rs +6 -0
  7. package/internals/caches/old_cache.rs +35 -0
  8. package/internals/caches/repokit_version_resolver.rs +50 -0
  9. package/internals/caches/settings_cache.rs +73 -0
  10. package/internals/caches/version_cache.rs +142 -0
  11. package/internals/context/cache_scope.rs +71 -0
  12. package/internals/context/file_system.rs +66 -0
  13. package/internals/context/git_scope.rs +55 -0
  14. package/internals/context/mod.rs +5 -0
  15. package/internals/context/node_scope.rs +133 -0
  16. package/internals/context/typescript_bridge.rs +68 -0
  17. package/internals/executables/internal_executable.rs +8 -2
  18. package/internals/executables/internal_executable_definition.rs +0 -8
  19. package/internals/executor/executor.rs +13 -0
  20. package/internals/file_walker/file_walker.rs +59 -0
  21. package/internals/file_walker/mod.rs +1 -0
  22. package/internals/internal_commands/help.rs +4 -3
  23. package/internals/internal_commands/internal_registry.rs +14 -20
  24. package/internals/internal_commands/list_commands.rs +7 -16
  25. package/internals/internal_commands/list_owners.rs +3 -16
  26. package/internals/internal_commands/list_themes.rs +11 -10
  27. package/internals/internal_commands/list_version.rs +17 -18
  28. package/internals/internal_commands/locate_command.rs +11 -17
  29. package/internals/internal_commands/onboarder.rs +5 -16
  30. package/internals/internal_commands/register_command.rs +12 -20
  31. package/internals/internal_commands/search_commands.rs +29 -20
  32. package/internals/internal_commands/upgrade_repokit.rs +19 -30
  33. package/internals/internal_filesystem/file_builder.rs +4 -9
  34. package/internals/internal_filesystem/mod.rs +0 -1
  35. package/internals/logger/logger.rs +19 -6
  36. package/internals/main.rs +8 -11
  37. package/internals/repokit/mod.rs +1 -1
  38. package/internals/repokit/repokit.rs +49 -57
  39. package/internals/repokit/repokit_command.rs +70 -39
  40. package/internals/repokit/repokit_config.rs +42 -18
  41. package/internals/repokit/repokit_construct_validator.rs +1 -4
  42. package/internals/repokit/repokit_runtime.rs +43 -0
  43. package/internals/themes/theme_registry.rs +5 -7
  44. package/internals/validations/command_validations.rs +39 -62
  45. package/package.json +3 -3
  46. package/internals/configuration/configuration.rs +0 -45
  47. package/internals/configuration/mod.rs +0 -3
  48. package/internals/configuration/recovery.rs +0 -42
  49. package/internals/configuration/typescript_command.rs +0 -65
  50. package/internals/internal_filesystem/internal_filesystem.rs +0 -308
  51. package/internals/repokit/runtime_compiler.rs +0 -62
@@ -1,308 +0,0 @@
1
- use normalize_path::NormalizePath;
2
-
3
- use regex::Regex;
4
- use shellexpand::tilde;
5
- use std::{
6
- collections::HashMap,
7
- fs::{self, File},
8
- io::{BufRead, BufReader, Lines},
9
- path::{Path, PathBuf},
10
- sync::LazyLock,
11
- };
12
-
13
- use crate::{
14
- executor::executor::Executor, internal_filesystem::file_builder::FileBuilder,
15
- logger::logger::Logger,
16
- };
17
-
18
- pub static VERSION_REGEX: LazyLock<Regex> =
19
- LazyLock::new(|| Regex::new(r#"\d*\.\d*.\d*"#).unwrap());
20
-
21
- pub struct InternalFileSystem {
22
- root: String,
23
- }
24
-
25
- impl InternalFileSystem {
26
- pub fn new(root: &str) -> InternalFileSystem {
27
- InternalFileSystem {
28
- root: root.to_string(),
29
- }
30
- }
31
-
32
- pub fn absolute(&self, segment: &str) -> PathBuf {
33
- let path = Path::new(&self.root);
34
- path.join(segment).normalize()
35
- }
36
-
37
- pub fn resolve_command(&self, command_name: &str) -> String {
38
- self.path_buf_to_str(
39
- self.commands_directory()
40
- .join(format!("{command_name}.mjs")),
41
- )
42
- }
43
-
44
- pub fn resolve_template(&self, file_name: &str) -> File {
45
- let path = self.path_buf_to_str(self.templates_directory().join(file_name));
46
- FileBuilder::open(&path, |_| {
47
- Logger::error(format!("Unable to locate internal {file_name}").as_str());
48
- Logger::error("Please file a bug here");
49
- Logger::log_issue_link();
50
- })
51
- }
52
-
53
- pub fn find_root() -> String {
54
- let root = Executor::exec("echo $(git rev-parse --show-toplevel 2>/dev/null)", |cmd| {
55
- cmd
56
- });
57
- if root.is_empty() {
58
- Logger::exit_with_info(
59
- format!(
60
- "To start using {}, please initialize your git repository by running {}",
61
- Logger::with_theme(|theme| theme.highlight("Repokit")),
62
- Logger::with_theme(|theme| theme.highlight("git init"))
63
- )
64
- .as_str(),
65
- );
66
- }
67
- root
68
- }
69
-
70
- pub fn read_theme_preference(&self) -> String {
71
- let default = Logger::with_registry(|registry| registry.default_theme.clone());
72
- let theme = self.read_dot_file(&mut |mut lines, _| {
73
- if let Some(theme_preference) = lines.nth(1)
74
- && let Ok(preference) = theme_preference
75
- {
76
- return preference;
77
- }
78
- default.to_string()
79
- });
80
- theme.unwrap_or(default)
81
- }
82
-
83
- pub fn store_theme_preference(&self, theme: &str) {
84
- self.read_dot_file(&mut |lines, path| {
85
- let mut content: Vec<String> = lines.map(|line| line.unwrap()).collect();
86
- let theme_text = theme.to_string();
87
- if content.len() >= 2 {
88
- content[1] = theme_text;
89
- } else {
90
- content.push(theme_text);
91
- }
92
- fs::write(path, content.join("\n"))
93
- });
94
- }
95
-
96
- pub fn store_current_version(&self, version: &str) {
97
- self.read_dot_file(&mut |lines, path| {
98
- let mut content: Vec<String> = lines.map(|line| line.unwrap()).collect();
99
- if !content.is_empty() {
100
- content[0] = version.to_owned();
101
- } else {
102
- content.push(version.to_owned());
103
- }
104
- fs::write(path, content.join("\n"))
105
- });
106
- }
107
-
108
- pub fn read_dot_file<R>(
109
- &self,
110
- func: &mut impl FnMut(Lines<BufReader<File>>, PathBuf) -> R,
111
- ) -> Option<R> {
112
- let file_path = self.create_dot_file_if_not_exists();
113
- match file_path {
114
- Some(path) => {
115
- if let Ok(file) = File::open(&path) {
116
- let lines = BufReader::new(file).lines();
117
- return Some(func(lines, path));
118
- }
119
- None
120
- }
121
- None => None,
122
- }
123
- }
124
-
125
- pub fn home() -> Option<PathBuf> {
126
- let expanded_path_str = tilde("~/");
127
- let path = Path::new(expanded_path_str.as_ref()).normalize();
128
- if path.is_absolute() && path.exists() {
129
- return Some(path);
130
- }
131
- None
132
- }
133
-
134
- pub fn get_package_manager(root: &str) -> &str {
135
- let manager_map = HashMap::from([
136
- ("npm", "package-lock.json"),
137
- ("yarn", "yarn.lock"),
138
- ("pnpm", "pnpm-lock.yaml"),
139
- ("bun", "bun.lockb"),
140
- ]);
141
- for (manager, lock_file) in manager_map {
142
- let path = Path::new(&root).join(lock_file).normalize();
143
- if path.exists() && path.is_file() {
144
- return manager;
145
- }
146
- }
147
- "npm"
148
- }
149
-
150
- pub fn get_install_command(root: &str) -> &str {
151
- let npm_install = "npm i -D";
152
- let package_manager = InternalFileSystem::get_package_manager(root);
153
- let manager_map = HashMap::from([
154
- ("npm", npm_install),
155
- ("yarn", "yarn add -D"),
156
- ("pnpm", "pnpm i -D"),
157
- ("bun", "bun add -D"),
158
- ]);
159
- manager_map.get(package_manager).unwrap_or(&npm_install)
160
- }
161
-
162
- pub fn get_node_executor(root: &str) -> &str {
163
- let npx = "npx";
164
- let package_manager = InternalFileSystem::get_package_manager(root);
165
- let manager_map = HashMap::from([
166
- ("npm", "npx"),
167
- ("yarn", "yarn run -T"),
168
- ("pnpm", "pnpm run"),
169
- ("bun", "bunx"),
170
- ]);
171
- manager_map.get(package_manager).unwrap_or(&npx)
172
- }
173
-
174
- pub fn get_typescript_version(node_executor: &str) -> u32 {
175
- let stdout = Executor::exec(format!("{} tsc --version", node_executor), |cmd| cmd);
176
- let lines: Vec<&str> = stdout
177
- .split("\n")
178
- .filter_map(|s| {
179
- let trimmed = s.trim();
180
- if trimmed.is_empty() {
181
- return None;
182
- }
183
- Some(trimmed)
184
- })
185
- .collect();
186
- let fallback_version = "5.0.0";
187
- let version = lines.last().unwrap_or(&fallback_version);
188
- let captures: Vec<String> = VERSION_REGEX
189
- .captures_iter(version)
190
- .filter_map(|item| {
191
- item.get(0)
192
- .map(|match_text| match_text.as_str().to_string())
193
- })
194
- .collect();
195
- let fallback_version_str = fallback_version.to_string();
196
- let semver = captures.first().unwrap_or(&fallback_version_str);
197
- semver
198
- .chars()
199
- .next()
200
- .unwrap_or('5')
201
- .to_digit(10)
202
- .unwrap_or(5)
203
- }
204
-
205
- fn commands_directory(&self) -> PathBuf {
206
- self.absolute(format!("{}/dist/commands", self.package_directory()).as_str())
207
- }
208
-
209
- fn templates_directory(&self) -> PathBuf {
210
- self.absolute(format!("{}/externals/templates", self.package_directory()).as_str())
211
- }
212
-
213
- pub fn package_directory(&self) -> String {
214
- format!("./node_modules/{}", self.package_name())
215
- }
216
-
217
- fn package_name(&self) -> String {
218
- "@repokit/core".to_string()
219
- }
220
-
221
- fn path_buf_to_str(&self, buffer: PathBuf) -> String {
222
- buffer
223
- .into_os_string()
224
- .into_string()
225
- .expect("Cannot construct path")
226
- }
227
-
228
- fn create_dot_file_if_not_exists(&self) -> Option<PathBuf> {
229
- match InternalFileSystem::home() {
230
- Some(home) => {
231
- let dot_file_path = home.join(".repokit");
232
- if !&dot_file_path.exists() {
233
- let found_version = self.installed_repokit_version();
234
- found_version.as_ref()?;
235
- let version_string = found_version.unwrap();
236
- let result = fs::write(&dot_file_path, format!("{version_string}\n"));
237
- if result.is_err() {
238
- return None;
239
- }
240
- }
241
- Some(dot_file_path)
242
- }
243
- None => {
244
- Logger::error(
245
- "I encountered an issue when attempting to create a cache file on your machine",
246
- );
247
- Logger::error(
248
- format!(
249
- "Please create a file called {} in your home directory",
250
- Logger::with_theme(|theme| theme.highlight(".repokit"))
251
- )
252
- .as_str(),
253
- );
254
- Logger::error(
255
- "This file will be used to store settings and indicators that optimize how repokit runs in your repository",
256
- );
257
- None
258
- }
259
- }
260
- }
261
-
262
- pub fn installed_repokit_version(&self) -> Option<String> {
263
- let package_path = Path::new(&self.root)
264
- .join(InternalFileSystem::package_directory(self))
265
- .normalize();
266
- let package_json_path = package_path.join("package.json");
267
- let file = File::open(package_json_path);
268
- if file.is_err() {
269
- return None;
270
- }
271
- let lines = BufReader::new(file.unwrap()).lines();
272
- let version_matcher = Regex::new(r#""([^"]*)""#).unwrap();
273
- for line in lines.map_while(Result::ok) {
274
- if line.contains("\"version\": ") {
275
- let captures: Vec<String> = version_matcher
276
- .captures_iter(&line)
277
- .filter_map(|item| {
278
- item.get(1)
279
- .map(|match_text| match_text.as_str().to_string())
280
- })
281
- .collect();
282
- if let Some(version) = captures.get(1)
283
- && VERSION_REGEX.is_match(version)
284
- {
285
- return Some(version.to_string());
286
- }
287
- return None;
288
- }
289
- }
290
- None
291
- }
292
-
293
- pub fn runtime_repokit_version() -> Option<String> {
294
- if let Some(home) = InternalFileSystem::home() {
295
- let version = Executor::exec(
296
- format!(
297
- "head -n 1 {}",
298
- home.join(".repokit").normalize().to_str().unwrap()
299
- ),
300
- |cmd| cmd,
301
- );
302
- if VERSION_REGEX.is_match(&version) {
303
- return Some(version);
304
- }
305
- }
306
- None
307
- }
308
- }
@@ -1,62 +0,0 @@
1
- use std::{env::args, path::PathBuf, process::exit};
2
-
3
- use normalize_path::NormalizePath;
4
- use terminal_spinners::{BOUNCING_BALL, SpinnerBuilder};
5
-
6
- use crate::{
7
- executor::executor::Executor, internal_filesystem::internal_filesystem::InternalFileSystem,
8
- logger::logger::Logger,
9
- };
10
-
11
- pub struct RuntimeCompiler;
12
-
13
- impl RuntimeCompiler {
14
- pub fn hop_to_runtime_version(root: &str) {
15
- RuntimeCompiler::with_version_mismatch(root, |installed_version, fs| {
16
- let package_path = fs.absolute(&fs.package_directory());
17
- let install_path = package_path.join("installation/install.sh").normalize();
18
- if install_path.is_absolute() && install_path.exists() {
19
- Logger::info(
20
- format!(
21
- "Switching to version {}",
22
- Logger::with_theme(|theme| theme.highlight(installed_version))
23
- )
24
- .as_str(),
25
- );
26
- if let Some(errors) = RuntimeCompiler::run_post_install(&package_path) {
27
- println!("{errors}");
28
- } else {
29
- InternalFileSystem::new(root).store_current_version(installed_version);
30
- RuntimeCompiler::re_run_command();
31
- }
32
- }
33
- });
34
- }
35
-
36
- fn with_version_mismatch(root: &str, func: impl Fn(&str, InternalFileSystem)) {
37
- let scoped_fs = InternalFileSystem::new(root);
38
- if let Some(installed_version) = scoped_fs.installed_repokit_version()
39
- && let Some(runtime_version) = InternalFileSystem::runtime_repokit_version()
40
- && runtime_version != installed_version
41
- {
42
- func(&installed_version, scoped_fs);
43
- }
44
- }
45
-
46
- fn run_post_install(cwd: &PathBuf) -> Option<String> {
47
- let handle = SpinnerBuilder::new()
48
- .spinner(&BOUNCING_BALL)
49
- .text(" Installing")
50
- .start();
51
- let result =
52
- Executor::exec_with_errors("./installation/install.sh", |cmd| cmd.current_dir(cwd));
53
- handle.done();
54
- result
55
- }
56
-
57
- fn re_run_command() {
58
- let args: Vec<String> = args().collect();
59
- Executor::with_stdio(args.join(" "), |cmd| cmd);
60
- exit(0);
61
- }
62
- }