@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
@@ -0,0 +1,618 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @fileoverview Install CA Certificates - trusted Certificate Authority certificates.
5
+ *
6
+ * CA certificates (Certificate Authority certificates) are digital certificates
7
+ * that establish a chain of trust for SSL/TLS connections. They are used by
8
+ * web browsers, command-line tools like cURL and wget, programming languages,
9
+ * and other applications to verify that secure connections to remote servers
10
+ * are legitimate and not being intercepted by malicious actors.
11
+ *
12
+ * CA certificates are essential for:
13
+ * - Secure web browsing (HTTPS)
14
+ * - Package manager operations (downloading from secure repositories)
15
+ * - API calls from applications
16
+ * - Git operations over HTTPS
17
+ * - Email encryption (TLS)
18
+ * - VPN connections
19
+ *
20
+ * Platform-specific packages and tools:
21
+ * - macOS: Homebrew ca-certificates formula (Mozilla CA bundle for CLI tools)
22
+ * - Ubuntu/Debian/Raspbian: ca-certificates package via APT + update-ca-certificates
23
+ * - Amazon Linux/RHEL: ca-certificates package via DNF/YUM + update-ca-trust
24
+ * - Windows: Windows Certificate Store (managed via certutil)
25
+ * - WSL: ca-certificates package via APT (same as Ubuntu)
26
+ * - Git Bash: CA bundle bundled with Git for Windows
27
+ *
28
+ * @module installs/ca-certificates
29
+ */
30
+
31
+ const os = require('../utils/common/os');
32
+ const shell = require('../utils/common/shell');
33
+ const brew = require('../utils/macos/brew');
34
+ const apt = require('../utils/ubuntu/apt');
35
+
36
+ // -----------------------------------------------------------------------------
37
+ // Helper Functions
38
+ // -----------------------------------------------------------------------------
39
+
40
+ /**
41
+ * Checks if the ca-certificates package is installed on Debian-based systems.
42
+ * Uses dpkg to query the package installation status.
43
+ *
44
+ * @returns {Promise<boolean>} True if ca-certificates is installed via APT
45
+ */
46
+ async function isDebianCaCertsInstalled() {
47
+ return await apt.isPackageInstalled('ca-certificates');
48
+ }
49
+
50
+ /**
51
+ * Checks if the certificate bundle file exists on Debian-based systems.
52
+ * The bundle file at /etc/ssl/certs/ca-certificates.crt contains all
53
+ * trusted CA certificates concatenated together.
54
+ *
55
+ * @returns {Promise<boolean>} True if the certificate bundle file exists
56
+ */
57
+ async function doesDebianCertBundleExist() {
58
+ const result = await shell.exec('test -f /etc/ssl/certs/ca-certificates.crt');
59
+ return result.code === 0;
60
+ }
61
+
62
+ /**
63
+ * Checks if the certificate bundle file exists on RHEL-based systems.
64
+ * The actual bundle file is at /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
65
+ * (with a symlink at /etc/pki/tls/certs/ca-bundle.crt for compatibility).
66
+ * We check the actual file location since the symlink may be missing even when
67
+ * the bundle exists.
68
+ *
69
+ * @returns {Promise<boolean>} True if the certificate bundle file exists
70
+ */
71
+ async function doesRhelCertBundleExist() {
72
+ // Check the actual bundle file location, not the symlink
73
+ const result = await shell.exec('test -f /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem');
74
+ return result.code === 0;
75
+ }
76
+
77
+ // -----------------------------------------------------------------------------
78
+ // Platform-Specific Installation Functions
79
+ // -----------------------------------------------------------------------------
80
+
81
+ /**
82
+ * Install CA certificates on macOS using Homebrew.
83
+ *
84
+ * macOS maintains CA certificates in two locations:
85
+ * 1. System Keychain - Used by Safari, native macOS applications, and system services
86
+ * 2. Homebrew ca-certificates - Used by Homebrew-installed tools like cURL, OpenSSL, and Python
87
+ *
88
+ * This function installs the Mozilla CA certificate bundle via Homebrew, which
89
+ * provides certificates for command-line tools. The certificate bundle is sourced
90
+ * from Mozilla (via https://curl.se/docs/caextract.html) and is regularly updated.
91
+ *
92
+ * Note: System applications use the macOS Keychain, not Homebrew's ca-certificates.
93
+ * Use Keychain Access or the security command to manage system-wide certificates.
94
+ *
95
+ * @returns {Promise<void>}
96
+ */
97
+ async function install_macos() {
98
+ // Check if Homebrew is available - it is required for macOS installation
99
+ if (!brew.isInstalled()) {
100
+ console.log('Homebrew is not installed. Please install Homebrew first.');
101
+ console.log('Run: dev install homebrew');
102
+ return;
103
+ }
104
+
105
+ // Check if ca-certificates is already installed via Homebrew
106
+ const isBrewCaCertsInstalled = await brew.isFormulaInstalled('ca-certificates');
107
+ if (isBrewCaCertsInstalled) {
108
+ console.log('CA certificates are already installed via Homebrew, skipping...');
109
+ return;
110
+ }
111
+
112
+ // Install ca-certificates using Homebrew
113
+ // The --quiet flag suppresses non-essential output for cleaner automation
114
+ console.log('Installing CA certificates via Homebrew...');
115
+ const result = await brew.install('ca-certificates');
116
+
117
+ if (!result.success) {
118
+ console.log('Failed to install CA certificates via Homebrew.');
119
+ console.log(result.output);
120
+ return;
121
+ }
122
+
123
+ // Verify the installation succeeded by checking if the formula is now installed
124
+ const verified = await brew.isFormulaInstalled('ca-certificates');
125
+ if (!verified) {
126
+ console.log('Installation may have failed: ca-certificates formula not found after install.');
127
+ return;
128
+ }
129
+
130
+ console.log('CA certificates installed successfully via Homebrew.');
131
+ console.log('');
132
+ console.log('Note: Homebrew-installed tools will automatically use this certificate bundle.');
133
+ console.log('System applications (Safari, Mail) use the macOS Keychain instead.');
134
+ }
135
+
136
+ /**
137
+ * Install CA certificates on Ubuntu/Debian using APT.
138
+ *
139
+ * The ca-certificates package is typically pre-installed on Ubuntu and Debian
140
+ * systems. This function ensures it is installed and up to date, then regenerates
141
+ * the certificate bundle using update-ca-certificates.
142
+ *
143
+ * The update-ca-certificates command:
144
+ * 1. Reads certificate configuration from /etc/ca-certificates.conf
145
+ * 2. Processes certificates from /usr/share/ca-certificates/ and /usr/local/share/ca-certificates/
146
+ * 3. Generates the unified bundle at /etc/ssl/certs/ca-certificates.crt
147
+ * 4. Creates individual certificate symlinks in /etc/ssl/certs/
148
+ *
149
+ * @returns {Promise<void>}
150
+ */
151
+ async function install_ubuntu() {
152
+ // Check if ca-certificates is already installed and certificate bundle exists
153
+ const isInstalled = await isDebianCaCertsInstalled();
154
+ const bundleExists = await doesDebianCertBundleExist();
155
+
156
+ if (isInstalled && bundleExists) {
157
+ console.log('CA certificates are already installed, skipping...');
158
+ return;
159
+ }
160
+
161
+ // Update package lists before installing to ensure we get the latest version
162
+ console.log('Updating package lists...');
163
+ const updateResult = await shell.exec('sudo DEBIAN_FRONTEND=noninteractive apt-get update -y');
164
+ if (updateResult.code !== 0) {
165
+ console.log('Warning: Failed to update package lists. Continuing with installation...');
166
+ }
167
+
168
+ // Install ca-certificates using APT with non-interactive mode
169
+ console.log('Installing CA certificates via APT...');
170
+ const installResult = await shell.exec('sudo DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates');
171
+
172
+ if (installResult.code !== 0) {
173
+ console.log('Failed to install CA certificates via APT.');
174
+ console.log(installResult.stderr || installResult.stdout);
175
+ return;
176
+ }
177
+
178
+ // Regenerate the certificate bundle to ensure it is up to date
179
+ // This command processes all certificates and creates the unified bundle
180
+ console.log('Regenerating certificate bundle...');
181
+ const updateCaResult = await shell.exec('sudo update-ca-certificates');
182
+
183
+ if (updateCaResult.code !== 0) {
184
+ console.log('Warning: Failed to regenerate certificate bundle.');
185
+ console.log(updateCaResult.stderr || updateCaResult.stdout);
186
+ }
187
+
188
+ // Verify the installation succeeded by checking if the bundle file exists
189
+ const verified = await doesDebianCertBundleExist();
190
+ if (!verified) {
191
+ console.log('Installation may have failed: certificate bundle not found after install.');
192
+ return;
193
+ }
194
+
195
+ console.log('CA certificates installed successfully.');
196
+ }
197
+
198
+ /**
199
+ * Install CA certificates on Ubuntu running in WSL.
200
+ *
201
+ * WSL Ubuntu installations follow the same process as native Ubuntu using APT.
202
+ * The certificate store is separate from the Windows host, so certificates
203
+ * added to Windows Certificate Store are not automatically available in WSL.
204
+ *
205
+ * @returns {Promise<void>}
206
+ */
207
+ async function install_ubuntu_wsl() {
208
+ // WSL Ubuntu uses the same APT-based installation as native Ubuntu
209
+ await install_ubuntu();
210
+ }
211
+
212
+ /**
213
+ * Install CA certificates on Raspberry Pi OS using APT.
214
+ *
215
+ * Raspberry Pi OS is based on Debian, so CA certificates management follows
216
+ * the same process as Ubuntu/Debian. The ca-certificates package is typically
217
+ * pre-installed on Raspberry Pi OS.
218
+ *
219
+ * Note: The ca-certificates package is architecture-independent (it contains
220
+ * only certificate data files, no compiled binaries), so there is no difference
221
+ * between ARM and x86 installations.
222
+ *
223
+ * @returns {Promise<void>}
224
+ */
225
+ async function install_raspbian() {
226
+ // Check if ca-certificates is already installed and certificate bundle exists
227
+ const isInstalled = await isDebianCaCertsInstalled();
228
+ const bundleExists = await doesDebianCertBundleExist();
229
+
230
+ if (isInstalled && bundleExists) {
231
+ console.log('CA certificates are already installed, skipping...');
232
+ return;
233
+ }
234
+
235
+ // Update package lists before installing to ensure we get the latest version
236
+ console.log('Updating package lists...');
237
+ const updateResult = await shell.exec('sudo DEBIAN_FRONTEND=noninteractive apt-get update -y');
238
+ if (updateResult.code !== 0) {
239
+ console.log('Warning: Failed to update package lists. Continuing with installation...');
240
+ }
241
+
242
+ // Install ca-certificates using APT with non-interactive mode
243
+ console.log('Installing CA certificates via APT...');
244
+ console.log('Note: Installation may take a few minutes on Raspberry Pi.');
245
+ const installResult = await shell.exec('sudo DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates');
246
+
247
+ if (installResult.code !== 0) {
248
+ console.log('Failed to install CA certificates via APT.');
249
+ console.log(installResult.stderr || installResult.stdout);
250
+ return;
251
+ }
252
+
253
+ // Regenerate the certificate bundle to ensure it is up to date
254
+ console.log('Regenerating certificate bundle...');
255
+ const updateCaResult = await shell.exec('sudo update-ca-certificates');
256
+
257
+ if (updateCaResult.code !== 0) {
258
+ console.log('Warning: Failed to regenerate certificate bundle.');
259
+ console.log(updateCaResult.stderr || updateCaResult.stdout);
260
+ }
261
+
262
+ // Verify the installation succeeded by checking if the bundle file exists
263
+ const verified = await doesDebianCertBundleExist();
264
+ if (!verified) {
265
+ console.log('Installation may have failed: certificate bundle not found after install.');
266
+ return;
267
+ }
268
+
269
+ console.log('CA certificates installed successfully.');
270
+ }
271
+
272
+ /**
273
+ * Install CA certificates on Amazon Linux/RHEL using DNF or YUM.
274
+ *
275
+ * The ca-certificates package is pre-installed on all Amazon Linux versions.
276
+ * This function ensures it is installed and up to date, then regenerates
277
+ * the certificate bundle using update-ca-trust.
278
+ *
279
+ * Note: Unlike Debian-based systems that use update-ca-certificates, Red Hat-based
280
+ * systems (including Amazon Linux) use update-ca-trust to manage the certificate
281
+ * trust store. The bundle is located at /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
282
+ * (with a symlink at /etc/pki/tls/certs/ca-bundle.crt for compatibility).
283
+ *
284
+ * Amazon Linux 2023 uses dnf as the package manager, while Amazon Linux 2 uses yum.
285
+ * This function automatically detects which package manager is available.
286
+ *
287
+ * @returns {Promise<void>}
288
+ */
289
+ async function install_amazon_linux() {
290
+ // Check if the certificate bundle already exists
291
+ const bundleExists = await doesRhelCertBundleExist();
292
+
293
+ if (bundleExists) {
294
+ // Verify the package is installed by checking if rpm can find it
295
+ const rpmResult = await shell.exec('rpm -q ca-certificates');
296
+ if (rpmResult.code === 0) {
297
+ console.log('CA certificates are already installed, skipping...');
298
+ return;
299
+ }
300
+ }
301
+
302
+ // Detect the platform to determine which package manager to use
303
+ // Amazon Linux 2023 uses dnf, Amazon Linux 2 uses yum
304
+ const platform = os.detect();
305
+ const packageManager = platform.packageManager;
306
+
307
+ // Construct the install command based on available package manager
308
+ const installCommand = packageManager === 'dnf'
309
+ ? 'sudo dnf install -y ca-certificates'
310
+ : 'sudo yum install -y ca-certificates';
311
+
312
+ // Install ca-certificates
313
+ console.log(`Installing CA certificates via ${packageManager}...`);
314
+ const installResult = await shell.exec(installCommand);
315
+
316
+ if (installResult.code !== 0) {
317
+ console.log(`Failed to install CA certificates via ${packageManager}.`);
318
+ console.log(installResult.stderr || installResult.stdout);
319
+ return;
320
+ }
321
+
322
+ // Regenerate the certificate bundle using update-ca-trust
323
+ // This command reads certificates from /etc/pki/ca-trust/source/anchors/
324
+ // and generates the unified bundle at /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
325
+ console.log('Regenerating certificate trust store...');
326
+ const updateTrustResult = await shell.exec('sudo update-ca-trust');
327
+
328
+ if (updateTrustResult.code !== 0) {
329
+ console.log('Warning: Failed to regenerate certificate trust store.');
330
+ console.log(updateTrustResult.stderr || updateTrustResult.stdout);
331
+ }
332
+
333
+ // Verify the installation succeeded by checking if the bundle file exists
334
+ const verified = await doesRhelCertBundleExist();
335
+ if (!verified) {
336
+ console.log('Installation may have failed: certificate bundle not found after install.');
337
+ return;
338
+ }
339
+
340
+ console.log('CA certificates installed successfully.');
341
+ }
342
+
343
+ /**
344
+ * Install/update CA certificates on Windows.
345
+ *
346
+ * Windows handles CA certificates differently from Linux and macOS. There is no
347
+ * "ca-certificates" package to install. Instead, Windows maintains a Certificate
348
+ * Trust List (CTL) that is automatically updated through Windows Update.
349
+ *
350
+ * This function manually triggers an update of the root certificates by:
351
+ * 1. Downloading the latest root certificate list from Microsoft
352
+ * 2. Importing the certificates to the Trusted Root store
353
+ *
354
+ * Windows stores certificates in the Windows Certificate Store, accessible via:
355
+ * - Certificate Manager (certmgr.msc) for current user certificates
356
+ * - Certificate Manager (certlm.msc) for local machine certificates
357
+ * - certutil command-line tool
358
+ * - PowerShell certificate provider
359
+ *
360
+ * Note: This function must be run with Administrator privileges.
361
+ *
362
+ * @returns {Promise<void>}
363
+ */
364
+ async function install_windows() {
365
+ // Check if certutil is available (it should be on all modern Windows versions)
366
+ const hasCertutil = shell.commandExists('certutil');
367
+ if (!hasCertutil) {
368
+ console.log('certutil command not found. This is unexpected on Windows.');
369
+ console.log('Please ensure you are running Windows 10 or later.');
370
+ return;
371
+ }
372
+
373
+ // Check if certificates are already present in the Trusted Root store
374
+ // A healthy Windows installation should have over 100 root certificates
375
+ console.log('Checking current certificate store...');
376
+ const countResult = await shell.exec('powershell -Command "(Get-ChildItem Cert:\\LocalMachine\\Root).Count"');
377
+
378
+ if (countResult.code === 0) {
379
+ const certCount = parseInt(countResult.stdout.trim(), 10);
380
+ if (certCount > 100) {
381
+ console.log(`Windows Certificate Store contains ${certCount} root certificates.`);
382
+ console.log('CA certificates are already present, skipping...');
383
+ return;
384
+ }
385
+ }
386
+
387
+ // Download and import the latest root certificates from Microsoft
388
+ // This command retrieves the Certificate Trust List from Windows Update servers
389
+ console.log('Downloading latest root certificates from Microsoft...');
390
+ const downloadResult = await shell.exec('certutil -generateSSTFromWU C:\\Windows\\Temp\\roots.sst');
391
+
392
+ if (downloadResult.code !== 0) {
393
+ console.log('Failed to download root certificates from Microsoft.');
394
+ console.log('This may be due to network issues or Windows Update being blocked.');
395
+ console.log(downloadResult.stderr || downloadResult.stdout);
396
+ return;
397
+ }
398
+
399
+ // Import the certificates to the Trusted Root store
400
+ console.log('Importing certificates to Trusted Root store...');
401
+ const importResult = await shell.exec('certutil -addstore -f Root C:\\Windows\\Temp\\roots.sst');
402
+
403
+ if (importResult.code !== 0) {
404
+ console.log('Failed to import certificates to Trusted Root store.');
405
+ console.log('Ensure you are running this command as Administrator.');
406
+ console.log(importResult.stderr || importResult.stdout);
407
+ // Clean up temporary file
408
+ await shell.exec('del C:\\Windows\\Temp\\roots.sst');
409
+ return;
410
+ }
411
+
412
+ // Clean up the temporary file
413
+ await shell.exec('del C:\\Windows\\Temp\\roots.sst');
414
+
415
+ console.log('CA certificates updated successfully.');
416
+ console.log('');
417
+ console.log('Note: Windows Update automatically maintains root CA certificates.');
418
+ console.log('This manual update ensures you have the latest certificates immediately.');
419
+ }
420
+
421
+ /**
422
+ * Install CA certificates on Git Bash (Windows).
423
+ *
424
+ * Git for Windows includes its own CA certificate bundle that is used by Git
425
+ * and the bundled cURL. This bundle is separate from both the Windows Certificate
426
+ * Store and any WSL certificate stores.
427
+ *
428
+ * The CA certificate bundle is located at:
429
+ * - C:\Program Files\Git\mingw64\etc\ssl\certs\ca-bundle.crt (Git commands)
430
+ * - C:\Program Files\Git\mingw64\ssl\certs\ca-bundle.crt (cURL/OpenSSL)
431
+ *
432
+ * No separate installation is required. If the certificate bundle is missing or
433
+ * needs to be updated, users can:
434
+ * 1. Upgrade Git for Windows (which includes an updated certificate bundle)
435
+ * 2. Configure Git to use the Windows SChannel backend instead
436
+ *
437
+ * @returns {Promise<void>}
438
+ */
439
+ async function install_gitbash() {
440
+ // Check if the CA bundle file exists (it should be bundled with Git Bash)
441
+ const bundleCheckResult = await shell.exec('test -f /mingw64/etc/ssl/certs/ca-bundle.crt');
442
+
443
+ if (bundleCheckResult.code === 0) {
444
+ console.log('CA certificates are already installed (bundled with Git for Windows), skipping...');
445
+ return;
446
+ }
447
+
448
+ // If the bundle is missing, provide guidance
449
+ console.log('CA certificate bundle not found at expected location.');
450
+ console.log('');
451
+ console.log('Git for Windows includes its own CA certificate bundle. If it is missing:');
452
+ console.log('');
453
+ console.log('Option 1: Reinstall or upgrade Git for Windows');
454
+ console.log(' Download from: https://git-scm.com/download/win');
455
+ console.log('');
456
+ console.log('Option 2: Configure Git to use Windows Certificate Store');
457
+ console.log(' git config --global http.sslBackend schannel');
458
+ console.log('');
459
+ console.log('Option 3: Manually download the Mozilla CA bundle');
460
+ console.log(' curl -o /mingw64/etc/ssl/certs/ca-bundle.crt https://curl.se/ca/cacert.pem');
461
+ }
462
+
463
+ // -----------------------------------------------------------------------------
464
+ // Eligibility Check
465
+ // -----------------------------------------------------------------------------
466
+
467
+ /**
468
+ * Check if CA certificates are installed on the current platform.
469
+ *
470
+ * This function performs platform-specific checks to determine if CA certificates
471
+ * are installed:
472
+ * - macOS: Checks for ca-certificates Homebrew formula
473
+ * - Linux (Debian-based): Checks for ca-certificates APT package and bundle file
474
+ * - Linux (RHEL-based): Checks for ca-certificates RPM package and bundle file
475
+ * - Windows/Git Bash: Checks for certificate store or bundle file
476
+ *
477
+ * @returns {Promise<boolean>} True if CA certificates are installed
478
+ */
479
+ async function isInstalled() {
480
+ const platform = os.detect();
481
+
482
+ // macOS: Check for ca-certificates via Homebrew
483
+ if (platform.type === 'macos') {
484
+ return await brew.isFormulaInstalled('ca-certificates');
485
+ }
486
+
487
+ // Ubuntu/Debian/WSL/Raspberry Pi: Check for package and bundle file
488
+ if (['ubuntu', 'debian', 'wsl', 'raspbian'].includes(platform.type)) {
489
+ const packageInstalled = await isDebianCaCertsInstalled();
490
+ const bundleExists = await doesDebianCertBundleExist();
491
+ return packageInstalled && bundleExists;
492
+ }
493
+
494
+ // Amazon Linux/RHEL/Fedora: Check for RPM package and bundle file
495
+ if (['amazon_linux', 'rhel', 'fedora'].includes(platform.type)) {
496
+ const rpmResult = await shell.exec('rpm -q ca-certificates 2>/dev/null');
497
+ const bundleExists = await doesRhelCertBundleExist();
498
+ return rpmResult.code === 0 && bundleExists;
499
+ }
500
+
501
+ // Windows: Check if certificate store has certificates
502
+ if (platform.type === 'windows') {
503
+ const countResult = await shell.exec('powershell -Command "(Get-ChildItem Cert:\\LocalMachine\\Root).Count"');
504
+ if (countResult.code === 0) {
505
+ const certCount = parseInt(countResult.stdout.trim(), 10);
506
+ return certCount > 100;
507
+ }
508
+ return false;
509
+ }
510
+
511
+ // Git Bash: Check if CA bundle file exists
512
+ if (platform.type === 'gitbash') {
513
+ const bundleCheckResult = await shell.exec('test -f /mingw64/etc/ssl/certs/ca-bundle.crt');
514
+ return bundleCheckResult.code === 0;
515
+ }
516
+
517
+ return false;
518
+ }
519
+
520
+ /**
521
+ * Check if this installer is supported on the current platform.
522
+ *
523
+ * CA certificates can be installed on all supported platforms:
524
+ * - macOS (Homebrew ca-certificates formula)
525
+ * - Ubuntu/Debian (ca-certificates package via APT)
526
+ * - Ubuntu on WSL (ca-certificates package via APT)
527
+ * - Raspberry Pi OS (ca-certificates package via APT)
528
+ * - Amazon Linux/RHEL/Fedora (ca-certificates package via DNF/YUM)
529
+ * - Windows (certutil for Windows Certificate Store)
530
+ * - Git Bash (bundled with Git for Windows)
531
+ *
532
+ * @returns {boolean} True if installation is supported on this platform
533
+ */
534
+ function isEligible() {
535
+ const platform = os.detect();
536
+ return ['macos', 'ubuntu', 'debian', 'wsl', 'raspbian', 'amazon_linux', 'fedora', 'rhel', 'windows', 'gitbash'].includes(platform.type);
537
+ }
538
+
539
+ // -----------------------------------------------------------------------------
540
+ // Main Installation Entry Point
541
+ // -----------------------------------------------------------------------------
542
+
543
+ /**
544
+ * Main installation entry point - detects platform and runs appropriate installer.
545
+ *
546
+ * This function detects the current operating system and dispatches to the
547
+ * appropriate platform-specific installer function. CA certificates are
548
+ * supported on all major platforms.
549
+ *
550
+ * Supported platforms:
551
+ * - macOS (Homebrew ca-certificates formula)
552
+ * - Ubuntu/Debian (ca-certificates package via APT)
553
+ * - Ubuntu on WSL (ca-certificates package via APT)
554
+ * - Raspberry Pi OS (ca-certificates package via APT)
555
+ * - Amazon Linux/RHEL/Fedora (ca-certificates package via DNF/YUM)
556
+ * - Windows (certutil for Windows Certificate Store)
557
+ * - Git Bash (bundled with Git for Windows)
558
+ *
559
+ * @returns {Promise<void>}
560
+ */
561
+ async function install() {
562
+ const platform = os.detect();
563
+
564
+ // Map platform types to their corresponding installer functions
565
+ // Multiple platform types can map to the same installer (e.g., debian and ubuntu)
566
+ const installers = {
567
+ 'macos': install_macos,
568
+ 'ubuntu': install_ubuntu,
569
+ 'debian': install_ubuntu,
570
+ 'wsl': install_ubuntu_wsl,
571
+ 'raspbian': install_raspbian,
572
+ 'amazon_linux': install_amazon_linux,
573
+ 'fedora': install_amazon_linux,
574
+ 'rhel': install_amazon_linux,
575
+ 'windows': install_windows,
576
+ 'gitbash': install_gitbash,
577
+ };
578
+
579
+ // Look up the installer for the detected platform
580
+ const installer = installers[platform.type];
581
+
582
+ // If no installer exists for this platform, inform the user gracefully
583
+ if (!installer) {
584
+ console.log(`CA certificates are not available for ${platform.type}.`);
585
+ return;
586
+ }
587
+
588
+ // Run the platform-specific installer
589
+ await installer();
590
+ }
591
+
592
+ // -----------------------------------------------------------------------------
593
+ // Module Exports
594
+ // -----------------------------------------------------------------------------
595
+
596
+ module.exports = {
597
+ install,
598
+ isInstalled,
599
+ isEligible,
600
+ install_macos,
601
+ install_ubuntu,
602
+ install_ubuntu_wsl,
603
+ install_raspbian,
604
+ install_amazon_linux,
605
+ install_windows,
606
+ install_gitbash,
607
+ };
608
+
609
+ // -----------------------------------------------------------------------------
610
+ // Direct Execution Handler
611
+ // -----------------------------------------------------------------------------
612
+
613
+ if (require.main === module) {
614
+ install().catch(err => {
615
+ console.error(err.message);
616
+ process.exit(1);
617
+ });
618
+ }