@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,44 +1,1019 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * @fileoverview Install Draw.IO.
4
+ * @fileoverview Install Draw.io (diagrams.net) Desktop Application.
5
5
  * @module installs/drawio
6
+ *
7
+ * Draw.io is a free, open-source diagramming application for creating
8
+ * flowcharts, process diagrams, org charts, UML diagrams, ER diagrams,
9
+ * network diagrams, and more. The desktop application is built on Electron
10
+ * and provides a security-first approach where all diagram data remains
11
+ * local - no data is ever sent externally.
12
+ *
13
+ * Key features:
14
+ * - Offline-first: Works completely offline after installation
15
+ * - Privacy-focused: No analytics or external data transmission
16
+ * - Cross-platform: Available for macOS, Windows, and Linux
17
+ * - Free and open-source: Licensed under Apache 2.0
18
+ *
19
+ * IMPORTANT PLATFORM NOTES:
20
+ * - macOS: Installs Draw.io Desktop via Homebrew cask
21
+ * - Windows: Installs Draw.io Desktop via Chocolatey
22
+ * - Ubuntu/Debian: Installs Draw.io via Snap
23
+ * - Raspberry Pi OS: Installs via Snap or ARM64 .deb package
24
+ * - Amazon Linux: Installs via RPM package from GitHub releases
25
+ * - WSL: Installs via Snap (requires X11 server on Windows host)
26
+ * - Git Bash: Installs portable Windows version
6
27
  */
7
28
 
8
29
  const os = require('../utils/common/os');
