@fredlackey/devutils 0.0.18 → 0.1.0
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.
- package/README.md +214 -141
- package/package.json +8 -83
- package/src/api/loader.js +229 -0
- package/src/api/registry.json +62 -0
- package/src/cli.js +293 -60
- package/src/commands/ai/index.js +16 -0
- package/src/commands/ai/launch.js +112 -0
- package/src/commands/ai/list.js +54 -0
- package/src/commands/ai/resume.js +70 -0
- package/src/commands/ai/sessions.js +121 -0
- package/src/commands/ai/set.js +131 -0
- package/src/commands/ai/show.js +74 -0
- package/src/commands/ai/tools.js +46 -0
- package/src/commands/alias/add.js +93 -0
- package/src/commands/alias/helpers.js +107 -0
- package/src/commands/alias/index.js +14 -0
- package/src/commands/alias/list.js +55 -0
- package/src/commands/alias/remove.js +62 -0
- package/src/commands/alias/sync.js +109 -0
- package/src/commands/api/disable.js +73 -0
- package/src/commands/api/enable.js +148 -0
- package/src/commands/api/index.js +15 -0
- package/src/commands/api/list.js +66 -0
- package/src/commands/api/update.js +87 -0
- package/src/commands/auth/index.js +15 -0
- package/src/commands/auth/list.js +49 -0
- package/src/commands/auth/login.js +384 -0
- package/src/commands/auth/logout.js +111 -0
- package/src/commands/auth/refresh.js +184 -0
- package/src/commands/auth/services.js +169 -0
- package/src/commands/auth/status.js +104 -0
- package/src/commands/config/export.js +224 -0
- package/src/commands/config/get.js +52 -0
- package/src/commands/config/import.js +308 -0
- package/src/commands/config/index.js +17 -0
- package/src/commands/config/init.js +143 -0
- package/src/commands/config/reset.js +57 -0
- package/src/commands/config/set.js +93 -0
- package/src/commands/config/show.js +35 -0
- package/src/commands/help.js +338 -0
- package/src/commands/identity/add.js +133 -0
- package/src/commands/identity/index.js +17 -0
- package/src/commands/identity/link.js +76 -0
- package/src/commands/identity/list.js +48 -0
- package/src/commands/identity/remove.js +72 -0
- package/src/commands/identity/show.js +65 -0
- package/src/commands/identity/sync.js +172 -0
- package/src/commands/identity/unlink.js +57 -0
- package/src/commands/ignore/add.js +165 -0
- package/src/commands/ignore/index.js +14 -0
- package/src/commands/ignore/list.js +89 -0
- package/src/commands/ignore/markers.js +43 -0
- package/src/commands/ignore/remove.js +164 -0
- package/src/commands/ignore/show.js +169 -0
- package/src/commands/machine/detect.js +122 -0
- package/src/commands/machine/index.js +14 -0
- package/src/commands/machine/list.js +74 -0
- package/src/commands/machine/set.js +106 -0
- package/src/commands/machine/show.js +35 -0
- package/src/commands/schema.js +152 -0
- package/src/commands/search/collections.js +134 -0
- package/src/commands/search/get.js +71 -0
- package/src/commands/search/index-cmd.js +54 -0
- package/src/commands/search/index.js +21 -0
- package/src/commands/search/keyword.js +60 -0
- package/src/commands/search/qmd.js +70 -0
- package/src/commands/search/query.js +64 -0
- package/src/commands/search/semantic.js +62 -0
- package/src/commands/search/status.js +46 -0
- package/src/commands/status.js +224 -171
- package/src/commands/tools/check.js +79 -0
- package/src/commands/tools/index.js +14 -0
- package/src/commands/tools/install.js +110 -0
- package/src/commands/tools/list.js +91 -0
- package/src/commands/tools/search.js +60 -0
- package/src/commands/update.js +83 -112
- package/src/commands/util/add.js +151 -0
- package/src/commands/util/index.js +15 -0
- package/src/commands/util/list.js +97 -0
- package/src/commands/util/remove.js +76 -0
- package/src/commands/util/run.js +79 -0
- package/src/commands/util/show.js +67 -0
- package/src/commands/version.js +21 -88
- package/src/installers/_template.js +104 -0
- package/src/installers/git.js +150 -0
- package/src/installers/homebrew.js +190 -0
- package/src/installers/node.js +223 -0
- package/src/installers/registry.json +29 -0
- package/src/lib/config.js +125 -0
- package/src/lib/detect.js +74 -0
- package/src/lib/errors.js +114 -0
- package/src/lib/github.js +315 -0
- package/src/lib/installer.js +225 -0
- package/src/lib/output.js +239 -0
- package/src/lib/platform.js +112 -0
- package/src/lib/platforms/amazon-linux.js +41 -0
- package/src/lib/platforms/gitbash.js +46 -0
- package/src/lib/platforms/macos.js +45 -0
- package/src/lib/platforms/raspbian.js +41 -0
- package/src/lib/platforms/ubuntu.js +39 -0
- package/src/lib/platforms/windows.js +45 -0
- package/src/lib/prompt.js +161 -0
- package/src/lib/schema.js +211 -0
- package/src/lib/shell.js +75 -0
- package/src/patterns/gitignore/claude-code.txt +25 -0
- package/src/patterns/gitignore/docker.txt +15 -0
- package/src/patterns/gitignore/go.txt +24 -0
- package/src/patterns/gitignore/java.txt +38 -0
- package/src/patterns/gitignore/jetbrains.txt +26 -0
- package/src/patterns/gitignore/linux.txt +18 -0
- package/src/patterns/gitignore/macos.txt +27 -0
- package/src/patterns/gitignore/node.txt +51 -0
- package/src/patterns/gitignore/python.txt +55 -0
- package/src/patterns/gitignore/rust.txt +14 -0
- package/src/patterns/gitignore/terraform.txt +30 -0
- package/src/patterns/gitignore/vscode.txt +15 -0
- package/src/patterns/gitignore/windows.txt +25 -0
- package/src/utils/clone/index.js +165 -0
- package/src/utils/git-push/index.js +230 -0
- package/src/utils/git-status/index.js +116 -0
- package/src/utils/git-status/unix.sh +75 -0
- package/src/utils/registry.json +41 -0
- package/bin/dev.js +0 -16
- package/files/README.md +0 -0
- package/files/claude/.claude/commands/setup-context.md +0 -3
- package/files/monorepos/_archive/README.md +0 -36
- package/files/monorepos/_legacy/README.md +0 -36
- package/files/monorepos/ai-docs/README.md +0 -33
- package/files/monorepos/apps/README.md +0 -24
- package/files/monorepos/docs/README.md +0 -40
- package/files/monorepos/packages/README.md +0 -25
- package/files/monorepos/research/README.md +0 -29
- package/files/monorepos/scripts/README.md +0 -24
- package/src/commands/README.md +0 -41
- package/src/commands/configure.js +0 -199
- package/src/commands/identity.js +0 -1630
- package/src/commands/ignore.js +0 -247
- package/src/commands/install.js +0 -526
- package/src/commands/setup.js +0 -246
- package/src/completion.js +0 -284
- package/src/constants.js +0 -45
- package/src/ignore/claude-code.txt +0 -10
- package/src/ignore/docker.txt +0 -18
- package/src/ignore/linux.txt +0 -23
- package/src/ignore/macos.txt +0 -36
- package/src/ignore/node.txt +0 -55
- package/src/ignore/terraform.txt +0 -37
- package/src/ignore/vscode.txt +0 -18
- package/src/ignore/windows.txt +0 -35
- package/src/index.js +0 -0
- package/src/installs/README.md +0 -399
- package/src/installs/adobe-creative-cloud.js +0 -546
- package/src/installs/adobe-creative-cloud.md +0 -605
- package/src/installs/appcleaner.js +0 -321
- package/src/installs/appcleaner.md +0 -699
- package/src/installs/apt-transport-https.js +0 -390
- package/src/installs/apt-transport-https.md +0 -678
- package/src/installs/atomicparsley.js +0 -642
- package/src/installs/atomicparsley.md +0 -795
- package/src/installs/aws-cli.js +0 -797
- package/src/installs/aws-cli.md +0 -727
- package/src/installs/balena-etcher.js +0 -710
- package/src/installs/balena-etcher.md +0 -761
- package/src/installs/bambu-studio.js +0 -1143
- package/src/installs/bambu-studio.md +0 -780
- package/src/installs/bash-completion.js +0 -575
- package/src/installs/bash-completion.md +0 -833
- package/src/installs/bash.js +0 -417
- package/src/installs/bash.md +0 -993
- package/src/installs/beyond-compare.js +0 -603
- package/src/installs/beyond-compare.md +0 -813
- package/src/installs/brave-browser.js +0 -968
- package/src/installs/brave-browser.md +0 -650
- package/src/installs/build-essential.js +0 -529
- package/src/installs/build-essential.md +0 -977
- package/src/installs/ca-certificates.js +0 -618
- package/src/installs/ca-certificates.md +0 -937
- package/src/installs/caffeine.js +0 -508
- package/src/installs/caffeine.md +0 -839
- package/src/installs/camtasia.js +0 -596
- package/src/installs/camtasia.md +0 -762
- package/src/installs/chatgpt.js +0 -476
- package/src/installs/chatgpt.md +0 -814
- package/src/installs/chocolatey.js +0 -456
- package/src/installs/chocolatey.md +0 -661
- package/src/installs/chrome-canary.js +0 -419
- package/src/installs/chrome-canary.md +0 -641
- package/src/installs/chromium.js +0 -667
- package/src/installs/chromium.md +0 -838
- package/src/installs/claude-code.js +0 -576
- package/src/installs/claude-code.md +0 -1173
- package/src/installs/cloudflare-warp.js +0 -900
- package/src/installs/cloudflare-warp.md +0 -1047
- package/src/installs/comet-browser.js +0 -588
- package/src/installs/comet-browser.md +0 -731
- package/src/installs/curl.js +0 -379
- package/src/installs/curl.md +0 -714
- package/src/installs/cursor.js +0 -579
- package/src/installs/cursor.md +0 -970
- package/src/installs/dbeaver.js +0 -924
- package/src/installs/dbeaver.md +0 -939
- package/src/installs/dbschema.js +0 -692
- package/src/installs/dbschema.md +0 -925
- package/src/installs/dependencies.md +0 -453
- package/src/installs/development-tools.js +0 -600
- package/src/installs/development-tools.md +0 -977
- package/src/installs/docker.js +0 -1029
- package/src/installs/docker.md +0 -1109
- package/src/installs/drawio.js +0 -1019
- package/src/installs/drawio.md +0 -795
- package/src/installs/elmedia-player.js +0 -347
- package/src/installs/elmedia-player.md +0 -556
- package/src/installs/ffmpeg.js +0 -889
- package/src/installs/ffmpeg.md +0 -852
- package/src/installs/file.js +0 -464
- package/src/installs/file.md +0 -987
- package/src/installs/gemini-cli.js +0 -811
- package/src/installs/gemini-cli.md +0 -1153
- package/src/installs/git.js +0 -400
- package/src/installs/git.md +0 -907
- package/src/installs/gitego.js +0 -949
- package/src/installs/gitego.md +0 -1172
- package/src/installs/go.js +0 -931
- package/src/installs/go.md +0 -958
- package/src/installs/google-antigravity.js +0 -913
- package/src/installs/google-antigravity.md +0 -1075
- package/src/installs/google-chrome.js +0 -833
- package/src/installs/google-chrome.md +0 -862
- package/src/installs/gpg.js +0 -480
- package/src/installs/gpg.md +0 -1056
- package/src/installs/homebrew.js +0 -1028
- package/src/installs/homebrew.md +0 -988
- package/src/installs/imageoptim.js +0 -968
- package/src/installs/imageoptim.md +0 -1119
- package/src/installs/installers.json +0 -4032
- package/src/installs/installers.json.tmp +0 -3953
- package/src/installs/jq.js +0 -400
- package/src/installs/jq.md +0 -809
- package/src/installs/keyboard-maestro.js +0 -719
- package/src/installs/keyboard-maestro.md +0 -825
- package/src/installs/kiro.js +0 -864
- package/src/installs/kiro.md +0 -1015
- package/src/installs/latex.js +0 -789
- package/src/installs/latex.md +0 -1095
- package/src/installs/lftp.js +0 -356
- package/src/installs/lftp.md +0 -907
- package/src/installs/lsb-release.js +0 -346
- package/src/installs/lsb-release.md +0 -814
- package/src/installs/messenger.js +0 -847
- package/src/installs/messenger.md +0 -900
- package/src/installs/microsoft-office.js +0 -568
- package/src/installs/microsoft-office.md +0 -760
- package/src/installs/microsoft-teams.js +0 -801
- package/src/installs/microsoft-teams.md +0 -886
- package/src/installs/moom.js +0 -326
- package/src/installs/moom.md +0 -570
- package/src/installs/node.js +0 -904
- package/src/installs/node.md +0 -1153
- package/src/installs/nordpass.js +0 -716
- package/src/installs/nordpass.md +0 -921
- package/src/installs/nordvpn.js +0 -892
- package/src/installs/nordvpn.md +0 -1052
- package/src/installs/nvm.js +0 -995
- package/src/installs/nvm.md +0 -1057
- package/src/installs/ohmyzsh.js +0 -529
- package/src/installs/ohmyzsh.md +0 -1094
- package/src/installs/openssh.js +0 -804
- package/src/installs/openssh.md +0 -1056
- package/src/installs/pandoc.js +0 -662
- package/src/installs/pandoc.md +0 -1036
- package/src/installs/parallels-desktop.js +0 -431
- package/src/installs/parallels-desktop.md +0 -446
- package/src/installs/pinentry.js +0 -510
- package/src/installs/pinentry.md +0 -1142
- package/src/installs/pngyu.js +0 -869
- package/src/installs/pngyu.md +0 -896
- package/src/installs/postman.js +0 -799
- package/src/installs/postman.md +0 -940
- package/src/installs/procps.js +0 -425
- package/src/installs/procps.md +0 -851
- package/src/installs/safari-tech-preview.js +0 -374
- package/src/installs/safari-tech-preview.md +0 -533
- package/src/installs/sfnt2woff.js +0 -658
- package/src/installs/sfnt2woff.md +0 -795
- package/src/installs/shellcheck.js +0 -481
- package/src/installs/shellcheck.md +0 -1005
- package/src/installs/slack.js +0 -741
- package/src/installs/slack.md +0 -865
- package/src/installs/snagit.js +0 -585
- package/src/installs/snagit.md +0 -844
- package/src/installs/software-properties-common.js +0 -372
- package/src/installs/software-properties-common.md +0 -805
- package/src/installs/spotify.js +0 -877
- package/src/installs/spotify.md +0 -901
- package/src/installs/studio-3t.js +0 -823
- package/src/installs/studio-3t.md +0 -918
- package/src/installs/sublime-text.js +0 -804
- package/src/installs/sublime-text.md +0 -914
- package/src/installs/superwhisper.js +0 -706
- package/src/installs/superwhisper.md +0 -630
- package/src/installs/tailscale.js +0 -745
- package/src/installs/tailscale.md +0 -1100
- package/src/installs/tar.js +0 -389
- package/src/installs/tar.md +0 -946
- package/src/installs/termius.js +0 -798
- package/src/installs/termius.md +0 -844
- package/src/installs/terraform.js +0 -779
- package/src/installs/terraform.md +0 -899
- package/src/installs/tfenv.js +0 -778
- package/src/installs/tfenv.md +0 -1091
- package/src/installs/tidal.js +0 -771
- package/src/installs/tidal.md +0 -864
- package/src/installs/tmux.js +0 -346
- package/src/installs/tmux.md +0 -1030
- package/src/installs/tree.js +0 -411
- package/src/installs/tree.md +0 -833
- package/src/installs/unzip.js +0 -460
- package/src/installs/unzip.md +0 -879
- package/src/installs/vim.js +0 -421
- package/src/installs/vim.md +0 -1040
- package/src/installs/vlc.js +0 -821
- package/src/installs/vlc.md +0 -927
- package/src/installs/vscode.js +0 -843
- package/src/installs/vscode.md +0 -1002
- package/src/installs/wget.js +0 -420
- package/src/installs/wget.md +0 -791
- package/src/installs/whatsapp.js +0 -729
- package/src/installs/whatsapp.md +0 -854
- package/src/installs/winpty.js +0 -352
- package/src/installs/winpty.md +0 -620
- package/src/installs/woff2.js +0 -553
- package/src/installs/woff2.md +0 -977
- package/src/installs/wsl.js +0 -572
- package/src/installs/wsl.md +0 -699
- package/src/installs/xcode-clt.js +0 -520
- package/src/installs/xcode-clt.md +0 -351
- package/src/installs/xcode.js +0 -560
- package/src/installs/xcode.md +0 -573
- package/src/installs/yarn.js +0 -824
- package/src/installs/yarn.md +0 -1074
- package/src/installs/yq.js +0 -654
- package/src/installs/yq.md +0 -944
- package/src/installs/yt-dlp.js +0 -701
- package/src/installs/yt-dlp.md +0 -946
- package/src/installs/yum-utils.js +0 -297
- package/src/installs/yum-utils.md +0 -648
- package/src/installs/zoom.js +0 -759
- package/src/installs/zoom.md +0 -884
- package/src/installs/zsh.js +0 -455
- package/src/installs/zsh.md +0 -1008
- package/src/scripts/README.md +0 -617
- package/src/scripts/STATUS.md +0 -208
- package/src/scripts/afk.js +0 -411
- package/src/scripts/backup-all.js +0 -746
- package/src/scripts/backup-source.js +0 -727
- package/src/scripts/brewd.js +0 -389
- package/src/scripts/brewi.js +0 -520
- package/src/scripts/brewr.js +0 -527
- package/src/scripts/brews.js +0 -477
- package/src/scripts/brewu.js +0 -504
- package/src/scripts/c.js +0 -201
- package/src/scripts/ccurl.js +0 -341
- package/src/scripts/certbot-crontab-init.js +0 -504
- package/src/scripts/certbot-init.js +0 -657
- package/src/scripts/ch.js +0 -355
- package/src/scripts/claude-danger.js +0 -268
- package/src/scripts/clean-dev.js +0 -435
- package/src/scripts/clear-dns-cache.js +0 -541
- package/src/scripts/clone.js +0 -435
- package/src/scripts/code-all.js +0 -437
- package/src/scripts/count-files.js +0 -211
- package/src/scripts/count-folders.js +0 -211
- package/src/scripts/count.js +0 -264
- package/src/scripts/d.js +0 -219
- package/src/scripts/datauri.js +0 -389
- package/src/scripts/delete-files.js +0 -380
- package/src/scripts/docker-clean.js +0 -426
- package/src/scripts/dp.js +0 -442
- package/src/scripts/e.js +0 -390
- package/src/scripts/empty-trash.js +0 -513
- package/src/scripts/evm.js +0 -444
- package/src/scripts/fetch-github-repos.js +0 -456
- package/src/scripts/get-channel.js +0 -345
- package/src/scripts/get-course.js +0 -399
- package/src/scripts/get-dependencies.js +0 -306
- package/src/scripts/get-folder.js +0 -799
- package/src/scripts/get-tunes.js +0 -426
- package/src/scripts/get-video.js +0 -367
- package/src/scripts/git-backup.js +0 -577
- package/src/scripts/git-clone.js +0 -493
- package/src/scripts/git-pup.js +0 -319
- package/src/scripts/git-push.js +0 -396
- package/src/scripts/h.js +0 -622
- package/src/scripts/hide-desktop-icons.js +0 -499
- package/src/scripts/hide-hidden-files.js +0 -538
- package/src/scripts/install-dependencies-from.js +0 -456
- package/src/scripts/ips.js +0 -663
- package/src/scripts/iso.js +0 -370
- package/src/scripts/killni.js +0 -577
- package/src/scripts/ll.js +0 -467
- package/src/scripts/local-ip.js +0 -325
- package/src/scripts/m.js +0 -524
- package/src/scripts/map.js +0 -309
- package/src/scripts/mkd.js +0 -351
- package/src/scripts/ncu-update-all.js +0 -457
- package/src/scripts/nginx-init.js +0 -718
- package/src/scripts/npmi.js +0 -382
- package/src/scripts/o.js +0 -511
- package/src/scripts/org-by-date.js +0 -338
- package/src/scripts/p.js +0 -224
- package/src/scripts/packages.js +0 -330
- package/src/scripts/path.js +0 -225
- package/src/scripts/ports.js +0 -597
- package/src/scripts/q.js +0 -305
- package/src/scripts/refresh-files.js +0 -394
- package/src/scripts/remove-smaller-files.js +0 -516
- package/src/scripts/rename-files-with-date.js +0 -533
- package/src/scripts/resize-image.js +0 -539
- package/src/scripts/rm-safe.js +0 -669
- package/src/scripts/s.js +0 -540
- package/src/scripts/set-git-public.js +0 -365
- package/src/scripts/show-desktop-icons.js +0 -475
- package/src/scripts/show-hidden-files.js +0 -472
- package/src/scripts/tpa.js +0 -280
- package/src/scripts/tpo.js +0 -280
- package/src/scripts/u.js +0 -505
- package/src/scripts/vpush.js +0 -437
- package/src/scripts/y.js +0 -283
- package/src/utils/README.md +0 -95
- package/src/utils/common/apps.js +0 -143
- package/src/utils/common/display.js +0 -157
- package/src/utils/common/network.js +0 -185
- package/src/utils/common/os.js +0 -294
- package/src/utils/common/package-manager.js +0 -301
- package/src/utils/common/privileges.js +0 -138
- package/src/utils/common/shell.js +0 -261
- package/src/utils/macos/apps.js +0 -228
- package/src/utils/macos/brew.js +0 -315
- package/src/utils/ubuntu/apt.js +0 -307
- package/src/utils/ubuntu/desktop.js +0 -292
- package/src/utils/ubuntu/snap.js +0 -344
- package/src/utils/ubuntu/systemd.js +0 -286
- package/src/utils/windows/choco.js +0 -465
- package/src/utils/windows/env.js +0 -246
- package/src/utils/windows/registry.js +0 -269
- package/src/utils/windows/shell.js +0 -240
- package/src/utils/windows/winget.js +0 -489
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Package Manager Abstraction Utilities
|
|
5
|
-
*
|
|
6
|
-
* Cross-platform abstraction layer for package managers.
|
|
7
|
-
* Provides a unified interface for installing packages across different platforms.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const osUtils = require('./os');
|
|
11
|
-
const shell = require('./shell');
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Returns list of available package managers on current system
|
|
15
|
-
* @returns {Promise<string[]>}
|
|
16
|
-
*/
|
|
17
|
-
async function getAvailable() {
|
|
18
|
-
const available = [];
|
|
19
|
-
const platform = osUtils.detect();
|
|
20
|
-
|
|
21
|
-
switch (platform.type) {
|
|
22
|
-
case 'macos':
|
|
23
|
-
if (shell.commandExists('brew')) {
|
|
24
|
-
available.push('brew');
|
|
25
|
-
}
|
|
26
|
-
break;
|
|
27
|
-
|
|
28
|
-
case 'ubuntu':
|
|
29
|
-
case 'debian':
|
|
30
|
-
case 'raspbian':
|
|
31
|
-
if (shell.commandExists('apt-get')) {
|
|
32
|
-
available.push('apt');
|
|
33
|
-
}
|
|
34
|
-
if (shell.commandExists('snap')) {
|
|
35
|
-
available.push('snap');
|
|
36
|
-
}
|
|
37
|
-
break;
|
|
38
|
-
|
|
39
|
-
case 'amazon_linux':
|
|
40
|
-
case 'rhel':
|
|
41
|
-
case 'fedora':
|
|
42
|
-
if (shell.commandExists('dnf')) {
|
|
43
|
-
available.push('dnf');
|
|
44
|
-
}
|
|
45
|
-
if (shell.commandExists('yum')) {
|
|
46
|
-
available.push('yum');
|
|
47
|
-
}
|
|
48
|
-
break;
|
|
49
|
-
|
|
50
|
-
case 'windows':
|
|
51
|
-
if (shell.commandExists('winget')) {
|
|
52
|
-
available.push('winget');
|
|
53
|
-
}
|
|
54
|
-
if (shell.commandExists('choco')) {
|
|
55
|
-
available.push('choco');
|
|
56
|
-
}
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Universal package managers
|
|
61
|
-
if (shell.commandExists('npm')) {
|
|
62
|
-
available.push('npm');
|
|
63
|
-
}
|
|
64
|
-
if (shell.commandExists('pip') || shell.commandExists('pip3')) {
|
|
65
|
-
available.push('pip');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return available;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Returns the preferred/recommended package manager for current platform
|
|
73
|
-
* @returns {string|null}
|
|
74
|
-
*/
|
|
75
|
-
function getPreferred() {
|
|
76
|
-
const platform = osUtils.detect();
|
|
77
|
-
|
|
78
|
-
switch (platform.type) {
|
|
79
|
-
case 'macos':
|
|
80
|
-
return 'brew';
|
|
81
|
-
case 'ubuntu':
|
|
82
|
-
case 'debian':
|
|
83
|
-
case 'raspbian':
|
|
84
|
-
return 'apt';
|
|
85
|
-
case 'amazon_linux':
|
|
86
|
-
case 'rhel':
|
|
87
|
-
case 'fedora':
|
|
88
|
-
return platform.packageManager; // dnf or yum
|
|
89
|
-
case 'windows':
|
|
90
|
-
return shell.commandExists('winget') ? 'winget' : 'choco';
|
|
91
|
-
default:
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Installs a package using the best available package manager
|
|
98
|
-
* @param {string} packageName - The package to install
|
|
99
|
-
* @param {Object} [options] - Installation options
|
|
100
|
-
* @param {string} [options.manager] - Force a specific package manager
|
|
101
|
-
* @param {boolean} [options.global] - Install globally (for npm/pip)
|
|
102
|
-
* @param {boolean} [options.cask] - Install as cask (macOS only)
|
|
103
|
-
* @param {boolean} [options.classic] - Use classic confinement (snap only)
|
|
104
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
105
|
-
*/
|
|
106
|
-
async function install(packageName, options = {}) {
|
|
107
|
-
const manager = options.manager || getPreferred();
|
|
108
|
-
|
|
109
|
-
if (!manager) {
|
|
110
|
-
return {
|
|
111
|
-
success: false,
|
|
112
|
-
output: 'No package manager available'
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
let command;
|
|
117
|
-
|
|
118
|
-
switch (manager) {
|
|
119
|
-
case 'brew':
|
|
120
|
-
if (options.cask) {
|
|
121
|
-
command = `brew install --cask ${packageName}`;
|
|
122
|
-
} else {
|
|
123
|
-
command = `brew install ${packageName}`;
|
|
124
|
-
}
|
|
125
|
-
break;
|
|
126
|
-
|
|
127
|
-
case 'apt':
|
|
128
|
-
command = `sudo apt-get install -y ${packageName}`;
|
|
129
|
-
break;
|
|
130
|
-
|
|
131
|
-
case 'snap':
|
|
132
|
-
if (options.classic) {
|
|
133
|
-
command = `sudo snap install ${packageName} --classic`;
|
|
134
|
-
} else {
|
|
135
|
-
command = `sudo snap install ${packageName}`;
|
|
136
|
-
}
|
|
137
|
-
break;
|
|
138
|
-
|
|
139
|
-
case 'dnf':
|
|
140
|
-
command = `sudo dnf install -y ${packageName}`;
|
|
141
|
-
break;
|
|
142
|
-
|
|
143
|
-
case 'yum':
|
|
144
|
-
command = `sudo yum install -y ${packageName}`;
|
|
145
|
-
break;
|
|
146
|
-
|
|
147
|
-
case 'winget':
|
|
148
|
-
command = `winget install --accept-package-agreements --accept-source-agreements ${packageName}`;
|
|
149
|
-
break;
|
|
150
|
-
|
|
151
|
-
case 'choco':
|
|
152
|
-
command = `choco install -y ${packageName}`;
|
|
153
|
-
break;
|
|
154
|
-
|
|
155
|
-
case 'npm':
|
|
156
|
-
if (options.global) {
|
|
157
|
-
command = `npm install -g ${packageName}`;
|
|
158
|
-
} else {
|
|
159
|
-
command = `npm install ${packageName}`;
|
|
160
|
-
}
|
|
161
|
-
break;
|
|
162
|
-
|
|
163
|
-
case 'pip':
|
|
164
|
-
const pip = shell.commandExists('pip3') ? 'pip3' : 'pip';
|
|
165
|
-
if (options.global) {
|
|
166
|
-
command = `${pip} install ${packageName}`;
|
|
167
|
-
} else {
|
|
168
|
-
command = `${pip} install --user ${packageName}`;
|
|
169
|
-
}
|
|
170
|
-
break;
|
|
171
|
-
|
|
172
|
-
default:
|
|
173
|
-
return {
|
|
174
|
-
success: false,
|
|
175
|
-
output: `Unknown package manager: ${manager}`
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const result = await shell.exec(command);
|
|
180
|
-
return {
|
|
181
|
-
success: result.code === 0,
|
|
182
|
-
output: result.stdout || result.stderr
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* Uninstalls a package
|
|
188
|
-
* @param {string} packageName - The package to uninstall
|
|
189
|
-
* @param {Object} [options] - Uninstallation options
|
|
190
|
-
* @param {string} [options.manager] - Force a specific package manager
|
|
191
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
192
|
-
*/
|
|
193
|
-
async function uninstall(packageName, options = {}) {
|
|
194
|
-
const manager = options.manager || getPreferred();
|
|
195
|
-
|
|
196
|
-
if (!manager) {
|
|
197
|
-
return {
|
|
198
|
-
success: false,
|
|
199
|
-
output: 'No package manager available'
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
let command;
|
|
204
|
-
|
|
205
|
-
switch (manager) {
|
|
206
|
-
case 'brew':
|
|
207
|
-
command = `brew uninstall ${packageName}`;
|
|
208
|
-
break;
|
|
209
|
-
|
|
210
|
-
case 'apt':
|
|
211
|
-
command = `sudo apt-get remove -y ${packageName}`;
|
|
212
|
-
break;
|
|
213
|
-
|
|
214
|
-
case 'snap':
|
|
215
|
-
command = `sudo snap remove ${packageName}`;
|
|
216
|
-
break;
|
|
217
|
-
|
|
218
|
-
case 'dnf':
|
|
219
|
-
command = `sudo dnf remove -y ${packageName}`;
|
|
220
|
-
break;
|
|
221
|
-
|
|
222
|
-
case 'yum':
|
|
223
|
-
command = `sudo yum remove -y ${packageName}`;
|
|
224
|
-
break;
|
|
225
|
-
|
|
226
|
-
case 'winget':
|
|
227
|
-
command = `winget uninstall ${packageName}`;
|
|
228
|
-
break;
|
|
229
|
-
|
|
230
|
-
case 'choco':
|
|
231
|
-
command = `choco uninstall -y ${packageName}`;
|
|
232
|
-
break;
|
|
233
|
-
|
|
234
|
-
default:
|
|
235
|
-
return {
|
|
236
|
-
success: false,
|
|
237
|
-
output: `Unknown package manager: ${manager}`
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const result = await shell.exec(command);
|
|
242
|
-
return {
|
|
243
|
-
success: result.code === 0,
|
|
244
|
-
output: result.stdout || result.stderr
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Updates package lists
|
|
250
|
-
* @param {string} [manager] - Specific package manager to update
|
|
251
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
252
|
-
*/
|
|
253
|
-
async function update(manager) {
|
|
254
|
-
const pm = manager || getPreferred();
|
|
255
|
-
|
|
256
|
-
let command;
|
|
257
|
-
|
|
258
|
-
switch (pm) {
|
|
259
|
-
case 'brew':
|
|
260
|
-
command = 'brew update';
|
|
261
|
-
break;
|
|
262
|
-
|
|
263
|
-
case 'apt':
|
|
264
|
-
command = 'sudo apt-get update';
|
|
265
|
-
break;
|
|
266
|
-
|
|
267
|
-
case 'dnf':
|
|
268
|
-
command = 'sudo dnf check-update';
|
|
269
|
-
break;
|
|
270
|
-
|
|
271
|
-
case 'yum':
|
|
272
|
-
command = 'sudo yum check-update';
|
|
273
|
-
break;
|
|
274
|
-
|
|
275
|
-
case 'choco':
|
|
276
|
-
command = 'choco upgrade chocolatey -y';
|
|
277
|
-
break;
|
|
278
|
-
|
|
279
|
-
default:
|
|
280
|
-
return {
|
|
281
|
-
success: false,
|
|
282
|
-
output: `Update not supported for: ${pm}`
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
const result = await shell.exec(command);
|
|
287
|
-
// dnf/yum check-update returns 100 if updates are available, not an error
|
|
288
|
-
const success = result.code === 0 || (pm === 'dnf' || pm === 'yum') && result.code === 100;
|
|
289
|
-
return {
|
|
290
|
-
success,
|
|
291
|
-
output: result.stdout || result.stderr
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
module.exports = {
|
|
296
|
-
getAvailable,
|
|
297
|
-
getPreferred,
|
|
298
|
-
install,
|
|
299
|
-
uninstall,
|
|
300
|
-
update
|
|
301
|
-
};
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Permission and Elevation Checking Utilities
|
|
5
|
-
*
|
|
6
|
-
* Platform-agnostic utilities for checking elevated privileges.
|
|
7
|
-
* Handles root on Unix and Administrator on Windows internally.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const os = require('os');
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Checks if running with elevated privileges
|
|
14
|
-
* On Unix: checks if running as root (uid 0)
|
|
15
|
-
* On Windows: checks if running as Administrator
|
|
16
|
-
* @returns {boolean}
|
|
17
|
-
*/
|
|
18
|
-
function isElevated() {
|
|
19
|
-
if (process.platform === 'win32') {
|
|
20
|
-
return isWindowsAdmin();
|
|
21
|
-
}
|
|
22
|
-
return isUnixRoot();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Checks if running as root on Unix systems
|
|
27
|
-
* @returns {boolean}
|
|
28
|
-
*/
|
|
29
|
-
function isUnixRoot() {
|
|
30
|
-
if (process.platform === 'win32') {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
return process.getuid && process.getuid() === 0;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Checks if running as Administrator on Windows
|
|
38
|
-
* Uses a heuristic since Node.js doesn't have direct API for this
|
|
39
|
-
* @returns {boolean}
|
|
40
|
-
*/
|
|
41
|
-
function isWindowsAdmin() {
|
|
42
|
-
if (process.platform !== 'win32') {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Method 1: Try to read a system-protected location
|
|
47
|
-
const fs = require('fs');
|
|
48
|
-
try {
|
|
49
|
-
// Try to list the Windows system config directory
|
|
50
|
-
// Only administrators can access this
|
|
51
|
-
fs.readdirSync('C:\\Windows\\System32\\config');
|
|
52
|
-
return true;
|
|
53
|
-
} catch {
|
|
54
|
-
// Not admin or access denied
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Method 2: Check for common admin environment indicators
|
|
58
|
-
// This is less reliable but can be a fallback
|
|
59
|
-
if (process.env.ADMIN_MODE === 'true') {
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Determines if a given operation type requires elevation
|
|
68
|
-
* @param {string} operation - The operation type
|
|
69
|
-
* @returns {boolean}
|
|
70
|
-
*/
|
|
71
|
-
function requiresElevation(operation) {
|
|
72
|
-
const elevatedOperations = [
|
|
73
|
-
'install_system_package',
|
|
74
|
-
'modify_system_config',
|
|
75
|
-
'start_system_service',
|
|
76
|
-
'modify_hosts_file',
|
|
77
|
-
'install_global_npm',
|
|
78
|
-
'modify_registry',
|
|
79
|
-
'add_apt_repository',
|
|
80
|
-
'enable_systemd_service'
|
|
81
|
-
];
|
|
82
|
-
|
|
83
|
-
return elevatedOperations.includes(operation);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Gets the username of the current user
|
|
88
|
-
* @returns {string}
|
|
89
|
-
*/
|
|
90
|
-
function getCurrentUser() {
|
|
91
|
-
return os.userInfo().username;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Checks if the current user can write to a directory
|
|
96
|
-
* @param {string} dirPath - The directory path to check
|
|
97
|
-
* @returns {boolean}
|
|
98
|
-
*/
|
|
99
|
-
function canWriteToDirectory(dirPath) {
|
|
100
|
-
const fs = require('fs');
|
|
101
|
-
const path = require('path');
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
// Try to create a temporary file
|
|
105
|
-
const testFile = path.join(dirPath, `.write-test-${Date.now()}`);
|
|
106
|
-
fs.writeFileSync(testFile, '');
|
|
107
|
-
fs.unlinkSync(testFile);
|
|
108
|
-
return true;
|
|
109
|
-
} catch {
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Checks if the current user can execute a file
|
|
116
|
-
* @param {string} filePath - The file path to check
|
|
117
|
-
* @returns {boolean}
|
|
118
|
-
*/
|
|
119
|
-
function canExecute(filePath) {
|
|
120
|
-
const fs = require('fs');
|
|
121
|
-
|
|
122
|
-
try {
|
|
123
|
-
fs.accessSync(filePath, fs.constants.X_OK);
|
|
124
|
-
return true;
|
|
125
|
-
} catch {
|
|
126
|
-
return false;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
module.exports = {
|
|
131
|
-
isElevated,
|
|
132
|
-
isUnixRoot,
|
|
133
|
-
isWindowsAdmin,
|
|
134
|
-
requiresElevation,
|
|
135
|
-
getCurrentUser,
|
|
136
|
-
canWriteToDirectory,
|
|
137
|
-
canExecute
|
|
138
|
-
};
|
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Shell Command Execution Utilities
|
|
5
|
-
*
|
|
6
|
-
* Platform-agnostic utilities for executing shell commands. Uses Node.js
|
|
7
|
-
* child_process APIs that work identically on all platforms. Note that while
|
|
8
|
-
* these utilities are cross-platform, the commands passed to them may be
|
|
9
|
-
* platform-specific.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const { exec: cpExec, execSync: cpExecSync, spawn } = require('child_process');
|
|
13
|
-
const fs = require('fs');
|
|
14
|
-
const path = require('path');
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Executes a shell command asynchronously
|
|
18
|
-
* @param {string} command - The command to execute
|
|
19
|
-
* @param {Object} [options] - Options for child_process.exec
|
|
20
|
-
* @param {string} [options.cwd] - Working directory
|
|
21
|
-
* @param {Object} [options.env] - Environment variables
|
|
22
|
-
* @param {number} [options.timeout] - Timeout in milliseconds
|
|
23
|
-
* @param {string} [options.encoding] - Output encoding (default: 'utf8')
|
|
24
|
-
* @returns {Promise<{ stdout: string, stderr: string, code: number }>}
|
|
25
|
-
*/
|
|
26
|
-
async function exec(command, options = {}) {
|
|
27
|
-
return new Promise((resolve, reject) => {
|
|
28
|
-
const opts = {
|
|
29
|
-
encoding: options.encoding || 'utf8',
|
|
30
|
-
cwd: options.cwd,
|
|
31
|
-
env: options.env || process.env,
|
|
32
|
-
timeout: options.timeout,
|
|
33
|
-
maxBuffer: options.maxBuffer || 10 * 1024 * 1024 // 10MB default
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
cpExec(command, opts, (error, stdout, stderr) => {
|
|
37
|
-
if (error) {
|
|
38
|
-
resolve({
|
|
39
|
-
stdout: stdout || '',
|
|
40
|
-
stderr: stderr || error.message,
|
|
41
|
-
code: error.code || 1
|
|
42
|
-
});
|
|
43
|
-
} else {
|
|
44
|
-
resolve({
|
|
45
|
-
stdout: stdout || '',
|
|
46
|
-
stderr: stderr || '',
|
|
47
|
-
code: 0
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Executes a shell command synchronously
|
|
56
|
-
* @param {string} command - The command to execute
|
|
57
|
-
* @param {Object} [options] - Options for child_process.execSync
|
|
58
|
-
* @param {string} [options.cwd] - Working directory
|
|
59
|
-
* @param {Object} [options.env] - Environment variables
|
|
60
|
-
* @param {number} [options.timeout] - Timeout in milliseconds
|
|
61
|
-
* @param {string} [options.encoding] - Output encoding (default: 'utf8')
|
|
62
|
-
* @returns {string} - stdout as string, or empty string on error
|
|
63
|
-
*/
|
|
64
|
-
function execSync(command, options = {}) {
|
|
65
|
-
try {
|
|
66
|
-
const opts = {
|
|
67
|
-
encoding: options.encoding || 'utf8',
|
|
68
|
-
cwd: options.cwd,
|
|
69
|
-
env: options.env || process.env,
|
|
70
|
-
timeout: options.timeout,
|
|
71
|
-
maxBuffer: options.maxBuffer || 10 * 1024 * 1024, // 10MB default
|
|
72
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
return cpExecSync(command, opts).toString().trim();
|
|
76
|
-
} catch (err) {
|
|
77
|
-
return '';
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Locates an executable in PATH (pure Node.js implementation)
|
|
83
|
-
* @param {string} executable - The executable name to find
|
|
84
|
-
* @returns {string|null} - Full path to executable, or null if not found
|
|
85
|
-
*/
|
|
86
|
-
function which(executable) {
|
|
87
|
-
const isWindows = process.platform === 'win32';
|
|
88
|
-
const pathSeparator = isWindows ? ';' : ':';
|
|
89
|
-
const pathEnv = process.env.PATH || '';
|
|
90
|
-
const paths = pathEnv.split(pathSeparator);
|
|
91
|
-
|
|
92
|
-
// On Windows, also check PATHEXT for executable extensions
|
|
93
|
-
const pathExt = isWindows
|
|
94
|
-
? (process.env.PATHEXT || '.COM;.EXE;.BAT;.CMD').split(';')
|
|
95
|
-
: [''];
|
|
96
|
-
|
|
97
|
-
for (const dir of paths) {
|
|
98
|
-
if (!dir) continue;
|
|
99
|
-
|
|
100
|
-
for (const ext of pathExt) {
|
|
101
|
-
const fullPath = path.join(dir, executable + ext);
|
|
102
|
-
try {
|
|
103
|
-
const stat = fs.statSync(fullPath);
|
|
104
|
-
if (stat.isFile()) {
|
|
105
|
-
// On Unix, check if file is executable
|
|
106
|
-
if (!isWindows) {
|
|
107
|
-
try {
|
|
108
|
-
fs.accessSync(fullPath, fs.constants.X_OK);
|
|
109
|
-
return fullPath;
|
|
110
|
-
} catch {
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return fullPath;
|
|
115
|
-
}
|
|
116
|
-
} catch {
|
|
117
|
-
continue;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Checks if a command is available in PATH
|
|
127
|
-
*
|
|
128
|
-
* On Windows, this also handles App Execution Aliases (used by winget, etc.)
|
|
129
|
-
* which are special reparse points that don't appear as regular files to
|
|
130
|
-
* fs.statSync().isFile(). We fall back to using the 'where' command for these.
|
|
131
|
-
*
|
|
132
|
-
* @param {string} command - The command to check
|
|
133
|
-
* @returns {boolean}
|
|
134
|
-
*/
|
|
135
|
-
function commandExists(command) {
|
|
136
|
-
// First try the file-based check (works for regular executables)
|
|
137
|
-
if (which(command) !== null) {
|
|
138
|
-
return true;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// On Windows, App Execution Aliases (like winget) don't appear as regular
|
|
142
|
-
// files to fs.statSync(). Use 'where' command as a fallback.
|
|
143
|
-
if (process.platform === 'win32') {
|
|
144
|
-
try {
|
|
145
|
-
cpExecSync(`where ${command}`, { stdio: 'ignore' });
|
|
146
|
-
return true;
|
|
147
|
-
} catch {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/**
|
|
156
|
-
* Spawns a process with streaming output
|
|
157
|
-
* @param {string} command - The command to run
|
|
158
|
-
* @param {string[]} [args] - Arguments array
|
|
159
|
-
* @param {Object} [options] - Spawn options
|
|
160
|
-
* @returns {Promise<{ stdout: string, stderr: string, code: number }>}
|
|
161
|
-
*/
|
|
162
|
-
async function spawnAsync(command, args = [], options = {}) {
|
|
163
|
-
return new Promise((resolve, reject) => {
|
|
164
|
-
const opts = {
|
|
165
|
-
cwd: options.cwd,
|
|
166
|
-
env: options.env || process.env,
|
|
167
|
-
shell: options.shell !== false
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
const child = spawn(command, args, opts);
|
|
171
|
-
let stdout = '';
|
|
172
|
-
let stderr = '';
|
|
173
|
-
|
|
174
|
-
if (child.stdout) {
|
|
175
|
-
child.stdout.on('data', (data) => {
|
|
176
|
-
stdout += data.toString();
|
|
177
|
-
if (options.onStdout) {
|
|
178
|
-
options.onStdout(data.toString());
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (child.stderr) {
|
|
184
|
-
child.stderr.on('data', (data) => {
|
|
185
|
-
stderr += data.toString();
|
|
186
|
-
if (options.onStderr) {
|
|
187
|
-
options.onStderr(data.toString());
|
|
188
|
-
}
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
child.on('close', (code) => {
|
|
193
|
-
resolve({
|
|
194
|
-
stdout,
|
|
195
|
-
stderr,
|
|
196
|
-
code: code || 0
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
child.on('error', (err) => {
|
|
201
|
-
resolve({
|
|
202
|
-
stdout,
|
|
203
|
-
stderr: stderr || err.message,
|
|
204
|
-
code: 1
|
|
205
|
-
});
|
|
206
|
-
});
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* Spawns an interactive command with terminal passthrough.
|
|
212
|
-
*
|
|
213
|
-
* Use this function for commands that need user interaction, such as:
|
|
214
|
-
* - Commands that prompt for sudo password
|
|
215
|
-
* - Interactive installers that ask questions
|
|
216
|
-
* - Commands that show progress with cursor movement
|
|
217
|
-
*
|
|
218
|
-
* Unlike exec() or spawnAsync(), this function connects the child process
|
|
219
|
-
* directly to the parent's terminal (stdin, stdout, stderr), allowing the
|
|
220
|
-
* user to interact with the command as if they ran it directly.
|
|
221
|
-
*
|
|
222
|
-
* @param {string} command - The command to run (passed to shell)
|
|
223
|
-
* @param {Object} [options] - Options
|
|
224
|
-
* @param {string} [options.cwd] - Working directory for the command
|
|
225
|
-
* @param {Object} [options.env] - Environment variables (defaults to process.env)
|
|
226
|
-
* @returns {Promise<number>} Exit code (0 = success, non-zero = failure)
|
|
227
|
-
*
|
|
228
|
-
* @example
|
|
229
|
-
* // Run an installer that needs sudo password
|
|
230
|
-
* const exitCode = await spawnInteractive('/bin/bash -c "$(curl -fsSL https://example.com/install.sh)"');
|
|
231
|
-
* if (exitCode !== 0) {
|
|
232
|
-
* console.error('Installation failed');
|
|
233
|
-
* }
|
|
234
|
-
*/
|
|
235
|
-
async function spawnInteractive(command, options = {}) {
|
|
236
|
-
return new Promise((resolve) => {
|
|
237
|
-
const child = spawn(command, [], {
|
|
238
|
-
stdio: 'inherit', // Connect to parent's terminal
|
|
239
|
-
shell: true, // Run through shell to support complex commands
|
|
240
|
-
cwd: options.cwd,
|
|
241
|
-
env: options.env || process.env
|
|
242
|
-
});
|
|
243
|
-
|
|
244
|
-
child.on('close', (code) => {
|
|
245
|
-
resolve(code || 0);
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
child.on('error', () => {
|
|
249
|
-
resolve(1);
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
module.exports = {
|
|
255
|
-
exec,
|
|
256
|
-
execSync,
|
|
257
|
-
which,
|
|
258
|
-
commandExists,
|
|
259
|
-
spawnAsync,
|
|
260
|
-
spawnInteractive
|
|
261
|
-
};
|