@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
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Command: dev tools list
|
|
5
|
+
*
|
|
6
|
+
* Lists all available tools from the registry, with their install status.
|
|
7
|
+
* Can filter by --installed, --available, or --platform.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @type {{ description: string, arguments: Array, flags: Array }}
|
|
12
|
+
*/
|
|
13
|
+
const meta = {
|
|
14
|
+
description: 'List available tools',
|
|
15
|
+
arguments: [],
|
|
16
|
+
flags: [
|
|
17
|
+
{ name: '--installed', description: 'Show only installed tools' },
|
|
18
|
+
{ name: '--available', description: 'Show only tools not yet installed' },
|
|
19
|
+
{ name: '--platform', description: 'Filter by platform (default: current)' }
|
|
20
|
+
]
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Runs the list command.
|
|
25
|
+
* @param {{ positional: string[], flags: object }} args - Parsed command arguments.
|
|
26
|
+
* @param {object} context - The CLI context object.
|
|
27
|
+
*/
|
|
28
|
+
async function run(args, context) {
|
|
29
|
+
const installer = require('../../lib/installer');
|
|
30
|
+
|
|
31
|
+
// Load the full registry
|
|
32
|
+
const tools = installer.loadRegistry();
|
|
33
|
+
|
|
34
|
+
// Determine platform filter
|
|
35
|
+
const platformFilter = args.flags.platform || context.platform.detect().type;
|
|
36
|
+
|
|
37
|
+
// Filter to tools that support the target platform
|
|
38
|
+
let filtered = tools.filter(t => t.platforms.includes(platformFilter));
|
|
39
|
+
|
|
40
|
+
// If --installed or --available, check each tool's install status
|
|
41
|
+
const showInstalled = args.flags.installed === true;
|
|
42
|
+
const showAvailable = args.flags.available === true;
|
|
43
|
+
|
|
44
|
+
if (showInstalled || showAvailable) {
|
|
45
|
+
const statusResults = [];
|
|
46
|
+
for (const tool of filtered) {
|
|
47
|
+
try {
|
|
48
|
+
const mod = installer.loadInstaller(tool);
|
|
49
|
+
const isInst = await mod.isInstalled(context);
|
|
50
|
+
statusResults.push({ tool, installed: isInst });
|
|
51
|
+
} catch {
|
|
52
|
+
// If the installer can't be loaded, treat as not installed
|
|
53
|
+
statusResults.push({ tool, installed: false });
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (showInstalled) {
|
|
58
|
+
filtered = statusResults.filter(r => r.installed).map(r => r.tool);
|
|
59
|
+
} else {
|
|
60
|
+
filtered = statusResults.filter(r => !r.installed).map(r => r.tool);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (filtered.length === 0) {
|
|
65
|
+
context.output.info('No tools match the current filters.');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Build output rows with install status
|
|
70
|
+
const rows = [];
|
|
71
|
+
for (const tool of filtered) {
|
|
72
|
+
let status = '-';
|
|
73
|
+
try {
|
|
74
|
+
const mod = installer.loadInstaller(tool);
|
|
75
|
+
const isInst = await mod.isInstalled(context);
|
|
76
|
+
status = isInst ? 'yes' : 'no';
|
|
77
|
+
} catch {
|
|
78
|
+
status = '?';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
rows.push({
|
|
82
|
+
Name: tool.name,
|
|
83
|
+
Description: tool.description,
|
|
84
|
+
Installed: status,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
context.output.out(rows);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = { meta, run };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Command: dev tools search <query>
|
|
5
|
+
*
|
|
6
|
+
* Searches for tools by name or keyword in the registry.
|
|
7
|
+
* Matches against tool name and description (case-insensitive).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @type {{ description: string, arguments: Array, flags: Array }}
|
|
12
|
+
*/
|
|
13
|
+
const meta = {
|
|
14
|
+
description: 'Search for tools by name or keyword',
|
|
15
|
+
arguments: [
|
|
16
|
+
{ name: 'query', description: 'Search term (matches name and description)', required: true }
|
|
17
|
+
],
|
|
18
|
+
flags: []
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Runs the search command.
|
|
23
|
+
* @param {{ positional: string[], flags: object }} args - Parsed command arguments.
|
|
24
|
+
* @param {object} context - The CLI context object.
|
|
25
|
+
*/
|
|
26
|
+
async function run(args, context) {
|
|
27
|
+
const query = args.positional[0];
|
|
28
|
+
|
|
29
|
+
if (!query) {
|
|
30
|
+
context.errors.throwError(400, 'Missing required argument: query. Usage: dev tools search <query>', 'tools');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const installer = require('../../lib/installer');
|
|
35
|
+
|
|
36
|
+
// Load the registry and search
|
|
37
|
+
const tools = installer.loadRegistry();
|
|
38
|
+
const lower = query.toLowerCase();
|
|
39
|
+
|
|
40
|
+
const matches = tools.filter(t =>
|
|
41
|
+
t.name.toLowerCase().includes(lower) ||
|
|
42
|
+
t.description.toLowerCase().includes(lower)
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
if (matches.length === 0) {
|
|
46
|
+
context.output.info(`No tools found matching '${query}'.`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Format as table with name, description, and platforms
|
|
51
|
+
const rows = matches.map(t => ({
|
|
52
|
+
Name: t.name,
|
|
53
|
+
Description: t.description,
|
|
54
|
+
Platforms: t.platforms.join(', '),
|
|
55
|
+
}));
|
|
56
|
+
|
|
57
|
+
context.output.out(rows);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
module.exports = { meta, run };
|
package/src/commands/update.js
CHANGED
|
@@ -1,142 +1,113 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
* @fileoverview Update command - Update this package to the latest version.
|
|
5
|
-
* Queries the NPM registry and installs the latest version globally.
|
|
6
|
-
*/
|
|
3
|
+
const shell = require('../lib/shell');
|
|
7
4
|
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
const meta = {
|
|
6
|
+
description: 'Self-update to the latest published version.',
|
|
7
|
+
arguments: [],
|
|
8
|
+
flags: [
|
|
9
|
+
{ name: 'check', description: 'Check for updates without installing' },
|
|
10
|
+
],
|
|
11
|
+
};
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
*
|
|
14
|
+
* Get the current installed version from package.json.
|
|
15
|
+
* @returns {string}
|
|
14
16
|
*/
|
|
15
|
-
|
|
17
|
+
function getCurrentVersion() {
|
|
18
|
+
const pkg = require('../../package.json');
|
|
19
|
+
return pkg.version;
|
|
20
|
+
}
|
|
16
21
|
|
|
17
22
|
/**
|
|
18
|
-
* Get the latest version
|
|
19
|
-
* @returns {string|null}
|
|
23
|
+
* Get the latest version from the npm registry.
|
|
24
|
+
* @returns {Promise<string|null>}
|
|
20
25
|
*/
|
|
21
|
-
function getLatestVersion() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
26
|
-
});
|
|
27
|
-
return result.trim();
|
|
28
|
-
} catch {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
26
|
+
async function getLatestVersion() {
|
|
27
|
+
const result = await shell.exec('npm view @fredlackey/devutils version');
|
|
28
|
+
if (result.exitCode !== 0) return null;
|
|
29
|
+
return result.stdout.trim() || null;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
/**
|
|
34
|
-
* Compare two
|
|
35
|
-
* @param {string}
|
|
36
|
-
* @param {string}
|
|
37
|
-
* @returns {boolean}
|
|
33
|
+
* Compare two semver strings. Returns true if latest is newer than current.
|
|
34
|
+
* @param {string} latest
|
|
35
|
+
* @param {string} current
|
|
36
|
+
* @returns {boolean}
|
|
38
37
|
*/
|
|
39
|
-
function
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
for (let i = 0; i < 3; i++) {
|
|
48
|
-
const currentPart = currentParts[i] || 0;
|
|
49
|
-
const latestPart = latestParts[i] || 0;
|
|
50
|
-
|
|
51
|
-
if (latestPart > currentPart) {
|
|
52
|
-
return true;
|
|
53
|
-
}
|
|
54
|
-
if (latestPart < currentPart) {
|
|
55
|
-
return false;
|
|
56
|
-
}
|
|
38
|
+
function isNewer(latest, current) {
|
|
39
|
+
const l = latest.split('.').map(Number);
|
|
40
|
+
const c = current.split('.').map(Number);
|
|
41
|
+
for (let i = 0; i < Math.max(l.length, c.length); i++) {
|
|
42
|
+
const lv = l[i] || 0;
|
|
43
|
+
const cv = c[i] || 0;
|
|
44
|
+
if (lv > cv) return true;
|
|
45
|
+
if (lv < cv) return false;
|
|
57
46
|
}
|
|
58
|
-
|
|
59
47
|
return false;
|
|
60
48
|
}
|
|
61
49
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return new Promise((resolve) => {
|
|
68
|
-
console.log(`\nInstalling ${PACKAGE_NAME}@latest globally...`);
|
|
69
|
-
console.log('─'.repeat(40));
|
|
70
|
-
|
|
71
|
-
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
72
|
-
const child = spawn(npmCommand, ['install', '-g', `${PACKAGE_NAME}@latest`], {
|
|
73
|
-
stdio: 'inherit'
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
child.on('close', (code) => {
|
|
77
|
-
if (code === 0) {
|
|
78
|
-
resolve(true);
|
|
79
|
-
} else {
|
|
80
|
-
resolve(false);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
child.on('error', () => {
|
|
85
|
-
resolve(false);
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Check for updates and install if available
|
|
92
|
-
* @param {object} options - Command options
|
|
93
|
-
*/
|
|
94
|
-
async function runUpdate(options) {
|
|
95
|
-
const currentVersion = pkg.version;
|
|
96
|
-
|
|
97
|
-
console.log(`\n${pkg.name}`);
|
|
98
|
-
console.log('─'.repeat(40));
|
|
99
|
-
console.log(`Current version: ${currentVersion}`);
|
|
50
|
+
async function run(args, context) {
|
|
51
|
+
if (!shell.commandExists('npm')) {
|
|
52
|
+
context.errors.throwError(500, 'npm is not available on this system. Install Node.js and npm first.', 'update');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
100
55
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
56
|
+
const current = getCurrentVersion();
|
|
57
|
+
context.output.info(`Current version: ${current}`);
|
|
58
|
+
context.output.info('Checking for updates...');
|
|
104
59
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
60
|
+
const latest = await getLatestVersion();
|
|
61
|
+
if (!latest) {
|
|
62
|
+
context.errors.throwError(500, 'Could not reach the npm registry. Check your network connection.', 'update');
|
|
108
63
|
return;
|
|
109
64
|
}
|
|
110
65
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
66
|
+
if (!isNewer(latest, current)) {
|
|
67
|
+
const result = {
|
|
68
|
+
current,
|
|
69
|
+
latest,
|
|
70
|
+
updateAvailable: false,
|
|
71
|
+
message: `Already on the latest version (${current}).`,
|
|
72
|
+
};
|
|
73
|
+
context.output.out(result);
|
|
116
74
|
return;
|
|
117
75
|
}
|
|
118
76
|
|
|
119
|
-
|
|
77
|
+
// Update available
|
|
78
|
+
if (args.flags.check) {
|
|
79
|
+
const result = {
|
|
80
|
+
current,
|
|
81
|
+
latest,
|
|
82
|
+
updateAvailable: true,
|
|
83
|
+
message: `Update available: ${current} -> ${latest}. Run "dev update" to install.`,
|
|
84
|
+
};
|
|
85
|
+
context.output.out(result);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
120
88
|
|
|
121
89
|
// Perform the update
|
|
122
|
-
|
|
90
|
+
context.output.info(`Updating from ${current} to ${latest}...`);
|
|
123
91
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
92
|
+
const installResult = await shell.exec('npm install -g @fredlackey/devutils@latest');
|
|
93
|
+
|
|
94
|
+
if (installResult.exitCode !== 0) {
|
|
95
|
+
const msg = installResult.stderr || '';
|
|
96
|
+
if (msg.includes('EACCES') || msg.includes('permission')) {
|
|
97
|
+
context.errors.throwError(403, 'Permission denied. Try running with sudo: sudo dev update', 'update');
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
context.errors.throwError(500, `Update failed: ${msg}`, 'update');
|
|
101
|
+
return;
|
|
134
102
|
}
|
|
135
|
-
}
|
|
136
103
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
104
|
+
const result = {
|
|
105
|
+
previous: current,
|
|
106
|
+
current: latest,
|
|
107
|
+
updateAvailable: false,
|
|
108
|
+
message: `Updated to ${latest}. Restart your terminal to use the new version.`,
|
|
109
|
+
};
|
|
110
|
+
context.output.out(result);
|
|
111
|
+
}
|
|
141
112
|
|
|
142
|
-
module.exports =
|
|
113
|
+
module.exports = { meta, run };
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
description: 'Register a custom utility by name and source path. Copies the script into ~/.devutils/utils/.',
|
|
9
|
+
arguments: [
|
|
10
|
+
{ name: 'name', required: true, description: 'Name for the utility (used in dev util run <name>)' },
|
|
11
|
+
{ name: 'path', required: true, description: 'Path to the script file or directory to register' },
|
|
12
|
+
],
|
|
13
|
+
flags: [
|
|
14
|
+
{ name: 'link', description: 'Create a symlink instead of copying (for active development)' },
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Recursively copy a directory.
|
|
20
|
+
* @param {string} src - Source directory path.
|
|
21
|
+
* @param {string} dest - Destination directory path.
|
|
22
|
+
*/
|
|
23
|
+
function copyDirectorySync(src, dest) {
|
|
24
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
25
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
26
|
+
for (const entry of entries) {
|
|
27
|
+
const srcPath = path.join(src, entry.name);
|
|
28
|
+
const destPath = path.join(dest, entry.name);
|
|
29
|
+
if (entry.isDirectory()) {
|
|
30
|
+
copyDirectorySync(srcPath, destPath);
|
|
31
|
+
} else {
|
|
32
|
+
fs.copyFileSync(srcPath, destPath);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function run(args, context) {
|
|
38
|
+
const name = args.positional[0];
|
|
39
|
+
const sourcePath = args.positional[1];
|
|
40
|
+
|
|
41
|
+
if (!name || !sourcePath) {
|
|
42
|
+
context.errors.throwError(400, 'Usage: dev util add <name> <path>', 'util');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!/^[a-z0-9][a-z0-9-]*$/.test(name)) {
|
|
47
|
+
context.output.error('Utility names must be lowercase letters, numbers, and hyphens only.');
|
|
48
|
+
context.output.info('Example: my-script, git-helper, deploy-2');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Check for name conflicts with built-in utilities
|
|
53
|
+
const builtInRegistry = require('../../utils/registry.json');
|
|
54
|
+
const isBuiltIn = (builtInRegistry.utilities || []).some(u => u.name === name);
|
|
55
|
+
if (isBuiltIn) {
|
|
56
|
+
context.output.error(`"${name}" is a built-in utility and cannot be overridden.`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const customDir = path.join(os.homedir(), '.devutils', 'utils');
|
|
61
|
+
const existingFolder = path.join(customDir, name);
|
|
62
|
+
const existingFile = path.join(customDir, name + '.js');
|
|
63
|
+
if (fs.existsSync(existingFolder) || fs.existsSync(existingFile)) {
|
|
64
|
+
context.output.error(`A custom utility named "${name}" already exists.`);
|
|
65
|
+
context.output.info('Remove it first with: dev util remove ' + name);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Validate the source path
|
|
70
|
+
const resolvedSource = path.resolve(sourcePath);
|
|
71
|
+
if (!fs.existsSync(resolvedSource)) {
|
|
72
|
+
context.output.error(`Source path not found: ${resolvedSource}`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const stat = fs.statSync(resolvedSource);
|
|
77
|
+
let entryPoint;
|
|
78
|
+
|
|
79
|
+
if (stat.isDirectory()) {
|
|
80
|
+
entryPoint = path.join(resolvedSource, 'index.js');
|
|
81
|
+
if (!fs.existsSync(entryPoint)) {
|
|
82
|
+
context.output.error('Directory does not contain an index.js file.');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
} else if (stat.isFile() && resolvedSource.endsWith('.js')) {
|
|
86
|
+
entryPoint = resolvedSource;
|
|
87
|
+
} else {
|
|
88
|
+
context.output.error('Source must be a .js file or a directory containing index.js.');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Verify it exports a run function
|
|
93
|
+
try {
|
|
94
|
+
const mod = require(entryPoint);
|
|
95
|
+
if (typeof mod.run !== 'function') {
|
|
96
|
+
context.output.error('The source file must export a run() function.');
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
} catch (err) {
|
|
100
|
+
context.output.error(`Failed to load source file: ${err.message}`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Copy or link the utility
|
|
105
|
+
fs.mkdirSync(customDir, { recursive: true });
|
|
106
|
+
|
|
107
|
+
if (args.flags.link) {
|
|
108
|
+
const linkTarget = stat.isDirectory()
|
|
109
|
+
? path.join(customDir, name)
|
|
110
|
+
: path.join(customDir, name + '.js');
|
|
111
|
+
fs.symlinkSync(resolvedSource, linkTarget);
|
|
112
|
+
} else {
|
|
113
|
+
if (stat.isDirectory()) {
|
|
114
|
+
copyDirectorySync(resolvedSource, path.join(customDir, name));
|
|
115
|
+
} else {
|
|
116
|
+
fs.copyFileSync(resolvedSource, path.join(customDir, name + '.js'));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Update the custom registry
|
|
121
|
+
const registryPath = path.join(customDir, 'registry.json');
|
|
122
|
+
let registry = { utilities: [] };
|
|
123
|
+
if (fs.existsSync(registryPath)) {
|
|
124
|
+
try {
|
|
125
|
+
registry = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
|
|
126
|
+
} catch {
|
|
127
|
+
registry = { utilities: [] };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const mod = require(entryPoint);
|
|
132
|
+
const utilMeta = mod.meta || {};
|
|
133
|
+
|
|
134
|
+
registry.utilities.push({
|
|
135
|
+
name: name,
|
|
136
|
+
description: utilMeta.description || '',
|
|
137
|
+
type: 'custom',
|
|
138
|
+
platforms: utilMeta.platforms || [],
|
|
139
|
+
arguments: utilMeta.arguments || [],
|
|
140
|
+
flags: utilMeta.flags || [],
|
|
141
|
+
source: resolvedSource,
|
|
142
|
+
linked: !!args.flags.link,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
fs.writeFileSync(registryPath, JSON.stringify(registry, null, 2) + '\n');
|
|
146
|
+
|
|
147
|
+
context.output.info(`Utility "${name}" registered successfully.`);
|
|
148
|
+
context.output.info(`Run it with: dev util run ${name}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
module.exports = { meta, run };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Util service registration.
|
|
3
|
+
* Complex utility functions (platform-aware).
|
|
4
|
+
*/
|
|
5
|
+
module.exports = {
|
|
6
|
+
name: 'util',
|
|
7
|
+
description: 'Complex utility functions (platform-aware)',
|
|
8
|
+
commands: {
|
|
9
|
+
run: () => require('./run'),
|
|
10
|
+
list: () => require('./list'),
|
|
11
|
+
show: () => require('./show'),
|
|
12
|
+
add: () => require('./add'),
|
|
13
|
+
remove: () => require('./remove'),
|
|
14
|
+
}
|
|
15
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
description: 'List available utilities. Use flags to filter by source.',
|
|
9
|
+
arguments: [],
|
|
10
|
+
flags: [
|
|
11
|
+
{ name: 'built-in', description: 'Show only built-in utilities' },
|
|
12
|
+
{ name: 'custom', description: 'Show only user-added utilities' },
|
|
13
|
+
],
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Load custom utilities from ~/.devutils/utils/.
|
|
18
|
+
* Checks for a registry.json first; falls back to scanning directories.
|
|
19
|
+
*
|
|
20
|
+
* @returns {Array<object>} Array of utility metadata objects.
|
|
21
|
+
*/
|
|
22
|
+
function loadCustomUtilities() {
|
|
23
|
+
const customDir = path.join(os.homedir(), '.devutils', 'utils');
|
|
24
|
+
if (!fs.existsSync(customDir)) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const registryPath = path.join(customDir, 'registry.json');
|
|
29
|
+
if (fs.existsSync(registryPath)) {
|
|
30
|
+
try {
|
|
31
|
+
const data = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
|
|
32
|
+
return (data.utilities || []).map(u => ({ ...u, type: 'custom' }));
|
|
33
|
+
} catch {
|
|
34
|
+
// Fall through to directory scan
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Fallback: scan directories for index.js with meta exports
|
|
39
|
+
const entries = fs.readdirSync(customDir, { withFileTypes: true });
|
|
40
|
+
const utilities = [];
|
|
41
|
+
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
if (entry.name === 'registry.json') continue;
|
|
44
|
+
|
|
45
|
+
let indexPath;
|
|
46
|
+
if (entry.isDirectory()) {
|
|
47
|
+
indexPath = path.join(customDir, entry.name, 'index.js');
|
|
48
|
+
} else if (entry.isFile() && entry.name.endsWith('.js')) {
|
|
49
|
+
indexPath = path.join(customDir, entry.name);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (indexPath && fs.existsSync(indexPath)) {
|
|
53
|
+
try {
|
|
54
|
+
const mod = require(indexPath);
|
|
55
|
+
if (mod.meta) {
|
|
56
|
+
utilities.push({
|
|
57
|
+
name: mod.meta.name || entry.name.replace(/\.js$/, ''),
|
|
58
|
+
description: mod.meta.description || '',
|
|
59
|
+
type: 'custom',
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
// Skip utilities that fail to load
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return utilities;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function run(args, context) {
|
|
72
|
+
const builtInRegistry = require('../../utils/registry.json');
|
|
73
|
+
const results = [];
|
|
74
|
+
|
|
75
|
+
if (!args.flags.custom) {
|
|
76
|
+
for (const util of builtInRegistry.utilities || []) {
|
|
77
|
+
results.push({ Name: util.name, Description: util.description, Type: 'built-in' });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!args.flags['built-in']) {
|
|
82
|
+
const custom = loadCustomUtilities();
|
|
83
|
+
for (const util of custom) {
|
|
84
|
+
results.push({ Name: util.name, Description: util.description || '', Type: 'custom' });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (results.length === 0) {
|
|
89
|
+
context.output.info('No utilities found.');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
context.output.out(results);
|
|
94
|
+
context.output.info(`\n${results.length} ${results.length === 1 ? 'utility' : 'utilities'} available.`);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
module.exports = { meta, run };
|