30
+ const shell = require('../utils/common/shell');
31
+ const brew = require('../utils/macos/brew');
32
+ const macosApps = require('../utils/macos/apps');
33
+ const snap = require('../utils/ubuntu/snap');
34
+ const apt = require('../utils/ubuntu/apt');
35
+ const choco = require('../utils/windows/choco');
36
+
37
+ /**
38
+ * Whether this installer requires a desktop environment to function.
39
+ * Draw.io is a GUI diagramming application.
40
+ */
41
+ const REQUIRES_DESKTOP = true;
42
+
43
+ /**
44
+ * The Homebrew cask name for Draw.io Desktop on macOS.
45
+ * @constant {string}
46
+ */
47
+ const HOMEBREW_CASK_NAME = 'drawio';
48
+
49
+ /**
50
+ * The Chocolatey package name for Draw.io on Windows.
51
+ * @constant {string}
52
+ */
53
+ const CHOCO_PACKAGE_NAME = 'drawio';
54
+
55
+ /**
56
+ * The Snap package name for Draw.io on Linux.
57
+ * @constant {string}
58
+ */
59
+ const SNAP_PACKAGE_NAME = 'drawio';
60
+
61
+ /**
62
+ * The macOS application name as it appears in /Applications.
63
+ * @constant {string}
64
+ */
65
+ const MACOS_APP_NAME = 'draw.io';
66
+
67
+ /**
68
+ * The Windows executable path after installation.
69
+ * @constant {string}
70
+ */
71
+ const WINDOWS_EXE_PATH = 'C:\\Program Files\\draw.io\\draw.io.exe';
72
+
73
+ /**
74
+ * GitHub API URL for fetching the latest Draw.io release.
75
+ * Used for downloading .deb and .rpm packages directly.
76
+ * @constant {string}
77
+ */
78
+ const GITHUB_RELEASES_API = 'https://api.github.com/repos/jgraph/drawio-desktop/releases/latest';
79
+
80
+ /**
81
+ * Check if Draw.io is installed on macOS by looking for the application bundle.
82
+ *
83
+ * This function checks both /Applications and ~/Applications directories
84
+ * for the draw.io.app bundle.
85
+ *
86
+ * @returns {boolean} True if Draw.io is installed, false otherwise
87
+ */
88
+ function isInstalledMacOS() {
89
+ return macosApps.isAppInstalled(MACOS_APP_NAME);
90
+ }
91
+
92
+ /**
93
+ * Check if Draw.io is installed via Snap on Linux systems.
94
+ *
95
+ * This function queries the Snap package manager to determine
96
+ * if the drawio snap is installed.
97
+ *
98
+ * @returns {Promise<boolean>} True if Draw.io snap is installed, false otherwise
99
+ */
100
+ async function isInstalledSnap() {
101
+ return await snap.isSnapInstalled(SNAP_PACKAGE_NAME);
102
+ }
103
+
104
+ /**
105
+ * Check if Draw.io is installed via dpkg on Debian-based systems.
106
+ *
107
+ * This is used as a fallback check for systems where Draw.io was
108
+ * installed via .deb package rather than Snap.
109
+ *
110
+ * @returns {Promise<boolean>} True if Draw.io deb package is installed, false otherwise
111
+ */
112
+ async function isInstalledDeb() {
113
+ const result = await shell.exec('dpkg -l | grep -i drawio 2>/dev/null');
114
+ return result.code === 0 && result.stdout.includes('drawio');
115
+ }
116
+
117
+ /**
118
+ * Check if Draw.io is installed via RPM on RHEL-based systems.
119
+ *
120
+ * This function queries the RPM database to check if Draw.io
121
+ * was installed from the .rpm package.
122
+ *
123
+ * @returns {Promise<boolean>} True if Draw.io RPM is installed, false otherwise
124
+ */
125
+ async function isInstalledRpm() {
126
+ const result = await shell.exec('rpm -qa | grep -i drawio 2>/dev/null');
127
+ return result.code === 0 && result.stdout.includes('drawio');
128
+ }
129
+
130
+ /**
131
+ * Check if Draw.io is installed on Windows via Chocolatey.
132
+ *
133
+ * @returns {Promise<boolean>} True if Draw.io is installed via Chocolatey, false otherwise
134
+ */
135
+ async function isInstalledChoco() {
136
+ return await choco.isPackageInstalled(CHOCO_PACKAGE_NAME);
137
+ }
138
+
139
+ /**
140
+ * Check if Draw.io executable exists on Windows.
141
+ *
142
+ * This is a fallback check for cases where Draw.io was installed
143
+ * without using Chocolatey.
144
+ *
145
+ * @returns {Promise<boolean>} True if the Draw.io executable exists, false otherwise
146
+ */
147
+ async function isInstalledWindowsExe() {
148
+ const fs = require('fs');
149
+ return fs.existsSync(WINDOWS_EXE_PATH);
150
+ }
151
+
152
+ /**
153
+ * Get the version of Draw.io installed via Snap.
154
+ *
155
+ * @returns {Promise<string|null>} The installed version, or null if not installed
156
+ */
157
+ async function getSnapVersion() {
158
+ return await snap.getSnapVersion(SNAP_PACKAGE_NAME);
159
+ }
160
+
161
+ /**
162
+ * Install Draw.io Desktop on macOS using Homebrew.
163
+ *
164
+ * Prerequisites:
165
+ * - macOS 12 (Monterey) or later
166
+ * - Homebrew package manager installed
167
+ * - Apple Silicon (M1/M2/M3/M4) or Intel processor
168
+ *
169
+ * The installation uses the Homebrew cask 'drawio' which downloads and installs
170
+ * Draw.io Desktop to /Applications/draw.io.app. Homebrew automatically detects
171
+ * your processor architecture and installs the appropriate version.
172
+ *
173
+ * @returns {Promise<void>}
174
+ * @throws {Error} If Homebrew is not installed or installation fails
175
+ */
176
+ async function install_macos() {
177
+ console.log('Checking if Draw.io is already installed...');
178
+
179
+ // Check if Draw.io is already installed via application bundle
180
+ if (isInstalledMacOS()) {
181
+ const version = macosApps.getAppVersion(MACOS_APP_NAME);
182
+ if (version) {
183
+ console.log(`Draw.io ${version} is already installed, skipping installation.`);
184
+ } else {
185
+ console.log('Draw.io is already installed, skipping installation.');
186
+ }
187
+ return;
188
+ }
189
+
190
+ // Also check if the cask is installed (app may exist in non-standard location)
191
+ const caskInstalled = await brew.isCaskInstalled(HOMEBREW_CASK_NAME);
192
+ if (caskInstalled) {
193
+ console.log('Draw.io is already installed via Homebrew, skipping installation.');
194
+ return;
195
+ }
196
+
197
+ // Verify Homebrew is available
198
+ if (!brew.isInstalled()) {
199
+ throw new Error(
200
+ 'Homebrew is not installed. Please install Homebrew first using:\n' +
201
+ ' dev install homebrew\n' +
202
+ 'Then retry installing Draw.io.'
203
+ );
204
+ }
205
+
206
+ console.log('Installing Draw.io Desktop via Homebrew...');
207
+
208
+ // Install Draw.io cask
209
+ const result = await brew.installCask(HOMEBREW_CASK_NAME);
210
+
211
+ if (!result.success) {
212
+ throw new Error(
213
+ `Failed to install Draw.io via Homebrew.\n` +
214
+ `Output: ${result.output}\n\n` +
215
+ `Troubleshooting:\n` +
216
+ ` 1. Run 'brew update && brew cleanup' and retry\n` +
217
+ ` 2. Search for the cask: brew search drawio\n` +
218
+ ` 3. Try manual installation: brew reinstall --cask drawio`
219
+ );
220
+ }
221
+
222
+ // Verify installation succeeded
223
+ if (!isInstalledMacOS()) {
224
+ throw new Error(
225
+ 'Installation appeared to complete but Draw.io was not found.\n\n' +
226
+ 'Please try launching Draw.io from Applications or run:\n' +
227
+ ' open -a "draw.io"'
228
+ );
229
+ }
230
+
231
+ console.log('Draw.io Desktop installed successfully.');
232
+ console.log('');
233
+ console.log('To launch Draw.io:');
234
+ console.log(' - Open from Applications folder');
235
+ console.log(' - Or run: open -a "draw.io"');
236
+ }
9
237
 
