@fredlackey/devutils 0.0.7 → 0.0.9

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 (81) hide show
  1. package/package.json +78 -2
  2. package/src/installs/chocolatey.js +9 -0
  3. package/src/installs/wget.js +9 -4
  4. package/src/scripts/afk.js +0 -0
  5. package/src/scripts/backup-all.js +0 -0
  6. package/src/scripts/backup-source.js +0 -0
  7. package/src/scripts/brewd.js +0 -0
  8. package/src/scripts/brewi.js +0 -0
  9. package/src/scripts/brewr.js +0 -0
  10. package/src/scripts/brews.js +0 -0
  11. package/src/scripts/brewu.js +0 -0
  12. package/src/scripts/c.js +0 -0
  13. package/src/scripts/ccurl.js +0 -0
  14. package/src/scripts/certbot-crontab-init.js +0 -0
  15. package/src/scripts/certbot-init.js +0 -0
  16. package/src/scripts/ch.js +0 -0
  17. package/src/scripts/claude-danger.js +0 -0
  18. package/src/scripts/clean-dev.js +0 -0
  19. package/src/scripts/clear-dns-cache.js +0 -0
  20. package/src/scripts/clone.js +0 -0
  21. package/src/scripts/code-all.js +0 -0
  22. package/src/scripts/count-files.js +0 -0
  23. package/src/scripts/count-folders.js +0 -0
  24. package/src/scripts/count.js +0 -0
  25. package/src/scripts/d.js +0 -0
  26. package/src/scripts/datauri.js +0 -0
  27. package/src/scripts/delete-files.js +0 -0
  28. package/src/scripts/docker-clean.js +0 -0
  29. package/src/scripts/dp.js +0 -0
  30. package/src/scripts/e.js +0 -0
  31. package/src/scripts/empty-trash.js +0 -0
  32. package/src/scripts/evm.js +0 -0
  33. package/src/scripts/fetch-github-repos.js +0 -0
  34. package/src/scripts/get-channel.js +0 -0
  35. package/src/scripts/get-course.js +0 -0
  36. package/src/scripts/get-dependencies.js +0 -0
  37. package/src/scripts/get-folder.js +0 -0
  38. package/src/scripts/get-tunes.js +0 -0
  39. package/src/scripts/get-video.js +0 -0
  40. package/src/scripts/git-backup.js +0 -0
  41. package/src/scripts/git-clone.js +0 -0
  42. package/src/scripts/git-pup.js +0 -0
  43. package/src/scripts/git-push.js +0 -0
  44. package/src/scripts/h.js +0 -0
  45. package/src/scripts/hide-desktop-icons.js +0 -0
  46. package/src/scripts/hide-hidden-files.js +0 -0
  47. package/src/scripts/install-dependencies-from.js +0 -0
  48. package/src/scripts/ips.js +0 -0
  49. package/src/scripts/iso.js +0 -0
  50. package/src/scripts/killni.js +0 -0
  51. package/src/scripts/ll.js +0 -0
  52. package/src/scripts/local-ip.js +0 -0
  53. package/src/scripts/m.js +0 -0
  54. package/src/scripts/map.js +0 -0
  55. package/src/scripts/mkd.js +0 -0
  56. package/src/scripts/ncu-update-all.js +0 -0
  57. package/src/scripts/nginx-init.js +0 -0
  58. package/src/scripts/npmi.js +0 -0
  59. package/src/scripts/o.js +0 -0
  60. package/src/scripts/org-by-date.js +0 -0
  61. package/src/scripts/p.js +0 -0
  62. package/src/scripts/packages.js +0 -0
  63. package/src/scripts/path.js +0 -0
  64. package/src/scripts/ports.js +0 -0
  65. package/src/scripts/q.js +0 -0
  66. package/src/scripts/refresh-files.js +0 -0
  67. package/src/scripts/remove-smaller-files.js +0 -0
  68. package/src/scripts/rename-files-with-date.js +0 -0
  69. package/src/scripts/resize-image.js +0 -0
  70. package/src/scripts/rm-safe.js +0 -0
  71. package/src/scripts/s.js +0 -0
  72. package/src/scripts/set-git-public.js +0 -0
  73. package/src/scripts/show-desktop-icons.js +0 -0
  74. package/src/scripts/show-hidden-files.js +0 -0
  75. package/src/scripts/tpa.js +0 -0
  76. package/src/scripts/tpo.js +0 -0
  77. package/src/scripts/u.js +0 -0
  78. package/src/scripts/vpush.js +0 -0
  79. package/src/scripts/y.js +0 -0
  80. package/src/utils/windows/choco.js +82 -0
  81. package/src/utils/windows/winget.js +52 -3
