@fredlackey/devutils 0.0.1 → 0.0.3

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 (259) hide show
  1. package/README.md +5 -5
  2. package/package.json +1 -1
  3. package/src/commands/install.js +374 -36
  4. package/src/installs/adobe-creative-cloud.js +527 -25
  5. package/src/installs/adobe-creative-cloud.md +605 -0
  6. package/src/installs/appcleaner.js +303 -26
  7. package/src/installs/appcleaner.md +699 -0
  8. package/src/installs/apt-transport-https.js +390 -0
  9. package/src/installs/apt-transport-https.md +678 -0
  10. package/src/installs/atomicparsley.js +624 -26
  11. package/src/installs/atomicparsley.md +795 -0
  12. package/src/installs/aws-cli.js +779 -26
  13. package/src/installs/aws-cli.md +727 -0
  14. package/src/installs/balena-etcher.js +688 -26
  15. package/src/installs/balena-etcher.md +761 -0
  16. package/src/installs/bambu-studio.js +912 -26
  17. package/src/installs/bambu-studio.md +780 -0
  18. package/src/installs/bash-completion.js +554 -23
  19. package/src/installs/bash-completion.md +833 -0
  20. package/src/installs/bash.js +399 -26
  21. package/src/installs/bash.md +993 -0
  22. package/src/installs/beyond-compare.js +585 -26
  23. package/src/installs/beyond-compare.md +813 -0
  24. package/src/installs/build-essential.js +511 -26
  25. package/src/installs/build-essential.md +977 -0
  26. package/src/installs/ca-certificates.js +618 -0
  27. package/src/installs/ca-certificates.md +937 -0
  28. package/src/installs/caffeine.js +490 -26
  29. package/src/installs/caffeine.md +839 -0
  30. package/src/installs/camtasia.js +577 -25
  31. package/src/installs/camtasia.md +762 -0
  32. package/src/installs/chatgpt.js +458 -26
  33. package/src/installs/chatgpt.md +814 -0
  34. package/src/installs/chocolatey.js +447 -0
  35. package/src/installs/chocolatey.md +661 -0
  36. package/src/installs/chrome-canary.js +472 -26
  37. package/src/installs/chrome-canary.md +641 -0
  38. package/src/installs/chromium.js +645 -26
  39. package/src/installs/chromium.md +838 -0
  40. package/src/installs/claude-code.js +558 -26
  41. package/src/installs/claude-code.md +1173 -0
  42. package/src/installs/curl.js +361 -26
  43. package/src/installs/curl.md +714 -0
  44. package/src/installs/cursor.js +561 -26
  45. package/src/installs/cursor.md +970 -0
  46. package/src/installs/dbschema.js +674 -26
  47. package/src/installs/dbschema.md +925 -0
  48. package/src/installs/dependencies.md +435 -0
  49. package/src/installs/development-tools.js +600 -0
  50. package/src/installs/development-tools.md +977 -0
  51. package/src/installs/docker.js +1010 -25
  52. package/src/installs/docker.md +1109 -0
  53. package/src/installs/drawio.js +1001 -26
  54. package/src/installs/drawio.md +795 -0
  55. package/src/installs/elmedia-player.js +328 -25
  56. package/src/installs/elmedia-player.md +556 -0
  57. package/src/installs/ffmpeg.js +870 -25
  58. package/src/installs/ffmpeg.md +852 -0
  59. package/src/installs/file.js +464 -0
  60. package/src/installs/file.md +987 -0
  61. package/src/installs/gemini-cli.js +793 -26
  62. package/src/installs/gemini-cli.md +1153 -0
  63. package/src/installs/git.js +382 -26
  64. package/src/installs/git.md +907 -0
  65. package/src/installs/gitego.js +931 -26
  66. package/src/installs/gitego.md +1172 -0
  67. package/src/installs/go.js +913 -26
  68. package/src/installs/go.md +958 -0
  69. package/src/installs/google-chrome.js +801 -25
  70. package/src/installs/google-chrome.md +862 -0
  71. package/src/installs/gpg.js +412 -73
  72. package/src/installs/gpg.md +1056 -0
  73. package/src/installs/homebrew.js +1015 -26
  74. package/src/installs/homebrew.md +988 -0
  75. package/src/installs/imageoptim.js +950 -26
  76. package/src/installs/imageoptim.md +1119 -0
  77. package/src/installs/installers.json +2297 -0
  78. package/src/installs/jq.js +382 -26
  79. package/src/installs/jq.md +809 -0
  80. package/src/installs/keyboard-maestro.js +701 -26
  81. package/src/installs/keyboard-maestro.md +825 -0
  82. package/src/installs/latex.js +771 -26
  83. package/src/installs/latex.md +1095 -0
  84. package/src/installs/lftp.js +338 -26
  85. package/src/installs/lftp.md +907 -0
  86. package/src/installs/lsb-release.js +346 -0
  87. package/src/installs/lsb-release.md +814 -0
  88. package/src/installs/messenger.js +829 -26
  89. package/src/installs/messenger.md +900 -0
  90. package/src/installs/microsoft-office.js +550 -26
  91. package/src/installs/microsoft-office.md +760 -0
  92. package/src/installs/microsoft-teams.js +782 -25
  93. package/src/installs/microsoft-teams.md +886 -0
  94. package/src/installs/node.js +886 -26
  95. package/src/installs/node.md +1153 -0
  96. package/src/installs/nordpass.js +698 -26
  97. package/src/installs/nordpass.md +921 -0
  98. package/src/installs/nvm.js +977 -26
  99. package/src/installs/nvm.md +1057 -0
  100. package/src/installs/openssh.js +734 -64
  101. package/src/installs/openssh.md +1056 -0
  102. package/src/installs/pandoc.js +644 -26
  103. package/src/installs/pandoc.md +1036 -0
  104. package/src/installs/pinentry.js +492 -26
  105. package/src/installs/pinentry.md +1142 -0
  106. package/src/installs/pngyu.js +851 -26
  107. package/src/installs/pngyu.md +896 -0
  108. package/src/installs/postman.js +781 -26
  109. package/src/installs/postman.md +940 -0
  110. package/src/installs/procps.js +425 -0
  111. package/src/installs/procps.md +851 -0
  112. package/src/installs/safari-tech-preview.js +355 -25
  113. package/src/installs/safari-tech-preview.md +533 -0
  114. package/src/installs/sfnt2woff.js +640 -26
  115. package/src/installs/sfnt2woff.md +795 -0
  116. package/src/installs/shellcheck.js +463 -26
  117. package/src/installs/shellcheck.md +1005 -0
  118. package/src/installs/slack.js +722 -25
  119. package/src/installs/slack.md +865 -0
  120. package/src/installs/snagit.js +566 -25
  121. package/src/installs/snagit.md +844 -0
  122. package/src/installs/software-properties-common.js +372 -0
  123. package/src/installs/software-properties-common.md +805 -0
  124. package/src/installs/spotify.js +858 -25
  125. package/src/installs/spotify.md +901 -0
  126. package/src/installs/studio-3t.js +803 -26
  127. package/src/installs/studio-3t.md +918 -0
  128. package/src/installs/sublime-text.js +780 -25
  129. package/src/installs/sublime-text.md +914 -0
  130. package/src/installs/superwhisper.js +687 -25
  131. package/src/installs/superwhisper.md +630 -0
  132. package/src/installs/tailscale.js +727 -26
  133. package/src/installs/tailscale.md +1100 -0
  134. package/src/installs/tar.js +389 -0
  135. package/src/installs/tar.md +946 -0
  136. package/src/installs/termius.js +780 -26
  137. package/src/installs/termius.md +844 -0
  138. package/src/installs/terraform.js +761 -26
  139. package/src/installs/terraform.md +899 -0
  140. package/src/installs/tidal.js +752 -25
  141. package/src/installs/tidal.md +864 -0
  142. package/src/installs/tmux.js +328 -26
  143. package/src/installs/tmux.md +1030 -0
  144. package/src/installs/tree.js +393 -26
  145. package/src/installs/tree.md +833 -0
  146. package/src/installs/unzip.js +460 -0
  147. package/src/installs/unzip.md +879 -0
  148. package/src/installs/vim.js +403 -26
  149. package/src/installs/vim.md +1040 -0
  150. package/src/installs/vlc.js +803 -26
  151. package/src/installs/vlc.md +927 -0
  152. package/src/installs/vscode.js +825 -26
  153. package/src/installs/vscode.md +1002 -0
  154. package/src/installs/wget.js +415 -0
  155. package/src/installs/wget.md +791 -0
  156. package/src/installs/whatsapp.js +710 -25
  157. package/src/installs/whatsapp.md +854 -0
  158. package/src/installs/winpty.js +352 -0
  159. package/src/installs/winpty.md +620 -0
  160. package/src/installs/woff2.js +535 -26
  161. package/src/installs/woff2.md +977 -0
  162. package/src/installs/wsl.js +572 -0
  163. package/src/installs/wsl.md +699 -0
  164. package/src/installs/xcode-clt.js +520 -0
  165. package/src/installs/xcode-clt.md +351 -0
  166. package/src/installs/xcode.js +542 -26
  167. package/src/installs/xcode.md +573 -0
  168. package/src/installs/yarn.js +806 -26
  169. package/src/installs/yarn.md +1074 -0
  170. package/src/installs/yq.js +636 -26
  171. package/src/installs/yq.md +944 -0
  172. package/src/installs/yt-dlp.js +683 -26
  173. package/src/installs/yt-dlp.md +946 -0
  174. package/src/installs/yum-utils.js +297 -0
  175. package/src/installs/yum-utils.md +648 -0
  176. package/src/installs/zoom.js +740 -25
  177. package/src/installs/zoom.md +884 -0
  178. package/src/scripts/README.md +567 -45
  179. package/src/scripts/STATUS.md +208 -0
  180. package/src/scripts/afk.js +395 -7
  181. package/src/scripts/backup-all.js +731 -9
  182. package/src/scripts/backup-source.js +711 -8
  183. package/src/scripts/brewd.js +373 -7
  184. package/src/scripts/brewi.js +505 -9
  185. package/src/scripts/brewr.js +512 -9
  186. package/src/scripts/brews.js +462 -9
  187. package/src/scripts/brewu.js +488 -7
  188. package/src/scripts/c.js +185 -7
  189. package/src/scripts/ccurl.js +325 -8
  190. package/src/scripts/certbot-crontab-init.js +488 -8
  191. package/src/scripts/certbot-init.js +641 -9
  192. package/src/scripts/ch.js +339 -7
  193. package/src/scripts/claude-danger.js +253 -8
  194. package/src/scripts/clean-dev.js +419 -8
  195. package/src/scripts/clear-dns-cache.js +525 -7
  196. package/src/scripts/clone.js +417 -7
  197. package/src/scripts/code-all.js +420 -7
  198. package/src/scripts/count-files.js +195 -8
  199. package/src/scripts/count-folders.js +195 -8
  200. package/src/scripts/count.js +248 -8
  201. package/src/scripts/d.js +203 -7
  202. package/src/scripts/datauri.js +373 -8
  203. package/src/scripts/delete-files.js +363 -7
  204. package/src/scripts/docker-clean.js +410 -8
  205. package/src/scripts/dp.js +426 -7
  206. package/src/scripts/e.js +375 -9
  207. package/src/scripts/empty-trash.js +497 -7
  208. package/src/scripts/evm.js +428 -9
  209. package/src/scripts/fetch-github-repos.js +441 -10
  210. package/src/scripts/get-channel.js +329 -8
  211. package/src/scripts/get-course.js +384 -11
  212. package/src/scripts/get-dependencies.js +290 -9
  213. package/src/scripts/get-folder.js +783 -10
  214. package/src/scripts/get-tunes.js +411 -10
  215. package/src/scripts/get-video.js +352 -9
  216. package/src/scripts/git-backup.js +561 -9
  217. package/src/scripts/git-clone.js +477 -9
  218. package/src/scripts/git-pup.js +303 -7
  219. package/src/scripts/git-push.js +380 -8
  220. package/src/scripts/h.js +607 -9
  221. package/src/scripts/hide-desktop-icons.js +483 -7
  222. package/src/scripts/hide-hidden-files.js +522 -7
  223. package/src/scripts/install-dependencies-from.js +440 -9
  224. package/src/scripts/ips.js +647 -10
  225. package/src/scripts/iso.js +354 -8
  226. package/src/scripts/killni.js +561 -7
  227. package/src/scripts/ll.js +451 -8
  228. package/src/scripts/local-ip.js +310 -8
  229. package/src/scripts/m.js +508 -8
  230. package/src/scripts/map.js +293 -8
  231. package/src/scripts/mkd.js +287 -7
  232. package/src/scripts/ncu-update-all.js +441 -8
  233. package/src/scripts/nginx-init.js +702 -12
  234. package/src/scripts/npmi.js +366 -7
  235. package/src/scripts/o.js +495 -8
  236. package/src/scripts/org-by-date.js +321 -7
  237. package/src/scripts/p.js +208 -7
  238. package/src/scripts/packages.js +313 -8
  239. package/src/scripts/path.js +209 -7
  240. package/src/scripts/ports.js +582 -8
  241. package/src/scripts/q.js +290 -8
  242. package/src/scripts/refresh-files.js +378 -10
  243. package/src/scripts/remove-smaller-files.js +500 -8
  244. package/src/scripts/rename-files-with-date.js +517 -9
  245. package/src/scripts/resize-image.js +523 -9
  246. package/src/scripts/rm-safe.js +653 -8
  247. package/src/scripts/s.js +525 -9
  248. package/src/scripts/set-git-public.js +349 -7
  249. package/src/scripts/show-desktop-icons.js +459 -7
  250. package/src/scripts/show-hidden-files.js +456 -7
  251. package/src/scripts/tpa.js +265 -8
  252. package/src/scripts/tpo.js +264 -7
  253. package/src/scripts/u.js +489 -7
  254. package/src/scripts/vpush.js +422 -8
  255. package/src/scripts/y.js +267 -7
  256. package/src/utils/common/os.js +94 -2
  257. package/src/utils/ubuntu/apt.js +13 -7
  258. package/src/utils/windows/choco.js +82 -26
  259. package/src/utils/windows/winget.js +89 -27