10
238
  /**
11
- * Install Draw.IO across supported platforms.
239
+ * Install Draw.io on Ubuntu/Debian using Snap.
240
+ *
241
+ * Prerequisites:
242
+ * - Ubuntu 16.04 LTS or later, or Debian 9 or later
243
+ * - snapd package manager (pre-installed on Ubuntu 16.04+)
244
+ * - sudo privileges
245
+ *
246
+ * Snap is the recommended installation method for Ubuntu/Debian as it
247
+ * provides automatic updates and consistent behavior across distributions.
248
+ *
249
+ * @returns {Promise<void>}
250
+ * @throws {Error} If installation fails
251
+ */
252
+ async function install_ubuntu() {
253
+ console.log('Checking if Draw.io is already installed...');
254
+
255
+ // Check if already installed via Snap
256
+ if (await isInstalledSnap()) {
257
+ const version = await getSnapVersion();
258
+ if (version) {
259
+ console.log(`Draw.io ${version} is already installed via Snap, skipping installation.`);
260
+ } else {
261
+ console.log('Draw.io is already installed via Snap, skipping installation.');
262
+ }
263
+ return;
264
+ }
265
+
266
+ // Also check if installed via .deb package
267
+ if (await isInstalledDeb()) {
268
+ console.log('Draw.io is already installed via deb package, skipping installation.');
269
+ return;
270
+ }
271
+
272
+ // Ensure snapd is installed
273
+ if (!snap.isInstalled()) {
274
+ console.log('Installing snapd package manager...');
275
+ const snapdResult = await shell.exec(
276
+ 'sudo DEBIAN_FRONTEND=noninteractive apt-get update -y && ' +
277
+ 'sudo DEBIAN_FRONTEND=noninteractive apt-get install -y snapd'
278
+ );
279
+ if (snapdResult.code !== 0) {
280
+ throw new Error(
281
+ `Failed to install snapd.\n` +
282
+ `Output: ${snapdResult.stderr}\n\n` +
283
+ `Please try installing snapd manually:\n` +
284
+ ` sudo apt-get update && sudo apt-get install -y snapd`
285
+ );
286
+ }
287
+ }
288
+
289
+ console.log('Installing Draw.io via Snap...');
290
+
291
+ // Install Draw.io snap
292
+ const result = await snap.install(SNAP_PACKAGE_NAME);
293
+
294
+ if (!result.success) {
295
+ // Snap installation failed - provide guidance
296
+ throw new Error(
297
+ `Failed to install Draw.io via Snap.\n` +
298
+ `Output: ${result.output}\n\n` +
299
+ `Troubleshooting:\n` +
300
+ ` 1. Ensure snapd is running: sudo systemctl start snapd\n` +
301
+ ` 2. If on a minimal install, enable systemd for snaps\n` +
302
+ ` 3. Check architecture support: snap info drawio`
303
+ );
304
+ }
305
+
306
+ // Verify installation
307
+ if (!(await isInstalledSnap())) {
308
+ throw new Error(
309
+ 'Installation appeared to complete but Draw.io was not found.\n\n' +
310
+ 'Please verify with: snap list drawio'
311
+ );
312
+ }
313
+
314
+ const installedVersion = await getSnapVersion();
315
+ if (installedVersion) {
316
+ console.log(`Draw.io ${installedVersion} installed successfully.`);
317
+ } else {
318
+ console.log('Draw.io installed successfully.');
319
+ }
320
+ console.log('');
321
+ console.log('To launch Draw.io:');
322
+ console.log(' - Run: drawio');
323
+ console.log(' - Or find it in your application menu');
324
+ }
325
+
326
+ /**
327
+ * Install Draw.io on Raspberry Pi OS.
328
+ *
329
+ * Prerequisites:
330
+ * - Raspberry Pi OS (64-bit recommended) - Bookworm or Bullseye
331
+ * - Raspberry Pi 3B+ or later (64-bit capable hardware)
332
+ * - At least 2 GB RAM
333
+ * - sudo privileges
334
+ *
335
+ * This function first attempts Snap installation, then falls back to
336
+ * the ARM64 .deb package from GitHub releases if Snap is not available
337
+ * or does not support the architecture.
338
+ *
339
+ * IMPORTANT: Draw.io Desktop is an Electron application which can be
340
+ * resource-intensive. Ensure adequate RAM is available.
341
+ *
342
+ * @returns {Promise<void>}
343
+ * @throws {Error} If installation fails on 64-bit systems
344
+ */
345
+ async function install_raspbian() {
346
+ console.log('Checking if Draw.io is already installed...');
347
+
348
+ // Check if already installed via Snap
349
+ if (await isInstalledSnap()) {
350
+ const version = await getSnapVersion();
351
+ if (version) {
352
+ console.log(`Draw.io ${version} is already installed via Snap, skipping installation.`);
353
+ } else {
354
+ console.log('Draw.io is already installed via Snap, skipping installation.');
355
+ }
356
+ return;
357
+ }
358
+
359
+ // Check if installed via .deb package
360
+ if (await isInstalledDeb()) {
361
+ console.log('Draw.io is already installed via deb package, skipping installation.');
362
+ return;
363
+ }
364
+
365
+ // Check architecture
366
+ const archResult = await shell.exec('uname -m');
367
+ const arch = archResult.stdout.trim();
368
+
369
+ // 32-bit ARM is not supported
370
+ if (arch === 'armv7l' || arch === 'armhf') {
371
+ console.log('Draw.io Desktop is not available for 32-bit Raspberry Pi OS.');
372
+ console.log('');
373
+ console.log('Alternative: Use the web version at https://app.diagrams.net');
374
+ console.log('The web application provides the same functionality as the desktop app.');
375
+ return;
376
+ }
377
+
378
+ console.log(`Detected architecture: ${arch}`);
379
+
380
+ // Try Snap installation first (for 64-bit systems)
381
+ if (snap.isInstalled()) {
382
+ console.log('Attempting installation via Snap...');
383
+ const snapResult = await snap.install(SNAP_PACKAGE_NAME);
384
+
385
+ if (snapResult.success) {
386
+ const installedVersion = await getSnapVersion();
387
+ if (installedVersion) {
388
+ console.log(`Draw.io ${installedVersion} installed successfully via Snap.`);
389
+ } else {
390
+ console.log('Draw.io installed successfully via Snap.');
391
+ }
392
+ console.log('');
393
+ console.log('To launch Draw.io:');
394
+ console.log(' - Run: drawio');
395
+ console.log(' - Or find it in your application menu');
396
+ return;
397
+ }
398
+
399
+ console.log('Snap installation failed, falling back to .deb package...');
400
+ }
401
+
402
+ // Fallback: Install from ARM64 .deb package
403
+ console.log('Installing Draw.io from ARM64 .deb package...');
404
+
405
+ // Download the latest ARM64 .deb package from GitHub releases
406
+ console.log('Downloading latest Draw.io ARM64 package from GitHub...');
407
+ const downloadResult = await shell.exec(
408
+ `curl -s ${GITHUB_RELEASES_API} | ` +
409
+ `grep "browser_download_url.*arm64.*\\.deb" | ` +
410
+ `cut -d '"' -f 4 | ` +
411
+ `xargs -I {} curl -L -o /tmp/drawio-arm64.deb {}`
412
+ );
413
+
414
+ if (downloadResult.code !== 0) {
415
+ throw new Error(
416
+ `Failed to download Draw.io ARM64 package.\n` +
417
+ `Output: ${downloadResult.stderr}\n\n` +
418
+ `Please check your internet connection and try again.\n` +
419
+ `Alternatively, download manually from:\n` +
420
+ ` https://github.com/jgraph/drawio-desktop/releases`
421
+ );
422
+ }
423
+
424
+ // Update apt cache and install the package
425
+ console.log('Installing downloaded package...');
426
+ const installResult = await shell.exec(
427
+ 'sudo DEBIAN_FRONTEND=noninteractive apt-get update -y && ' +
428
+ 'sudo DEBIAN_FRONTEND=noninteractive apt-get install -y /tmp/drawio-arm64.deb'
429
+ );
430
+
431
+ if (installResult.code !== 0) {
432
+ // Try fixing dependencies and retrying
433
+ console.log('Attempting to fix dependencies...');
434
+ await shell.exec('sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -f');
435
+ const retryResult = await shell.exec(
436
+ 'sudo DEBIAN_FRONTEND=noninteractive apt-get install -y /tmp/drawio-arm64.deb'
437
+ );
438
+
439
+ if (retryResult.code !== 0) {
440
+ throw new Error(
441
+ `Failed to install Draw.io .deb package.\n` +
442
+ `Output: ${retryResult.stderr}\n\n` +
443
+ `Troubleshooting:\n` +
444
+ ` 1. Run: sudo apt-get install -f\n` +
445
+ ` 2. Check for missing dependencies\n` +
446
+ ` 3. Ensure you have enough disk space`
447
+ );
448
+ }
449
+ }
450
+
451
+ // Clean up downloaded file
452
+ await shell.exec('rm -f /tmp/drawio-arm64.deb');
453
+
454
+ // Verify installation
455
+ if (!(await isInstalledDeb())) {
456
+ throw new Error(
457
+ 'Installation appeared to complete but Draw.io was not found.\n\n' +
458
+ 'Please verify with: dpkg -l | grep drawio'
459
+ );
460
+ }
461
+
462
+ console.log('Draw.io installed successfully.');
463
+ console.log('');
464
+ console.log('To launch Draw.io:');
465
+ console.log(' - Run: drawio');
466
+ console.log(' - Or find it in your application menu');
467
+ console.log('');
468
+ console.log('NOTE: Draw.io is an Electron app which may be resource-intensive.');
469
+ console.log('For best performance, ensure at least 2 GB RAM is available.');
470
+ }
471
+
472
+ /**
473
+ * Install Draw.io on Amazon Linux/RHEL using RPM from GitHub releases.
474
+ *
475
+ * Prerequisites:
476
+ * - Amazon Linux 2023 (AL2023) or Amazon Linux 2 (AL2)
477
+ * - sudo privileges
478
+ * - curl installed
479
+ *
480
+ * NOTE: Draw.io is not available in Amazon Linux's default repositories.
481
+ * This function downloads and installs the x86_64 RPM package directly
482
+ * from GitHub releases.
483
+ *
484
+ * IMPORTANT: Draw.io is a GUI application requiring an X11 display.
485
+ * On headless servers, use X11 forwarding or the web version.
486
+ *
487
+ * @returns {Promise<void>}
488
+ * @throws {Error} If installation fails
489
+ */
490
+ async function install_amazon_linux() {
491
+ console.log('Checking if Draw.io is already installed...');
492
+
493
+ // Check if already installed via RPM
494
+ if (await isInstalledRpm()) {
495
+ console.log('Draw.io is already installed, skipping installation.');
496
+ return;
497
+ }
498
+
499
+ // Detect package manager (dnf for AL2023, yum for AL2)
500
+ const hasDnf = shell.commandExists('dnf');
501
+ const hasYum = shell.commandExists('yum');
502
+ const packageManager = hasDnf ? 'dnf' : (hasYum ? 'yum' : null);
503
+
504
+ if (!packageManager) {
505
+ throw new Error(
506
+ 'Neither dnf nor yum package manager found.\n' +
507
+ 'This installer supports Amazon Linux 2023 (dnf) and Amazon Linux 2 (yum).'
508
+ );
509
+ }
510
+
511
+ console.log(`Detected package manager: ${packageManager}`);
512
+
513
+ // Install dependencies
514
+ console.log('Installing required dependencies...');
515
+ const depsResult = await shell.exec(
516
+ `sudo ${packageManager} install -y wget curl libxkbfile libsecret nss gtk3 libdrm mesa-libgbm alsa-lib`
517
+ );
518
+ if (depsResult.code !== 0) {
519
+ console.log('Warning: Some dependencies may not have been installed.');
520
+ console.log('Continuing with installation...');
521
+ }
522
+
523
+ // Download the latest x86_64 RPM package from GitHub releases
524
+ console.log('Downloading latest Draw.io RPM package from GitHub...');
525
+ const downloadResult = await shell.exec(
526
+ `curl -s ${GITHUB_RELEASES_API} | ` +
527
+ `grep "browser_download_url.*x86_64.*\\.rpm" | ` +
528
+ `cut -d '"' -f 4 | ` +
529
+ `xargs -I {} curl -L -o /tmp/drawio.rpm {}`
530
+ );
531
+
532
+ if (downloadResult.code !== 0) {
533
+ throw new Error(
534
+ `Failed to download Draw.io RPM package.\n` +
535
+ `Output: ${downloadResult.stderr}\n\n` +
536
+ `Please check your internet connection and try again.\n` +
537
+ `Alternatively, download manually from:\n` +
538
+ ` https://github.com/jgraph/drawio-desktop/releases`
539
+ );
540
+ }
541
+
542
+ // Install the RPM package
543
+ console.log('Installing Draw.io RPM package...');
544
+ const installResult = await shell.exec(
545
+ `sudo ${packageManager} install -y /tmp/drawio.rpm`
546
+ );
547
+
548
+ if (installResult.code !== 0) {
549
+ throw new Error(
550
+ `Failed to install Draw.io RPM package.\n` +
551
+ `Output: ${installResult.stderr}\n\n` +
552
+ `Troubleshooting:\n` +
553
+ ` 1. Check for missing dependencies: sudo ${packageManager} install -y gtk3 libdrm mesa-libgbm alsa-lib\n` +
554
+ ` 2. Verify the download: ls -la /tmp/drawio.rpm\n` +
555
+ ` 3. Try manual installation: sudo rpm -ivh /tmp/drawio.rpm`
556
+ );
557
+ }
558
+
559
+ // Clean up downloaded file
560
+ await shell.exec('rm -f /tmp/drawio.rpm');
561
+
562
+ // Verify installation
563
+ if (!(await isInstalledRpm())) {
564
+ throw new Error(
565
+ 'Installation appeared to complete but Draw.io was not found.\n\n' +
566
+ 'Please verify with: rpm -qa | grep drawio'
567
+ );
568
+ }
569
+
570
+ console.log('Draw.io installed successfully.');
571
+ console.log('');
572
+ console.log('To launch Draw.io (requires X11 display):');
573
+ console.log(' - Run: drawio');
574
+ console.log('');
575
+ console.log('NOTE: Draw.io is a GUI application. On headless servers:');
576
+ console.log(' - Use X11 forwarding: ssh -X user@host');
577
+ console.log(' - Or use the web version: https://app.diagrams.net');
578
+ }
579
+
580
+ /**
581
+ * Install Draw.io on Windows using Chocolatey.
582
+ *
583
+ * Prerequisites:
584
+ * - Windows 10 version 1809 or later (64-bit), or Windows 11
585
+ * - Administrator PowerShell or Command Prompt
586
+ * - Chocolatey package manager installed
587
+ *
588
+ * The Chocolatey package installs Draw.io Desktop silently with
589
+ * the /S flag for fully non-interactive installation.
590
+ *
591
+ * @returns {Promise<void>}
592
+ * @throws {Error} If Chocolatey is not installed or installation fails
593
+ */
594
+ async function install_windows() {
595
+ console.log('Checking if Draw.io is already installed...');
596
+
597
+ // Check if Draw.io is already installed via Chocolatey
598
+ if (await isInstalledChoco()) {
599
+ console.log('Draw.io is already installed via Chocolatey, skipping installation.');
600
+ return;
601
+ }
602
+
603
+ // Check if Draw.io executable exists (installed via other method)
604
+ if (await isInstalledWindowsExe()) {
605
+ console.log('Draw.io is already installed, skipping installation.');
606
+ return;
607
+ }
608
+
609
+ // Verify Chocolatey is available
610
+ if (!choco.isInstalled()) {
611
+ throw new Error(
612
+ 'Chocolatey is not installed. Please install Chocolatey first:\n\n' +
613
+ 'Run the following in an Administrator PowerShell:\n' +
614
+ ' Set-ExecutionPolicy Bypass -Scope Process -Force; ' +
615
+ '[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; ' +
616
+ 'iex ((New-Object System.Net.WebClient).DownloadString(\'https://community.chocolatey.org/install.ps1\'))\n\n' +
617
+ 'Then retry installing Draw.io.'
618
+ );
619
+ }
620
+
621
+ console.log('Installing Draw.io via Chocolatey...');
622
+ console.log('This may take a few minutes...');
623
+
624
+ // Install Draw.io via Chocolatey
625
+ const result = await choco.install(CHOCO_PACKAGE_NAME);
626
+
627
+ if (!result.success) {
628
+ throw new Error(
629
+ `Failed to install Draw.io via Chocolatey.\n` +
630
+ `Output: ${result.output}\n\n` +
631
+ `Troubleshooting:\n` +
632
+ ` 1. Ensure you are running as Administrator\n` +
633
+ ` 2. Try: choco install drawio -y --force\n` +
634
+ ` 3. Check Chocolatey logs: C:\\ProgramData\\chocolatey\\logs`
635
+ );
636
+ }
637
+
638
+ console.log('Draw.io installed successfully.');
639
+ console.log('');
640
+ console.log('To launch Draw.io:');
641
+ console.log(' - Find it in the Start Menu');
642
+ console.log(' - Or run: start "" "C:\\Program Files\\draw.io\\draw.io.exe"');
643
+ }
644
+
645
+ /**
646
+ * Install Draw.io on Ubuntu running in WSL (Windows Subsystem for Linux).
647
+ *
648
+ * Prerequisites:
649
+ * - Windows 10 version 2004 or higher, or Windows 11
650
+ * - WSL 2 enabled with Ubuntu distribution installed
651
+ * - sudo privileges within WSL
652
+ * - X11 server running on Windows (for GUI applications)
653
+ *
654
+ * IMPORTANT: Draw.io is a GUI application. Running it in WSL requires
655
+ * an X11 server on Windows (such as VcXsrv or X410) to display the window.
656
+ *
657
+ * This function installs Draw.io via Snap within WSL, similar to the
658
+ * standard Ubuntu installation.
659
+ *
660
+ * @returns {Promise<void>}
661
+ * @throws {Error} If installation fails
662
+ */
663
+ async function install_ubuntu_wsl() {
664
+ console.log('Detected Ubuntu running in WSL (Windows Subsystem for Linux).');
665
+ console.log('');
666
+ console.log('IMPORTANT: Draw.io is a GUI application.');
667
+ console.log('You will need an X11 server running on Windows to display it.');
668
+ console.log('Consider installing VcXsrv: choco install vcxsrv (from Windows)');
669
+ console.log('');
670
+
671
+ // Check if already installed via Snap
672
+ if (await isInstalledSnap()) {
673
+ const version = await getSnapVersion();
674
+ if (version) {
675
+ console.log(`Draw.io ${version} is already installed via Snap, skipping installation.`);
676
+ } else {
677
+ console.log('Draw.io is already installed via Snap, skipping installation.');
678
+ }
679
+ return;
680
+ }
681
+
682
+ // Check if installed via .deb package
683
+ if (await isInstalledDeb()) {
684
+ console.log('Draw.io is already installed via deb package, skipping installation.');
685
+ return;
686
+ }
687
+
688
+ // Ensure snapd is installed
689
+ if (!snap.isInstalled()) {
690
+ console.log('Installing snapd package manager...');
691
+ const snapdResult = await shell.exec(
692
+ 'sudo DEBIAN_FRONTEND=noninteractive apt-get update -y && ' +
693
+ 'sudo DEBIAN_FRONTEND=noninteractive apt-get install -y snapd'
694
+ );
695
+ if (snapdResult.code !== 0) {
696
+ throw new Error(
697
+ `Failed to install snapd.\n` +
698
+ `Output: ${snapdResult.stderr}\n\n` +
699
+ `Note: Snap requires systemd which may not be enabled in WSL.\n` +
700
+ `To enable systemd, add to /etc/wsl.conf:\n` +
701
+ ` [boot]\n` +
702
+ ` systemd=true\n` +
703
+ `Then restart WSL: wsl --shutdown (from Windows PowerShell)`
704
+ );
705
+ }
706
+ }
707
+
708
+ console.log('Installing Draw.io via Snap...');
709
+
710
+ // Install Draw.io snap
711
+ const result = await snap.install(SNAP_PACKAGE_NAME);
712
+
713
+ if (!result.success) {
714
+ throw new Error(
715
+ `Failed to install Draw.io via Snap.\n` +
716
+ `Output: ${result.output}\n\n` +
717
+ `WSL Troubleshooting:\n` +
718
+ ` 1. Ensure systemd is enabled in /etc/wsl.conf\n` +
719
+ ` 2. Restart WSL: wsl --shutdown (from Windows)\n` +
720
+ ` 3. Verify snap is working: snap list\n` +
721
+ ` 4. Try: sudo snap install core && sudo snap install drawio`
722
+ );
723
+ }
724
+
725
+ // Verify installation
726
+ if (!(await isInstalledSnap())) {
727
+ throw new Error(
728
+ 'Installation appeared to complete but Draw.io was not found.\n\n' +
729
+ 'Please verify with: snap list drawio'
730
+ );
731
+ }
732
+
733
+ const installedVersion = await getSnapVersion();
734
+ if (installedVersion) {
735
+ console.log(`Draw.io ${installedVersion} installed successfully.`);
736
+ } else {
737
+ console.log('Draw.io installed successfully.');
738
+ }
739
+ console.log('');
740
+ console.log('To launch Draw.io:');
741
+ console.log(' 1. Ensure an X11 server is running on Windows');
742
+ console.log(' 2. Set DISPLAY variable (for WSL 2):');
743
+ console.log(' export DISPLAY=$(grep -m 1 nameserver /etc/resolv.conf | awk \'{print $2}\'):0');
744
+ console.log(' 3. Run: drawio');
745
+ console.log('');
746
+ console.log('If you experience display issues, try:');
747
+ console.log(' drawio --disable-gpu');
748
+ }
749
+
750
+ /**
751
+ * Install Draw.io from Git Bash on Windows using portable installation.
752
+ *
753
+ * Git Bash runs within Windows, so this function downloads and extracts
754
+ * the portable Windows ZIP package from GitHub releases.
755
+ *
756
+ * Prerequisites:
757
+ * - Windows 10 or Windows 11 (64-bit)
758
+ * - Git Bash installed (comes with Git for Windows)
759
+ * - Internet connection to download the portable package
760
+ *
761
+ * @returns {Promise<void>}
762
+ * @throws {Error} If installation fails
763
+ */
764
+ async function install_gitbash() {
765
+ console.log('Detected Git Bash on Windows.');
766
+ console.log('Installing Draw.io portable version...');
767
+ console.log('');
768
+
769
+ // Define portable app directory
770
+ const homeDir = os.getHomeDir();
771
+ const portableDir = `${homeDir}/portable-apps/drawio`;
772
+
773
+ // Check if already installed
774
+ const checkResult = await shell.exec(`ls "${portableDir}/draw.io.exe" 2>/dev/null`);
775
+ if (checkResult.code === 0) {
776
+ console.log('Draw.io is already installed in portable-apps, skipping installation.');
777
+ console.log('');
778
+ console.log('To launch Draw.io:');
779
+ console.log(` ${portableDir}/draw.io.exe`);
780
+ return;
781
+ }
782
+
783
+ // Also check if installed via Chocolatey/Windows installer
784
+ const winExeResult = await shell.exec('ls "C:/Program Files/draw.io/draw.io.exe" 2>/dev/null');
785
+ if (winExeResult.code === 0) {
786
+ console.log('Draw.io is already installed on Windows, skipping installation.');
787
+ console.log('');
788
+ console.log('To launch Draw.io from Git Bash:');
789
+ console.log(' "/c/Program Files/draw.io/draw.io.exe"');
790
+ return;
791
+ }
792
+
793
+ // Create portable apps directory
794
+ console.log('Creating portable apps directory...');
795
+ await shell.exec(`mkdir -p "${homeDir}/portable-apps"`);
796
+
797
+ // Download the latest Windows ZIP package
798
+ console.log('Downloading latest Draw.io portable package from GitHub...');
799
+ const downloadResult = await shell.exec(
800
+ `curl -L -o /tmp/drawio.zip "$(curl -s ${GITHUB_RELEASES_API} | ` +
801
+ `grep 'browser_download_url.*windows\\.zip' | head -1 | cut -d '"' -f 4)"`
802
+ );
803
+
804
+ if (downloadResult.code !== 0) {
805
+ throw new Error(
806
+ `Failed to download Draw.io portable package.\n` +
807
+ `Output: ${downloadResult.stderr}\n\n` +
808
+ `Please check your internet connection and try again.\n` +
809
+ `Alternatively, download manually from:\n` +
810
+ ` https://github.com/jgraph/drawio-desktop/releases`
811
+ );
812
+ }
813
+
814
+ // Extract the ZIP file
815
+ console.log('Extracting Draw.io...');
816
+
817
+ // Check if unzip is available
818
+ if (shell.commandExists('unzip')) {
819
+ const extractResult = await shell.exec(
820
+ `unzip -q /tmp/drawio.zip -d "${portableDir}"`
821
+ );
822
+ if (extractResult.code !== 0) {
823
+ throw new Error(
824
+ `Failed to extract Draw.io package.\n` +
825
+ `Output: ${extractResult.stderr}`
826
+ );
827
+ }
828
+ } else {
829
+ // Use PowerShell as fallback
830
+ console.log('Using PowerShell to extract (unzip not available)...');
831
+ const psExtractResult = await shell.exec(
832
+ `powershell.exe -command "Expand-Archive -Path '/tmp/drawio.zip' -DestinationPath '${portableDir}' -Force"`
833
+ );
834
+ if (psExtractResult.code !== 0) {
835
+ throw new Error(
836
+ `Failed to extract Draw.io package.\n` +
837
+ `Output: ${psExtractResult.stderr}`
838
+ );
839
+ }
840
+ }
841
+
842
+ // Clean up downloaded file
843
+ await shell.exec('rm -f /tmp/drawio.zip');
844
+
845
+ // Unblock the executable (Windows security)
846
+ console.log('Unblocking executable...');
847
+ await shell.exec(
848
+ `powershell.exe -command "Get-ChildItem -Path '${portableDir}' -Recurse | Unblock-File" 2>/dev/null`
849
+ );
850
+
851
+ // Verify installation
852
+ const verifyResult = await shell.exec(`ls "${portableDir}/draw.io.exe" 2>/dev/null`);
853
+ if (verifyResult.code !== 0) {
854
+ // Files might be in a subdirectory
855
+ const findResult = await shell.exec(`find "${portableDir}" -name "draw.io.exe" 2>/dev/null`);
856
+ if (findResult.code !== 0 || !findResult.stdout.trim()) {
857
+ throw new Error(
858
+ 'Installation appeared to complete but draw.io.exe was not found.\n\n' +
859
+ `Please check: ls "${portableDir}"`
860
+ );
861
+ }
862
+ console.log(`Note: Executable found at: ${findResult.stdout.trim()}`);
863
+ }
864
+
865
+ console.log('Draw.io installed successfully.');
866
+ console.log('');
867
+ console.log('To launch Draw.io:');
868
+ console.log(` "${portableDir}/draw.io.exe"`);
869
+ console.log('');
870
+ console.log('To add an alias, add this to your ~/.bashrc:');
871
+ console.log(` alias drawio='"${portableDir}/draw.io.exe"'`);
872
+ }
873
+
874
+ /**
875
+ * Check if Draw.io is currently installed on the system.
876
+ *
877
+ * This function checks for Draw.io installation across all supported platforms:
878
+ * - macOS: Checks for draw.io.app via Homebrew cask or application bundle
879
+ * - Windows: Checks for Draw.io via Chocolatey or executable path
880
+ * - Linux: Checks for Draw.io via Snap, dpkg, or RPM
881
+ *
882
+ * @returns {Promise<boolean>} True if Draw.io is installed, false otherwise
883
+ */
884
+ async function isInstalled() {
885
+ const platform = os.detect();
886
+
887
+ if (platform.type === 'macos') {
888
+ // Check if Draw.io app bundle exists
889
+ if (isInstalledMacOS()) {
890
+ return true;
891
+ }
892
+ // Also check via Homebrew cask
893
+ return await brew.isCaskInstalled(HOMEBREW_CASK_NAME);
894
+ }
895
+
896
+ if (platform.type === 'windows') {
897
+ // Check via Chocolatey or executable path
898
+ if (await isInstalledChoco()) {
899
+ return true;
900
+ }
901
+ return await isInstalledWindowsExe();
902
+ }
903
+
904
+ if (platform.type === 'gitbash') {
905
+ // Git Bash uses portable version, check in portable-apps directory
906
+ const homeDir = os.getHomeDir();
907
+ const portableDir = `${homeDir}/portable-apps/drawio`;
908
+ const checkResult = await shell.exec(`ls "${portableDir}/draw.io.exe" 2>/dev/null`);
909
+ if (checkResult.code === 0) {
910
+ return true;
911
+ }
912
+ // Also check Windows installation
913
+ return await isInstalledWindowsExe();
914
+ }
915
+
916
+ // Linux platforms: Check Snap first, then deb, then rpm
917
+ if (await isInstalledSnap()) {
918
+ return true;
919
+ }
920
+ if (await isInstalledDeb()) {
921
+ return true;
922
+ }
923
+ return await isInstalledRpm();
924
+ }
925
+
926
+ /**
927
+ * Check if this installer is supported on the current platform.
928
+ *
929
+ * Draw.io can be installed on all supported platforms:
930
+ * - macOS (Draw.io Desktop via Homebrew cask)
931
+ * - Ubuntu/Debian (Draw.io via Snap)
932
+ * - Raspberry Pi OS (Draw.io via Snap or ARM64 .deb package)
933
+ * - Amazon Linux/RHEL/Fedora (Draw.io via RPM from GitHub releases)
934
+ * - Windows (Draw.io Desktop via Chocolatey)
935
+ * - WSL (Draw.io via Snap, requires X11 server)
936
+ * - Git Bash (Draw.io portable Windows version)
937
+ *
938
+ * @returns {boolean} True if installation is supported on this platform
939
+ */
940
+ function isEligible() {
941
+ const platform = os.detect();
942
+ const supportedPlatforms = ['macos', 'ubuntu', 'debian', 'wsl', 'raspbian', 'amazon_linux', 'rhel', 'fedora', 'windows', 'gitbash'];
943
+ if (!supportedPlatforms.includes(platform.type)) {
944
+ return false;
945
+ }
946
+ if (REQUIRES_DESKTOP && !os.isDesktopAvailable()) {
947
+ return false;
948
+ }
949
+ return true;
950
+ }
951
+
952
+ /**
953
+ * Main installation entry point.
954
+ *
955
+ * Detects the current platform and runs the appropriate installer function.
956
+ * Handles platform-specific mappings to ensure all supported platforms
957
+ * have appropriate installation logic.
958
+ *
959
+ * Supported platforms:
960
+ * - macOS: Draw.io Desktop via Homebrew cask
961
+ * - Ubuntu/Debian: Draw.io via Snap
962
+ * - Raspberry Pi OS: Draw.io via Snap or ARM64 .deb package
963
+ * - Amazon Linux/RHEL: Draw.io via RPM from GitHub releases
964
+ * - Windows: Draw.io Desktop via Chocolatey
965
+ * - WSL (Ubuntu): Draw.io via Snap (requires X11 server)
966
+ * - Git Bash: Draw.io portable Windows version
12
967
  *
13
968
  * @returns {Promise<void>}
14
969
  */