package/package.json CHANGED
@@ -1,10 +1,86 @@
1
1
  {
2
2
  "name": "@fredlackey/devutils",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "A globally-installable Node.js CLI toolkit for bootstrapping and configuring development environments across any machine.",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
- "dev": "./bin/dev.js"
7
+ "dev": "./bin/dev.js",
8
+ "afk": "./src/scripts/afk.js",
9
+ "backup-all": "./src/scripts/backup-all.js",
10
+ "backup-source": "./src/scripts/backup-source.js",
11
+ "brewd": "./src/scripts/brewd.js",
12
+ "brewi": "./src/scripts/brewi.js",
13
+ "brewr": "./src/scripts/brewr.js",
14
+ "brews": "./src/scripts/brews.js",
15
+ "brewu": "./src/scripts/brewu.js",
16
+ "c": "./src/scripts/c.js",
17
+ "ccurl": "./src/scripts/ccurl.js",
18
+ "certbot-crontab-init": "./src/scripts/certbot-crontab-init.js",
19
+ "certbot-init": "./src/scripts/certbot-init.js",
20
+ "ch": "./src/scripts/ch.js",
21
+ "claude-danger": "./src/scripts/claude-danger.js",
22
+ "clean-dev": "./src/scripts/clean-dev.js",
23
+ "clear-dns-cache": "./src/scripts/clear-dns-cache.js",
24
+ "clone": "./src/scripts/clone.js",
25
+ "code-all": "./src/scripts/code-all.js",
26
+ "count": "./src/scripts/count.js",
27
+ "count-files": "./src/scripts/count-files.js",
28
+ "count-folders": "./src/scripts/count-folders.js",
29
+ "d": "./src/scripts/d.js",
30
+ "datauri": "./src/scripts/datauri.js",
31
+ "delete-files": "./src/scripts/delete-files.js",
32
+ "docker-clean": "./src/scripts/docker-clean.js",
33
+ "dp": "./src/scripts/dp.js",
34
+ "e": "./src/scripts/e.js",
35
+ "empty-trash": "./src/scripts/empty-trash.js",
36
+ "evm": "./src/scripts/evm.js",
37
+ "fetch-github-repos": "./src/scripts/fetch-github-repos.js",
38
+ "get-channel": "./src/scripts/get-channel.js",
39
+ "get-course": "./src/scripts/get-course.js",
40
+ "get-dependencies": "./src/scripts/get-dependencies.js",
41
+ "get-folder": "./src/scripts/get-folder.js",
42
+ "get-tunes": "./src/scripts/get-tunes.js",
43
+ "get-video": "./src/scripts/get-video.js",
44
+ "git-backup": "./src/scripts/git-backup.js",
45
+ "git-clone": "./src/scripts/git-clone.js",
46
+ "git-pup": "./src/scripts/git-pup.js",
47
+ "git-push": "./src/scripts/git-push.js",
48
+ "h": "./src/scripts/h.js",
49
+ "hide-desktop-icons": "./src/scripts/hide-desktop-icons.js",
50
+ "hide-hidden-files": "./src/scripts/hide-hidden-files.js",
51
+ "install-dependencies-from": "./src/scripts/install-dependencies-from.js",
52
+ "ips": "./src/scripts/ips.js",
53
+ "iso": "./src/scripts/iso.js",
54
+ "killni": "./src/scripts/killni.js",
55
+ "ll": "./src/scripts/ll.js",
56
+ "local-ip": "./src/scripts/local-ip.js",
57
+ "m": "./src/scripts/m.js",
58
+ "map": "./src/scripts/map.js",
59
+ "mkd": "./src/scripts/mkd.js",
60
+ "ncu-update-all": "./src/scripts/ncu-update-all.js",
61
+ "nginx-init": "./src/scripts/nginx-init.js",
62
+ "npmi": "./src/scripts/npmi.js",
63
+ "o": "./src/scripts/o.js",
64
+ "org-by-date": "./src/scripts/org-by-date.js",
65
+ "p": "./src/scripts/p.js",
66
+ "packages": "./src/scripts/packages.js",
67
+ "path": "./src/scripts/path.js",
68
+ "ports": "./src/scripts/ports.js",
69
+ "q": "./src/scripts/q.js",
70
+ "refresh-files": "./src/scripts/refresh-files.js",
71
+ "remove-smaller-files": "./src/scripts/remove-smaller-files.js",
72
+ "rename-files-with-date": "./src/scripts/rename-files-with-date.js",
73
+ "resize-image": "./src/scripts/resize-image.js",
74
+ "rm-safe": "./src/scripts/rm-safe.js",
75
+ "s": "./src/scripts/s.js",
76
+ "set-git-public": "./src/scripts/set-git-public.js",
77
+ "show-desktop-icons": "./src/scripts/show-desktop-icons.js",
78
+ "show-hidden-files": "./src/scripts/show-hidden-files.js",
79
+ "tpa": "./src/scripts/tpa.js",
80
+ "tpo": "./src/scripts/tpo.js",
81
+ "u": "./src/scripts/u.js",
82
+ "vpush": "./src/scripts/vpush.js",
83
+ "y": "./src/scripts/y.js"
8
84
  },
