@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
package/src/scripts/c.js CHANGED
@@ -1,23 +1,201 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * @fileoverview Clear the terminal screen.
4
+ * c - Clear the terminal screen
5
+ *
6
+ * Migrated from legacy dotfiles alias.
7
+ * Original: alias c="clear"
8
+ *
9
+ * This script clears the terminal screen, providing a clean workspace.
10
+ * It uses pure Node.js ANSI escape sequences which work across all platforms,
11
+ * making the implementation identical on macOS, Linux, and Windows.
12
+ *
5
13
  * @module scripts/c
6
14
  */
7
15
 
16
+ const os = require('../utils/common/os');
17
+
18
+ /**
19
+ * Pure Node.js implementation that works on any platform.
20
+ *
21
+ * This function clears the terminal screen using ANSI escape sequences.
22
+ * These sequences are understood by virtually all modern terminal emulators:
23
+ *
24
+ * - ESC[2J : Clears the entire screen
25
+ * - ESC[H : Moves the cursor to the home position (top-left corner)
26
+ *
27
+ * This approach is preferred over shelling out to `clear` or `cls` because:
28
+ * 1. It works identically on all platforms
29
+ * 2. It requires no external commands
30
+ * 3. It's faster (no process spawn overhead)
31
+ * 4. It's more reliable (no dependency on external tools)
32
+ *
33
+ * @param {string[]} args - Command line arguments (unused)
34
+ * @returns {Promise<void>}
35
+ */
36
+ async function do_c_nodejs(args) {
37
+ // ANSI escape sequence to clear screen and move cursor to home position
38
+ // \x1b is the escape character (ESC)
39
+ // [2J clears the entire screen
40
+ // [H moves the cursor to row 1, column 1 (home position)
41
+ //
42
+ // Note: Some terminals also support \x1b[3J to clear the scrollback buffer,
43
+ // but we only clear the visible screen to match the behavior of `clear` on Unix.
44
+ process.stdout.write('\x1b[2J\x1b[H');
45
+ }
46
+
47
+ /**
48
+ * Clear the terminal screen on macOS.
49
+ *
50
+ * Uses the pure Node.js implementation since ANSI escape sequences
51
+ * work perfectly in Terminal.app, iTerm2, and all other macOS terminals.
52
+ *
53
+ * @param {string[]} args - Command line arguments (unused)
54
+ * @returns {Promise<void>}
55
+ */
56
+ async function do_c_macos(args) {
57
+ return do_c_nodejs(args);
58
+ }
59
+
60
+ /**
61
+ * Clear the terminal screen on Ubuntu.
62
+ *
63
+ * Uses the pure Node.js implementation since ANSI escape sequences
64
+ * work in all Ubuntu terminal emulators (GNOME Terminal, Konsole, xterm, etc.).
65
+ *
66
+ * @param {string[]} args - Command line arguments (unused)
67
+ * @returns {Promise<void>}
68
+ */
69
+ async function do_c_ubuntu(args) {
70
+ return do_c_nodejs(args);
71
+ }
72
+
73
+ /**
74
+ * Clear the terminal screen on Raspberry Pi OS.
75
+ *
76
+ * Uses the pure Node.js implementation since ANSI escape sequences
77
+ * work in Raspberry Pi OS terminals (LXTerminal, xterm, etc.).
78
+ *
79
+ * @param {string[]} args - Command line arguments (unused)
80
+ * @returns {Promise<void>}
81
+ */
82
+ async function do_c_raspbian(args) {
83
+ return do_c_nodejs(args);
84
+ }
85
+
86
+ /**
87
+ * Clear the terminal screen on Amazon Linux.
88
+ *
89
+ * Uses the pure Node.js implementation since ANSI escape sequences
90
+ * work in all Linux terminals, including those used with Amazon Linux.
91
+ *
92
+ * @param {string[]} args - Command line arguments (unused)
93
+ * @returns {Promise<void>}
94
+ */
95
+ async function do_c_amazon_linux(args) {
96
+ return do_c_nodejs(args);
97
+ }
98
+
99
+ /**
100
+ * Clear the terminal screen in Windows Command Prompt.
101
+ *
102
+ * Uses the pure Node.js implementation. Windows 10 and later support
103
+ * ANSI escape sequences natively in CMD when virtual terminal processing
104
+ * is enabled (which is the default in modern Windows).
105
+ *
106
+ * For older Windows versions, Node.js handles this automatically through
107
+ * its terminal handling layer.
108
+ *
109
+ * @param {string[]} args - Command line arguments (unused)
110
+ * @returns {Promise<void>}
111
+ */
112
+ async function do_c_cmd(args) {
113
+ return do_c_nodejs(args);
114
+ }
115
+
116
+ /**
117
+ * Clear the terminal screen in Windows PowerShell.
118
+ *
119
+ * Uses the pure Node.js implementation. PowerShell on Windows 10 and later
120
+ * fully supports ANSI escape sequences.
121
+ *
122
+ * @param {string[]} args - Command line arguments (unused)
123
+ * @returns {Promise<void>}
124
+ */
125
+ async function do_c_powershell(args) {
126
+ return do_c_nodejs(args);
127
+ }
128
+
8
129
  /**
9
- * Clears the terminal screen by outputting the appropriate
10
- * escape sequences for the current platform.
130
+ * Clear the terminal screen in Git Bash.
131
+ *
132
+ * Uses the pure Node.js implementation. Git Bash uses MinTTY or Windows Terminal,
133
+ * both of which fully support ANSI escape sequences.
11
134
  *
12
135
  * @param {string[]} args - Command line arguments (unused)
13
136
  * @returns {Promise<void>}
14
137
  */