15
970
  async function install() {
16
971
  const platform = os.detect();
17
972
 
18
- switch (platform.type) {
19
- case 'macos':
20
- // TODO: Implement macOS installation
21
- break;
22
- case 'debian':
23
- // TODO: Implement Debian/Ubuntu installation
24
- break;
25
- case 'rhel':
26
- // TODO: Implement RHEL/Amazon Linux installation
27
- break;
28
- case 'windows-wsl':
29
- // TODO: Implement WSL installation
30
- break;
31
- case 'windows':
32
- // TODO: Implement Windows installation
33
- break;
34
- default:
35
- console.error(`Unsupported platform: ${platform.type}`);
36
- process.exit(1);
37
- }
38
- }
39
-
40
- module.exports = { install };
973
+ // Map platform types to their installer functions
974
+ // This mapping handles aliases (e.g., debian maps to ubuntu)
975
+ const installers = {
976
+ 'macos': install_macos,
977
+ 'ubuntu': install_ubuntu,
978
+ 'debian': install_ubuntu,
979
+ 'wsl': install_ubuntu_wsl,
980
+ 'raspbian': install_raspbian,
981
+ 'amazon_linux': install_amazon_linux,
982
+ 'rhel': install_amazon_linux,
983
+ 'fedora': install_amazon_linux,
984
+ 'windows': install_windows,
985
+ 'gitbash': install_gitbash
986
+ };
987
+
988
+ const installer = installers[platform.type];
989
+
990
+ if (!installer) {
991
+ console.log(`Draw.io is not available for ${platform.type}.`);
992
+ return;
993
+ }
994
+
995
+ await installer();
996
+ }
997
+
998
+ // Export all functions for use as a module and for testing
999
+ module.exports = {
1000
+ REQUIRES_DESKTOP,
1001
+ install,
1002
+ isInstalled,
1003
+ isEligible,
1004
+ install_macos,
1005
+ install_ubuntu,
1006
+ install_ubuntu_wsl,
1007
+ install_raspbian,
1008
+ install_amazon_linux,
1009
+ install_windows,
1010
+ install_gitbash
1011
+ };
41
1012
 
1013
+ // Allow direct execution: node drawio.js
42
1014
  if (require.main === module) {
43
- install();
1015
+ install().catch(err => {
1016
+ console.error(err.message);
1017
+ process.exit(1);
1018
+ });
44
1019
  }