9
85
  "files": [
10
86
  "bin/",
@@ -25,6 +25,7 @@
25
25
  const os = require('../utils/common/os');
26
26
  const shell = require('../utils/common/shell');
27
27
  const windowsShell = require('../utils/windows/shell');
28
+ const choco = require('../utils/windows/choco');
28
29
 
29
30
  /**
30
31
  * The official Chocolatey installation script URL.
@@ -252,6 +253,10 @@ async function install_windows() {
252
253
  return;
253
254
  }
254
255
 
256
+ // Add Chocolatey's bin directory to the current process PATH so that
257
+ // subsequent choco commands work without requiring a terminal restart
258
+ choco.addBinToPath();
259
+
255
260
  console.log('Chocolatey installed successfully.');
256
261
  console.log('');
257
262
  console.log('IMPORTANT: Close and reopen your terminal for PATH changes to take effect.');
@@ -341,6 +346,10 @@ async function install_gitbash() {
341
346
  return;
342
347
  }
343
348
 
349
+ // Add Chocolatey's bin directory to the current process PATH so that
350
+ // subsequent choco commands work without requiring a terminal restart
351
+ choco.addBinToPath();
352
+
344
353
  console.log('Chocolatey installed successfully.');
345
354
  console.log('');
346
355
  console.log('IMPORTANT: Close and reopen Git Bash for PATH changes to take effect.');
@@ -239,14 +239,19 @@ async function install_windows() {
239
239
  return;
240
240
  }
241
241
 
242
- // Verify the installation succeeded by checking if the package is now installed
243
- const verified = await choco.isPackageInstalled('wget');
242
+ // Verify the installation by checking if the binary exists in Chocolatey's bin directory
243
+ // This works even when PATH hasn't been updated in the current terminal session
244
+ const verified = choco.commandBinaryExists('wget');
244
245
  if (!verified) {
245
- console.log('Installation may have failed: wget package not found after install.');
246
+ // Binary not found - this is unexpected since choco.install() succeeded
247
+ console.log('Warning: wget binary not found in Chocolatey bin directory.');
248
+ console.log('The package may use a different executable name.');
249
+ console.log('');
250
+ console.log('Try running in a new terminal: wget --version');
246
251
  return;
247
252
  }
248
253
 
249
- console.log('wget installed successfully via Chocolatey.');
254
+ console.log('wget installed successfully.');
250
255
  console.log('');
251
256
  console.log('Note: In PowerShell, use "wget.exe" (with the extension) to run GNU wget,');
252
257
  console.log('as "wget" is an alias for Invoke-WebRequest.');
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/src/scripts/c.js CHANGED
File without changes
File without changes
File without changes
File without changes
package/src/scripts/ch.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/src/scripts/d.js CHANGED
File without changes
File without changes
File without changes
File without changes
package/src/scripts/dp.js CHANGED
File without changes
package/src/scripts/e.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/src/scripts/h.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/src/scripts/ll.js CHANGED
File without changes
File without changes
package/src/scripts/m.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/src/scripts/o.js CHANGED
File without changes
File without changes
package/src/scripts/p.js CHANGED
File without changes
File without changes
File without changes
File without changes
package/src/scripts/q.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/src/scripts/s.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/src/scripts/u.js CHANGED
File without changes
File without changes
package/src/scripts/y.js CHANGED
File without changes
@@ -17,6 +17,43 @@ const fs = require('fs');
17
17
  */
18
18
  const CHOCO_KNOWN_PATH = 'C:\\ProgramData\\chocolatey\\bin\\choco.exe';
19
19
 
20
+ /**
21
+ * Well-known directory where Chocolatey installs command binaries.
22
+ * All Chocolatey-installed commands get shims placed here.
23
+ */
24
+ const CHOCO_BIN_DIR = 'C:\\ProgramData\\chocolatey\\bin';
25
+
26
+ /**
27
+ * Adds Chocolatey's bin directory to the current process's PATH.
28
+ *
29
+ * This is necessary after installing Chocolatey because the PATH environment
30
+ * variable in the current Node.js process won't be updated until a new terminal
31
+ * is opened. By manually adding the bin directory, subsequent child processes
32
+ * spawned by this process will be able to find Chocolatey-installed commands.
33
+ *
34
+ * This function is idempotent - it won't add the path if it's already present.
35
+ *
36
+ * @returns {boolean} True if PATH was modified, false if already present
37
+ */
38
+ function addBinToPath() {
39
+ const currentPath = process.env.PATH || '';
40
+ const pathSeparator = ';';
41
+
42
+ // Check if already in PATH (case-insensitive on Windows)
43
+ const paths = currentPath.split(pathSeparator);
44
+ const alreadyInPath = paths.some(p =>
45
+ p.toLowerCase() === CHOCO_BIN_DIR.toLowerCase()
46
+ );
47
+
48
+ if (alreadyInPath) {
49
+ return false;
50
+ }
51
+
52
+ // Prepend Chocolatey bin directory to PATH
53
+ process.env.PATH = `${CHOCO_BIN_DIR}${pathSeparator}${currentPath}`;
54
+ return true;
55
+ }
56
+
20
57
  /**
21
58
  * Checks if Chocolatey is installed.
22
59
  *
@@ -59,6 +96,48 @@ function getExecutablePath() {
59
96
  return null;
60
97
  }
61
98
 
99
+ /**
100
+ * Checks if a command binary exists in Chocolatey's bin directory.
101
+ *
102
+ * This is useful for verifying installations when the PATH hasn't been
103
+ * updated yet. Chocolatey creates shims (small .exe files) in its bin
104
+ * directory for all installed commands.
105
+ *
106
+ * @param {string} commandName - The command name (without .exe extension)
107
+ * @returns {boolean} True if the binary exists in Chocolatey's bin directory
108
+ */
109
+ function commandBinaryExists(commandName) {
110
+ const path = require('path');
111
+ const binaryPath = path.join(CHOCO_BIN_DIR, `${commandName}.exe`);
112
+
113
+ try {
114
+ return fs.existsSync(binaryPath);
115
+ } catch {
116
+ return false;
117
+ }
118
+ }
119
+
120
+ /**
121
+ * Gets the full path to a command's binary in Chocolatey's bin directory.
122
+ *
123
+ * @param {string} commandName - The command name (without .exe extension)
124
+ * @returns {string|null} Full path to the binary, or null if not found
125
+ */
126
+ function getCommandBinaryPath(commandName) {
127
+ const path = require('path');
128
+ const binaryPath = path.join(CHOCO_BIN_DIR, `${commandName}.exe`);
129
+
130
+ try {
131
+ if (fs.existsSync(binaryPath)) {
132
+ return binaryPath;
133
+ }
134
+ } catch {
135
+ // Ignore errors
136
+ }
137
+
138
+ return null;
139
+ }
140
+
62
141
  /**
63
142
  * Returns the installed Chocolatey version
64
143
  * @returns {Promise<string|null>}
@@ -368,6 +447,9 @@ async function unpin(packageName) {
368
447
  module.exports = {
369
448
  isInstalled,
370
449
  getExecutablePath,
450
+ addBinToPath,
451
+ commandBinaryExists,
452
+ getCommandBinaryPath,
371
453
  getVersion,
372
454
  install,
373
455
  uninstall,
@@ -23,6 +23,50 @@ const WINGET_KNOWN_PATH = path.join(
23
23
  'winget.exe'
24
24
  );
25
25
 
26
+ /**
27
+ * The WindowsApps directory containing Microsoft Store app aliases.
28
+ */
29
+ const WINDOWS_APPS_DIR = path.join(
30
+ process.env.LOCALAPPDATA || '',
31
+ 'Microsoft',
32
+ 'WindowsApps'
33
+ );
34
+
35
+ /**
36
+ * Adds the WindowsApps directory to the current process's PATH.
37
+ *
38
+ * This ensures that winget and other Microsoft Store apps are accessible
39
+ * to child processes spawned by this Node.js process. Normally this directory
40
+ * is in PATH, but in some environments (like fresh installations or CI) it may
41
+ * not be.
42
+ *
43
+ * This function is idempotent - it won't add the path if it's already present.
44
+ *
45
+ * @returns {boolean} True if PATH was modified, false if already present
46
+ */
47
+ function addBinToPath() {
48
+ if (!WINDOWS_APPS_DIR) {
49
+ return false;
50
+ }
51
+
52
+ const currentPath = process.env.PATH || '';
53
+ const pathSeparator = ';';
54
+
55
+ // Check if already in PATH (case-insensitive on Windows)
56
+ const paths = currentPath.split(pathSeparator);
57
+ const alreadyInPath = paths.some(p =>
58
+ p.toLowerCase() === WINDOWS_APPS_DIR.toLowerCase()
59
+ );
60
+
61
+ if (alreadyInPath) {
62
+ return false;
63
+ }
64
+
65
+ // Prepend WindowsApps directory to PATH
66
+ process.env.PATH = `${WINDOWS_APPS_DIR}${pathSeparator}${currentPath}`;
67
+ return true;
68
+ }
69
+
26
70
  /**
27
71
  * Checks if winget is available.
28
72
  *
@@ -89,7 +133,8 @@ async function getVersion() {
89
133
  * @param {Object} [options] - Installation options
90
134
  * @param {boolean} [options.silent=true] - Silent installation
91
135
  * @param {string} [options.version] - Specific version to install
92
- * @param {string} [options.source] - Package source (winget, msstore)
136
+ * @param {string} [options.source='winget'] - Package source (winget, msstore). Defaults to 'winget'
137
+ * to avoid issues with msstore certificate errors and source ambiguity.
93
138
  * @returns {Promise<{ success: boolean, output: string }>}
94
139
  */
95
140
  async function install(packageName, options = {}) {
@@ -111,8 +156,11 @@ async function install(packageName, options = {}) {
111
156
  command += ` --version "${options.version}"`;
112
157
  }
113
158
 
114
- if (options.source) {
115
- command += ` --source ${options.source}`;
159
+ // Default to 'winget' source to avoid msstore certificate errors and
160
+ // source ambiguity when packages exist in multiple sources
161
+ const source = options.source !== undefined ? options.source : 'winget';
162
+ if (source) {
163
+ command += ` --source ${source}`;
116
164
  }
117
165
 
118
166
  const result = await shell.exec(command);
@@ -425,6 +473,7 @@ async function updateSources() {
425
473
  module.exports = {
426
474
  isInstalled,
427
475
  getExecutablePath,
476
+ addBinToPath,
428
477
  getVersion,
429
478
  install,
430
479
  uninstall,