@@ -1,24 +1,520 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * @fileoverview Install packages via Homebrew.
4
+ * brewi - Install packages via the system package manager
5
+ *
6
+ * Migrated from legacy dotfiles alias.
7
+ * Original: alias brewi="brew install"
8
+ *
9
+ * This script provides a cross-platform package installation command.
10
+ * On macOS, it wraps Homebrew's install command. On other platforms,
11
+ * it uses the native package manager (apt, dnf, yum, choco, winget).
12
+ *
5
13
  * @module scripts/brewi
6
14
  */
7
15
 
16
+ const os = require('../utils/common/os');
17
+ const shell = require('../utils/common/shell');
18
+
19
+ /**
20
+ * Pure Node.js implementation - not applicable for this script.
21
+ *
22
+ * Package installation requires shell-based package managers on all platforms,
23
+ * so there is no pure Node.js implementation. Each platform function must
24
+ * invoke the appropriate system package manager.
25
+ *
26
+ * @param {string[]} args - Package names to install
27
+ * @returns {Promise<void>}
28
+ * @throws {Error} Always throws - this function should not be called directly
29
+ */
30
+ async function do_brewi_nodejs(args) {
31
+ // Package installation requires OS-specific package managers.
32
+ // There is no pure Node.js implementation for this functionality.
33
+ throw new Error(
34
+ 'do_brewi_nodejs should not be called directly. ' +
35
+ 'Package installation requires platform-specific package managers.'
36
+ );
37
+ }
38
+
39
+ /**
40
+ * Install packages using Homebrew on macOS.
41
+ *
42
+ * Runs `brew install <packages>` to install the specified packages.
43
+ * Multiple packages can be specified at once.
44
+ *
45
+ * @param {string[]} args - Package names to install
46
+ * @returns {Promise<void>}
47
+ *
48
+ * @example
49
+ * // Install a single package
50
+ * do_brewi_macos(['wget'])
51
+ *
52
+ * @example
53
+ * // Install multiple packages
54
+ * do_brewi_macos(['wget', 'curl', 'jq'])
55
+ */
56
+ async function do_brewi_macos(args) {
57
+ // Validate that at least one package name was provided
58
+ if (args.length === 0) {
59
+ console.log('Usage: brewi <package> [package2] [package3] ...');
60
+ console.log('');
61
+ console.log('Install packages using Homebrew.');
62
+ console.log('');
63
+ console.log('Examples:');
64
+ console.log(' brewi wget # Install wget');
65
+ console.log(' brewi wget curl jq # Install multiple packages');
66
+ console.log(' brewi --cask firefox # Install a cask (GUI app)');
67
+ process.exit(1);
68
+ }
69
+
70
+ // Check if Homebrew is installed
71
+ if (!shell.commandExists('brew')) {
72
+ console.error('Error: Homebrew is not installed.');
73
+ console.error('');
74
+ console.error('Install Homebrew first:');
75
+ console.error(' /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"');
76
+ console.error('');
77
+ console.error('Or use: dev install homebrew');
78
+ process.exit(1);
79
+ }
80
+
81
+ // Build the command with all package arguments
82
+ // We pass args directly to brew install, which allows for:
83
+ // - Multiple package names: brewi wget curl jq
84
+ // - Cask installs: brewi --cask firefox
85
+ // - Version specifiers and other brew flags
86
+ const packages = args.join(' ');
87
+ const command = `brew install ${packages}`;
88
+
89
+ console.log(`Installing: ${args.join(', ')}`);
90
+
91
+ // Execute brew install and stream output to console
92
+ // We use spawnAsync to show real-time progress
93
+ const result = await shell.exec(command);
94
+
95
+ // Output the result
96
+ if (result.stdout) {
97
+ console.log(result.stdout);
98
+ }
99
+ if (result.stderr && result.code !== 0) {
100
+ console.error(result.stderr);
101
+ }
102
+
103
+ // Exit with the same code as brew
104
+ if (result.code !== 0) {
105
+ process.exit(result.code);
106
+ }
107
+ }
108
+
109
+ /**
110
+ * Install packages using APT on Ubuntu.
111
+ *
112
+ * Runs `sudo apt-get install -y <packages>` to install the specified packages.
113
+ * The -y flag automatically answers "yes" to prompts.
114
+ *
115
+ * @param {string[]} args - Package names to install
116
+ * @returns {Promise<void>}
117
+ *
118
+ * @example
119
+ * // Install a single package
120
+ * do_brewi_ubuntu(['wget'])
121
+ */
122
+ async function do_brewi_ubuntu(args) {
123
+ // Validate that at least one package name was provided
124
+ if (args.length === 0) {
125
+ console.log('Usage: brewi <package> [package2] [package3] ...');
126
+ console.log('');
127
+ console.log('Install packages using APT (Ubuntu equivalent of brew install).');
128
+ console.log('');
129
+ console.log('Examples:');
130
+ console.log(' brewi wget # Install wget');
131
+ console.log(' brewi wget curl jq # Install multiple packages');
132
+ process.exit(1);
133
+ }
134
+
135
+ // Check if apt-get is available
136
+ if (!shell.commandExists('apt-get')) {
137
+ console.error('Error: apt-get is not available on this system.');
138
+ process.exit(1);
139
+ }
140
+
141
+ // Build the command with all package arguments
142
+ const packages = args.join(' ');
143
+ const command = `sudo DEBIAN_FRONTEND=noninteractive apt-get install -y ${packages}`;
144
+
145
+ console.log(`Installing: ${args.join(', ')}`);
146
+
147
+ // Execute apt-get install
148
+ const result = await shell.exec(command);
149
+
150
+ // Output the result
151
+ if (result.stdout) {
152
+ console.log(result.stdout);
153
+ }
154
+ if (result.stderr && result.code !== 0) {
155
+ console.error(result.stderr);
156
+ }
157
+
158
+ // Exit with the same code as apt-get
159
+ if (result.code !== 0) {
160
+ process.exit(result.code);
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Install packages using APT on Raspberry Pi OS.
166
+ *
167
+ * Raspberry Pi OS is Debian-based, so it uses the same APT package manager
168
+ * as Ubuntu. This function delegates to the Ubuntu implementation.
169
+ *
170
+ * @param {string[]} args - Package names to install
171
+ * @returns {Promise<void>}
172
+ */
173
+ async function do_brewi_raspbian(args) {
174
+ // Raspbian uses the same APT package manager as Ubuntu
175
+ return do_brewi_ubuntu(args);
176
+ }
177
+
8
178
  /**
9
- * Installs the specified package(s) using Homebrew.
10
- * Shorthand for `brew install`.
179
+ * Install packages using DNF or YUM on Amazon Linux.
180
+ *
181
+ * Amazon Linux 2023 uses DNF, while Amazon Linux 2 uses YUM.
182
+ * This function detects which package manager is available and uses it.
11
183
  *
12
- * @param {string[]} args - Command line arguments
13
- * @param {string} args.0 - Package name to install
184
+ * @param {string[]} args - Package names to install
14
185
  * @returns {Promise<void>}
186
+ *
187
+ * @example
188
+ * // Install a single package
189
+ * do_brewi_amazon_linux(['wget'])
15
190
  */
16
- async function main(args) {
17
- // TODO: Implement brew install
191
+ async function do_brewi_amazon_linux(args) {
192
+ // Validate that at least one package name was provided
193
+ if (args.length === 0) {
194
+ console.log('Usage: brewi <package> [package2] [package3] ...');
195
+ console.log('');
196
+ console.log('Install packages using DNF/YUM (Amazon Linux equivalent of brew install).');
197
+ console.log('');
198
+ console.log('Examples:');
199
+ console.log(' brewi wget # Install wget');
200
+ console.log(' brewi wget curl jq # Install multiple packages');
201
+ process.exit(1);
202
+ }
203
+
204
+ // Detect package manager (dnf for AL2023, yum for AL2)
205
+ const hasDnf = shell.commandExists('dnf');
206
+ const hasYum = shell.commandExists('yum');
207
+ const packageManager = hasDnf ? 'dnf' : (hasYum ? 'yum' : null);
208
+
209
+ if (!packageManager) {
210
+ console.error('Error: Neither dnf nor yum package manager found.');
211
+ console.error('This command supports Amazon Linux 2023 (dnf) and Amazon Linux 2 (yum).');
212
+ process.exit(1);
213
+ }
214
+
215
+ // Build the command with all package arguments
216
+ const packages = args.join(' ');
217
+ const command = `sudo ${packageManager} install -y ${packages}`;
218
+
219
+ console.log(`Installing via ${packageManager}: ${args.join(', ')}`);
220
+
221
+ // Execute the install command
222
+ const result = await shell.exec(command);
223
+
224
+ // Output the result
225
+ if (result.stdout) {
226
+ console.log(result.stdout);
227
+ }
228
+ if (result.stderr && result.code !== 0) {
229
+ console.error(result.stderr);
230
+ }
231
+
232
+ // Exit with the same code as the package manager
233
+ if (result.code !== 0) {
234
+ process.exit(result.code);
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Install packages using Chocolatey in Windows Command Prompt.
240
+ *
241
+ * Runs `choco install -y <packages>` to install the specified packages.
242
+ * Requires Chocolatey to be installed and admin privileges.
243
+ *
244
+ * @param {string[]} args - Package names to install
245
+ * @returns {Promise<void>}
246
+ *
247
+ * @example
248
+ * // Install a single package
249
+ * do_brewi_cmd(['wget'])
250
+ */
251
+ async function do_brewi_cmd(args) {
252
+ // Validate that at least one package name was provided
253
+ if (args.length === 0) {
254
+ console.log('Usage: brewi <package> [package2] [package3] ...');
255
+ console.log('');
256
+ console.log('Install packages using Chocolatey (Windows equivalent of brew install).');
257
+ console.log('');
258
+ console.log('Examples:');
259
+ console.log(' brewi wget # Install wget');
260
+ console.log(' brewi wget curl jq # Install multiple packages');
261
+ console.log('');
262
+ console.log('Note: Run as Administrator for best results.');
263
+ process.exit(1);
264
+ }
265
+
266
+ // Check if Chocolatey is installed
267
+ if (!shell.commandExists('choco')) {
268
+ console.error('Error: Chocolatey is not installed.');
269
+ console.error('');
270
+ console.error('Install Chocolatey first (run as Administrator in PowerShell):');
271
+ console.error(' Set-ExecutionPolicy Bypass -Scope Process -Force;');
272
+ console.error(' [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;');
273
+ console.error(' iex ((New-Object System.Net.WebClient).DownloadString(\'https://community.chocolatey.org/install.ps1\'))');
274
+ process.exit(1);
275
+ }
276
+
277
+ // Build the command with all package arguments
278
+ const packages = args.join(' ');
279
+ const command = `choco install -y ${packages}`;
280
+
281
+ console.log(`Installing: ${args.join(', ')}`);
282
+
283
+ // Execute choco install
284
+ const result = await shell.exec(command);
285
+
286
+ // Output the result
287
+ if (result.stdout) {
288
+ console.log(result.stdout);
289
+ }
290
+ if (result.stderr && result.code !== 0) {
291
+ console.error(result.stderr);
292
+ }
293
+
294
+ // Exit with the same code as choco
295
+ if (result.code !== 0) {
296
+ process.exit(result.code);
297
+ }
298
+ }
299
+
300
+ /**
301
+ * Install packages using Chocolatey or winget in Windows PowerShell.
302
+ *
303
+ * Prefers Chocolatey if available, falls back to winget.
304
+ * This mirrors the macOS Homebrew experience.
305
+ *
306
+ * @param {string[]} args - Package names to install
307
+ * @returns {Promise<void>}
308
+ */
309
+ async function do_brewi_powershell(args) {
310
+ // Validate that at least one package name was provided
311
+ if (args.length === 0) {
312
+ console.log('Usage: brewi <package> [package2] [package3] ...');
313
+ console.log('');
314
+ console.log('Install packages using Chocolatey or winget (Windows equivalent of brew install).');
315
+ console.log('');
316
+ console.log('Examples:');
317
+ console.log(' brewi wget # Install wget');
318
+ console.log(' brewi wget curl jq # Install multiple packages');
319
+ console.log('');
320
+ console.log('Note: Run as Administrator for best results.');
321
+ process.exit(1);
322
+ }
323
+
324
+ // Prefer Chocolatey if available, fall back to winget
325
+ const hasChoco = shell.commandExists('choco');
326
+ const hasWinget = shell.commandExists('winget');
327
+
328
+ if (!hasChoco && !hasWinget) {
329
+ console.error('Error: Neither Chocolatey nor winget is available.');
330
+ console.error('');
331
+ console.error('Install Chocolatey (recommended):');
332
+ console.error(' Set-ExecutionPolicy Bypass -Scope Process -Force;');
333
+ console.error(' [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;');
334
+ console.error(' iex ((New-Object System.Net.WebClient).DownloadString(\'https://community.chocolatey.org/install.ps1\'))');
335
+ console.error('');
336
+ console.error('Or use winget (built into Windows 11 and Windows 10 21H2+).');
337
+ process.exit(1);
338
+ }
339
+
340
+ let command;
341
+ let packageManager;
342
+
343
+ if (hasChoco) {
344
+ // Use Chocolatey
345
+ packageManager = 'Chocolatey';
346
+ const packages = args.join(' ');
347
+ command = `choco install -y ${packages}`;
348
+ } else {
349
+ // Use winget - note: winget doesn't have a simple batch install
350
+ // so we install packages one at a time
351
+ packageManager = 'winget';
352
+ const packages = args.join(' ');
353
+ command = `winget install --accept-package-agreements --accept-source-agreements ${packages}`;
354
+ }
355
+
356
+ console.log(`Installing via ${packageManager}: ${args.join(', ')}`);
357
+
358
+ // Execute the install command
359
+ const result = await shell.exec(command);
360
+
361
+ // Output the result
362
+ if (result.stdout) {
363
+ console.log(result.stdout);
364
+ }
365
+ if (result.stderr && result.code !== 0) {
366
+ console.error(result.stderr);
367
+ }
368
+
369
+ // Exit with the same code as the package manager
370
+ if (result.code !== 0) {
371
+ process.exit(result.code);
372
+ }
373
+ }
374
+
375
+ /**
376
+ * Install packages from Git Bash on Windows.
377
+ *
378
+ * Git Bash runs within Windows, so this function uses Chocolatey
379
+ * via the Windows host. Falls back to winget if Chocolatey is not available.
380
+ *
381
+ * @param {string[]} args - Package names to install
382
+ * @returns {Promise<void>}
383
+ */
384
+ async function do_brewi_gitbash(args) {
385
+ // Validate that at least one package name was provided
386
+ if (args.length === 0) {
387
+ console.log('Usage: brewi <package> [package2] [package3] ...');
388
+ console.log('');
389
+ console.log('Install packages using Chocolatey (Windows equivalent of brew install).');
390
+ console.log('');
391
+ console.log('Examples:');
392
+ console.log(' brewi wget # Install wget');
393
+ console.log(' brewi wget curl jq # Install multiple packages');
394
+ console.log('');
395
+ console.log('Note: You may need to run Git Bash as Administrator.');
396
+ process.exit(1);
397
+ }
398
+
399
+ // Check for Chocolatey via PowerShell (more reliable in Git Bash)
400
+ const chocoCheck = await shell.exec('powershell.exe -NoProfile -Command "Get-Command choco -ErrorAction SilentlyContinue"');
401
+ const hasChoco = chocoCheck.code === 0 && chocoCheck.stdout.includes('choco');
402
+
403
+ // Check for winget via PowerShell
404
+ const wingetCheck = await shell.exec('powershell.exe -NoProfile -Command "Get-Command winget -ErrorAction SilentlyContinue"');
405
+ const hasWinget = wingetCheck.code === 0 && wingetCheck.stdout.includes('winget');
406
+
407
+ if (!hasChoco && !hasWinget) {
408
+ console.error('Error: Neither Chocolatey nor winget is available.');
409
+ console.error('');
410
+ console.error('Install Chocolatey (run as Administrator in PowerShell):');
411
+ console.error(' Set-ExecutionPolicy Bypass -Scope Process -Force;');
412
+ console.error(' [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;');
413
+ console.error(' iex ((New-Object System.Net.WebClient).DownloadString(\'https://community.chocolatey.org/install.ps1\'))');
414
+ process.exit(1);
415
+ }
416
+
417
+ let command;
418
+ let packageManager;
419
+
420
+ if (hasChoco) {
421
+ // Use Chocolatey via PowerShell
422
+ packageManager = 'Chocolatey';
423
+ const packages = args.join(' ');
424
+ command = `powershell.exe -NoProfile -Command "choco install -y ${packages}"`;
425
+ } else {
426
+ // Use winget via PowerShell
427
+ packageManager = 'winget';
428
+ const packages = args.join(' ');
429
+ command = `powershell.exe -NoProfile -Command "winget install --accept-package-agreements --accept-source-agreements ${packages}"`;
430
+ }
431
+
432
+ console.log(`Installing via ${packageManager}: ${args.join(', ')}`);
433
+
434
+ // Execute the install command
435
+ const result = await shell.exec(command);
436
+
437
+ // Output the result
438
+ if (result.stdout) {
439
+ console.log(result.stdout);
440
+ }
441
+ if (result.stderr && result.code !== 0) {
442
+ console.error(result.stderr);
443
+ }
444
+
445
+ // Exit with the same code as the package manager
446
+ if (result.code !== 0) {
447
+ process.exit(result.code);
448
+ }
449
+ }
450
+
451
+ /**
452
+ * Main entry point - detects environment and executes appropriate implementation.
453
+ *
454
+ * This script installs packages using the platform's native package manager:
455
+ * - macOS: Homebrew (brew install)
456
+ * - Ubuntu/Debian: APT (apt-get install)
457
+ * - Raspberry Pi OS: APT (apt-get install)
458
+ * - Amazon Linux: DNF or YUM (dnf/yum install)
459
+ * - Windows CMD: Chocolatey (choco install)
460
+ * - Windows PowerShell: Chocolatey or winget
461
+ * - Git Bash: Chocolatey or winget via PowerShell
462
+ *
463
+ * @param {string[]} args - Package names to install
464
+ * @returns {Promise<void>}
465
+ */
466
+ async function do_brewi(args) {
467
+ const platform = os.detect();
468
+
469
+ const handlers = {
470
+ 'macos': do_brewi_macos,
471
+ 'ubuntu': do_brewi_ubuntu,
472
+ 'debian': do_brewi_ubuntu,
473
+ 'raspbian': do_brewi_raspbian,
474
+ 'amazon_linux': do_brewi_amazon_linux,
475
+ 'rhel': do_brewi_amazon_linux,
476
+ 'fedora': do_brewi_amazon_linux,
477
+ 'cmd': do_brewi_cmd,
478
+ 'windows': do_brewi_powershell,
479
+ 'powershell': do_brewi_powershell,
480
+ 'gitbash': do_brewi_gitbash,
481
+ 'wsl': do_brewi_ubuntu
482
+ };
483
+
484
+ const handler = handlers[platform.type];
485
+ if (!handler) {
486
+ console.error(`Platform '${platform.type}' is not supported for this command.`);
487
+ console.error('');
488
+ console.error('Supported platforms:');
489
+ console.error(' - macOS (Homebrew)');
490
+ console.error(' - Ubuntu/Debian (APT)');
491
+ console.error(' - Raspberry Pi OS (APT)');
492
+ console.error(' - Amazon Linux/RHEL/Fedora (DNF/YUM)');
493
+ console.error(' - Windows (Chocolatey/winget)');
494
+ console.error(' - Git Bash (Chocolatey/winget)');
495
+ console.error(' - WSL (APT)');
496
+ process.exit(1);
497
+ }
498
+
499
+ await handler(args);
18
500
  }
19
501
 
20
- module.exports = { main };
502
+ module.exports = {
503
+ main: do_brewi,
504
+ do_brewi,
505
+ do_brewi_nodejs,
506
+ do_brewi_macos,
507
+ do_brewi_ubuntu,
508
+ do_brewi_raspbian,
509
+ do_brewi_amazon_linux,
510
+ do_brewi_cmd,
511
+ do_brewi_powershell,
512
+ do_brewi_gitbash
513
+ };
21
514
 
22
515
  if (require.main === module) {
23
- main(process.argv.slice(2));
516
+ do_brewi(process.argv.slice(2)).catch(err => {
517
+ console.error(err.message);
518
+ process.exit(1);
519
+ });
24
520
  }