15
- async function main(args) {
16
- // TODO: Implement terminal clear
138
+ async function do_c_gitbash(args) {
139
+ return do_c_nodejs(args);
140
+ }
141
+
142
+ /**
143
+ * Main entry point - detects environment and executes appropriate implementation.
144
+ *
145
+ * The "c" command clears the terminal screen, providing a clean workspace.
146
+ * This is a common developer shortcut that replaces the longer `clear` command
147
+ * (or `cls` on Windows) with a single character.
148
+ *
149
+ * The implementation uses ANSI escape sequences which work identically on all
150
+ * platforms, making this one of the simplest cross-platform scripts: every
151
+ * platform function simply delegates to the pure Node.js implementation.
152
+ *
153
+ * @param {string[]} args - Command line arguments (unused)
154
+ * @returns {Promise<void>}
155
+ */
156
+ async function do_c(args) {
157
+ const platform = os.detect();
158
+
159
+ const handlers = {
160
+ 'macos': do_c_macos,
161
+ 'ubuntu': do_c_ubuntu,
162
+ 'debian': do_c_ubuntu,
163
+ 'raspbian': do_c_raspbian,
164
+ 'amazon_linux': do_c_amazon_linux,
165
+ 'rhel': do_c_amazon_linux,
166
+ 'fedora': do_c_ubuntu,
167
+ 'linux': do_c_ubuntu,
168
+ 'wsl': do_c_ubuntu,
169
+ 'cmd': do_c_cmd,
170
+ 'windows': do_c_cmd,
171
+ 'powershell': do_c_powershell,
172
+ 'gitbash': do_c_gitbash
173
+ };
174
+
175
+ const handler = handlers[platform.type];
176
+ if (!handler) {
177
+ // Fallback: ANSI escape sequences work on most terminals, so try anyway
178
+ console.error(`Note: Platform '${platform.type}' not explicitly supported, attempting to clear...`);
179
+ await do_c_nodejs(args);
180
+ return;
181
+ }
182
+
183
+ await handler(args);
17
184
  }
18
185
 
19
- module.exports = { main };
186
+ module.exports = {
187
+ main: do_c,
188
+ do_c,
189
+ do_c_nodejs,
190
+ do_c_macos,
191
+ do_c_ubuntu,
192
+ do_c_raspbian,
193
+ do_c_amazon_linux,
194
+ do_c_cmd,
195
+ do_c_powershell,
196
+ do_c_gitbash
197
+ };
20
198
 
21
199
  if (require.main === module) {
22
- main(process.argv.slice(2));
200
+ do_c(process.argv.slice(2));
23
201
  }
@@ -1,24 +1,341 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * @fileoverview Curl JSON endpoint with pretty output.
4
+ * ccurl - Fetch a URL expecting JSON and pretty-print the output
5
+ *
6
+ * Migrated from legacy dotfiles alias.
7
+ * Original:
8
+ * ccurl() {
9
+ * if [ -z "$1" ]; then
10
+ * echo "Usage: ccurl <URL>"
11
+ * return 1
12
+ * fi
13
+ * curl -s -H "Accept: application/json" "$1" | jq
14
+ * }
15
+ *
16
+ * This script fetches a URL with an Accept: application/json header and
17
+ * pretty-prints the JSON response with syntax highlighting (if supported).
18
+ * Unlike the original bash version that required curl and jq to be installed,
19
+ * this Node.js implementation uses the built-in fetch() API and JSON methods,
20
+ * making it work on any system with Node.js 22+ without external dependencies.
21
+ *
5
22
  * @module scripts/ccurl
6
23
  */
7
24
 
25
+ const os = require('../utils/common/os');
26
+
27
+ /**
28
+ * Pretty-prints JSON with indentation.
29
+ *
30
+ * Takes a parsed JSON object and returns a formatted string with 2-space
31
+ * indentation. This replicates what jq does by default without any arguments.
32
+ *
33
+ * @param {any} data - The parsed JSON data to format
34
+ * @returns {string} The formatted JSON string
35
+ */
36
+ function prettyPrintJson(data) {
37
+ return JSON.stringify(data, null, 2);
38
+ }
39
+
40
+ /**
41
+ * Pure Node.js implementation using the built-in fetch() API.
42
+ *
43
+ * This implementation works on ALL platforms because Node.js 22+ includes
44
+ * fetch() natively. There is no need for platform-specific code - we can
45
+ * make HTTP requests and parse JSON entirely within Node.js.
46
+ *
47
+ * Key differences from the original bash version:
48
+ * - Uses native fetch() instead of shelling out to curl
49
+ * - Uses JSON.parse() and JSON.stringify() instead of jq
50
+ * - Works on any platform with Node.js 22+ without external tools
51
+ * - Provides better error handling and clearer error messages
52
+ *
53
+ * @param {string[]} args - Command line arguments
54
+ * @param {string} args.0 - URL to fetch (required)
55
+ * @returns {Promise<void>}
56
+ */
57
+ async function do_ccurl_nodejs(args) {
58
+ // Check if a URL was provided
59
+ const url = args[0];
60
+ if (!url) {
61
+ console.error('Usage: ccurl <URL>');
62
+ console.error('');
63
+ console.error('Fetches a URL expecting JSON and pretty-prints the response.');
64
+ console.error('');
65
+ console.error('Examples:');
66
+ console.error(' ccurl https://api.github.com/users/octocat');
67
+ console.error(' ccurl https://jsonplaceholder.typicode.com/posts/1');
68
+ process.exit(1);
69
+ }
70
+
71
+ // Validate that the URL looks reasonable
72
+ // Note: We don't use URL constructor validation because the user might
73
+ // provide a URL without a protocol, and we want a helpful error message
74
+ if (!url.startsWith('http://') && !url.startsWith('https://')) {
75
+ console.error(`Error: Invalid URL format: ${url}`);
76
+ console.error('');
77
+ console.error('URL must start with http:// or https://');
78
+ console.error('');
79
+ console.error('Example: ccurl https://api.example.com/data');
80
+ process.exit(1);
81
+ }
82
+
83
+ try {
84
+ // Make the HTTP request with Accept: application/json header
85
+ // This mimics the original: curl -s -H "Accept: application/json" "$1"
86
+ const response = await fetch(url, {
87
+ headers: {
88
+ 'Accept': 'application/json',
89
+ // Include a User-Agent to avoid being blocked by some APIs
90
+ 'User-Agent': 'ccurl/1.0 (devutils-cli)'
91
+ }
92
+ });
93
+
94
+ // Check if the response was successful
95
+ if (!response.ok) {
96
+ console.error(`Error: HTTP ${response.status} ${response.statusText}`);
97
+ // Try to get the response body for more context
98
+ try {
99
+ const errorBody = await response.text();
100
+ if (errorBody) {
101
+ // Try to parse and pretty-print if it's JSON
102
+ try {
103
+ const errorJson = JSON.parse(errorBody);
104
+ console.error('Response body:');
105
+ console.error(prettyPrintJson(errorJson));
106
+ } catch {
107
+ // Not JSON, just print the raw text (truncated if too long)
108
+ const truncated = errorBody.length > 500
109
+ ? errorBody.substring(0, 500) + '...'
110
+ : errorBody;
111
+ console.error('Response body:');
112
+ console.error(truncated);
113
+ }
114
+ }
115
+ } catch {
116
+ // Could not read response body, that's okay
117
+ }
118
+ process.exit(1);
119
+ }
120
+
121
+ // Get the response body as text first
122
+ const responseText = await response.text();
123
+
124
+ // Check if we got any content
125
+ if (!responseText || responseText.trim() === '') {
126
+ console.log('(empty response)');
127
+ return;
128
+ }
129
+
130
+ // Try to parse the response as JSON
131
+ let jsonData;
132
+ try {
133
+ jsonData = JSON.parse(responseText);
134
+ } catch (parseError) {
135
+ // Response is not valid JSON
136
+ console.error('Error: Response is not valid JSON');
137
+ console.error('');
138
+ console.error('Content-Type:', response.headers.get('content-type') || 'not specified');
139
+ console.error('');
140
+ console.error('Raw response (first 500 chars):');
141
+ const truncated = responseText.length > 500
142
+ ? responseText.substring(0, 500) + '...'
143
+ : responseText;
144
+ console.error(truncated);
145
+ process.exit(1);
146
+ }
147
+
148
+ // Pretty-print the JSON output
149
+ // This replicates what jq does by default
150
+ console.log(prettyPrintJson(jsonData));
151
+
152
+ } catch (error) {
153
+ // Handle network errors, DNS failures, etc.
154
+ if (error.cause && error.cause.code === 'ENOTFOUND') {
155
+ console.error(`Error: Could not resolve hostname for ${url}`);
156
+ console.error('');
157
+ console.error('Check that the URL is correct and you have network connectivity.');
158
+ } else if (error.cause && error.cause.code === 'ECONNREFUSED') {
159
+ console.error(`Error: Connection refused for ${url}`);
160
+ console.error('');
161
+ console.error('The server is not accepting connections on the specified port.');
162
+ } else if (error.cause && error.cause.code === 'ETIMEDOUT') {
163
+ console.error(`Error: Connection timed out for ${url}`);
164
+ console.error('');
165
+ console.error('The server took too long to respond.');
166
+ } else if (error.name === 'TypeError' && error.message.includes('fetch')) {
167
+ console.error(`Error: Invalid URL: ${url}`);
168
+ console.error('');
169
+ console.error('Make sure the URL is properly formatted.');
170
+ } else {
171
+ console.error(`Error fetching ${url}:`);
172
+ console.error(error.message || error);
173
+ }
174
+ process.exit(1);
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Fetch JSON from URL on macOS.
180
+ *
181
+ * Uses the pure Node.js implementation since fetch() works identically
182
+ * on all platforms. No macOS-specific code is needed.
183
+ *
184
+ * @param {string[]} args - Command line arguments
185
+ * @returns {Promise<void>}
186
+ */
187
+ async function do_ccurl_macos(args) {
188
+ return do_ccurl_nodejs(args);
189
+ }
190
+
191
+ /**
192
+ * Fetch JSON from URL on Ubuntu.
193
+ *
194
+ * Uses the pure Node.js implementation since fetch() works identically
195
+ * on all platforms. No Ubuntu-specific code is needed.
196
+ *
197
+ * @param {string[]} args - Command line arguments
198
+ * @returns {Promise<void>}
199
+ */
200
+ async function do_ccurl_ubuntu(args) {
201
+ return do_ccurl_nodejs(args);
202
+ }
203
+
204
+ /**
205
+ * Fetch JSON from URL on Raspberry Pi OS.
206
+ *
207
+ * Uses the pure Node.js implementation since fetch() works identically
208
+ * on all platforms. No Raspbian-specific code is needed.
209
+ *
210
+ * @param {string[]} args - Command line arguments
211
+ * @returns {Promise<void>}
212
+ */
213
+ async function do_ccurl_raspbian(args) {
214
+ return do_ccurl_nodejs(args);
215
+ }
216
+
8
217
  /**
9
- * Fetches a URL expecting JSON response and pretty-prints
10
- * the output using jq-style formatting.
218
+ * Fetch JSON from URL on Amazon Linux.
219
+ *
220
+ * Uses the pure Node.js implementation since fetch() works identically
221
+ * on all platforms. No Amazon Linux-specific code is needed.
222
+ *
223
+ * @param {string[]} args - Command line arguments
224
+ * @returns {Promise<void>}
225
+ */
226
+ async function do_ccurl_amazon_linux(args) {
227
+ return do_ccurl_nodejs(args);
228
+ }
229
+
230
+ /**
231
+ * Fetch JSON from URL on Windows Command Prompt.
232
+ *
233
+ * Uses the pure Node.js implementation since fetch() works identically
234
+ * on all platforms. No Windows CMD-specific code is needed.
235
+ *
236
+ * @param {string[]} args - Command line arguments
237
+ * @returns {Promise<void>}
238
+ */
239
+ async function do_ccurl_cmd(args) {
240
+ return do_ccurl_nodejs(args);
241
+ }
242
+
243
+ /**
244
+ * Fetch JSON from URL on Windows PowerShell.
245
+ *
246
+ * Uses the pure Node.js implementation since fetch() works identically
247
+ * on all platforms. No PowerShell-specific code is needed.
11
248
  *
12
249
  * @param {string[]} args - Command line arguments
13
- * @param {string} args.0 - URL to fetch
14
250
  * @returns {Promise<void>}
15
251
  */
16
- async function main(args) {
17
- // TODO: Implement JSON curl with pretty print
252
+ async function do_ccurl_powershell(args) {
253
+ return do_ccurl_nodejs(args);
254
+ }
255
+
256
+ /**
257
+ * Fetch JSON from URL on Git Bash.
258
+ *
259
+ * Uses the pure Node.js implementation since fetch() works identically
260
+ * on all platforms. No Git Bash-specific code is needed.
261
+ *
262
+ * @param {string[]} args - Command line arguments
263
+ * @returns {Promise<void>}
264
+ */
265
+ async function do_ccurl_gitbash(args) {
266
+ return do_ccurl_nodejs(args);
267
+ }
268
+
269
+ /**
270
+ * Main entry point - detects environment and executes appropriate implementation.
271
+ *
272
+ * The "ccurl" command fetches a URL expecting JSON and pretty-prints the output.
273
+ * This is useful for quickly inspecting API responses from the command line.
274
+ *
275
+ * Since this functionality is implemented entirely in Node.js using the built-in
276
+ * fetch() API, it works identically on all platforms. The platform detection is
277
+ * included for consistency with other scripts in this project, but all platforms
278
+ * delegate to the same Node.js implementation.
279
+ *
280
+ * Usage:
281
+ * ccurl <URL>
282
+ *
283
+ * Examples:
284
+ * ccurl https://api.github.com/users/octocat
285
+ * ccurl https://jsonplaceholder.typicode.com/posts/1
286
+ * ccurl https://httpbin.org/get
287
+ *
288
+ * @param {string[]} args - Command line arguments
289
+ * @returns {Promise<void>}
290
+ */
291
+ async function do_ccurl(args) {
292
+ const platform = os.detect();
293
+
294
+ const handlers = {
295
+ 'macos': do_ccurl_macos,
296
+ 'ubuntu': do_ccurl_ubuntu,
297
+ 'debian': do_ccurl_ubuntu,
298
+ 'raspbian': do_ccurl_raspbian,
299
+ 'amazon_linux': do_ccurl_amazon_linux,
300
+ 'rhel': do_ccurl_amazon_linux,
301
+ 'fedora': do_ccurl_ubuntu,
302
+ 'linux': do_ccurl_ubuntu,
303
+ 'wsl': do_ccurl_ubuntu,
304
+ 'cmd': do_ccurl_cmd,
305
+ 'windows': do_ccurl_cmd,
306
+ 'powershell': do_ccurl_powershell,
307
+ 'gitbash': do_ccurl_gitbash
308
+ };
309
+
310
+ const handler = handlers[platform.type];
311
+ if (!handler) {
312
+ console.error(`Platform '${platform.type}' is not supported for this command.`);
313
+ console.error('');
314
+ console.error('Supported platforms:');
315
+ console.error(' - macOS');
316
+ console.error(' - Ubuntu, Debian, and other Linux distributions');
317
+ console.error(' - Raspberry Pi OS');
318
+ console.error(' - Amazon Linux, RHEL, Fedora');
319
+ console.error(' - Windows (CMD, PowerShell, Git Bash)');
320
+ process.exit(1);
321
+ }
322
+
323
+ await handler(args);
18
324
  }
19
325
 
20
- module.exports = { main };
326
+ module.exports = {
327
+ main: do_ccurl,
328
+ do_ccurl,
329
+ do_ccurl_nodejs,
330
+ do_ccurl_macos,
331
+ do_ccurl_ubuntu,
332
+ do_ccurl_raspbian,
333
+ do_ccurl_amazon_linux,
334
+ do_ccurl_cmd,
335
+ do_ccurl_powershell,
336
+ do_ccurl_gitbash
337
+ };
21
338
 
22
339
  if (require.main === module) {
23
- main(process.argv.slice(2));
340
+ do_ccurl(process.argv.slice(2));
24
341
  }