@fredlackey/devutils 0.0.18 → 0.0.19
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 +32 -150
- package/package.json +5 -82
- 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/cli.js +0 -72
- 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/commands/status.js +0 -223
- package/src/commands/update.js +0 -142
- package/src/commands/version.js +0 -100
- 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
package/src/commands/install.js
DELETED
|
@@ -1,526 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @fileoverview Install command - Platform-agnostic installation of development tools.
|
|
5
|
-
*
|
|
6
|
-
* This command handles the installation of development tools with automatic
|
|
7
|
-
* dependency resolution. It performs the following steps for each technology:
|
|
8
|
-
*
|
|
9
|
-
* 1. Check if already installed using isInstalled() - skip if true
|
|
10
|
-
* 2. Check if eligible for current platform using isEligible() - fail if false
|
|
11
|
-
* 3. Resolve dependencies from installers.json
|
|
12
|
-
* 4. Recursively check and install dependencies first
|
|
13
|
-
* 5. Install the requested technology
|
|
14
|
-
*
|
|
15
|
-
* @module commands/install
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
const { Command } = require('commander');
|
|
19
|
-
const fs = require('fs');
|
|
20
|
-
const path = require('path');
|
|
21
|
-
const readline = require('readline');
|
|
22
|
-
const os = require('../utils/common/os');
|
|
23
|
-
|
|
24
|
-
const INSTALLS_DIR = path.join(__dirname, '..', 'installs');
|
|
25
|
-
const INSTALLERS_JSON = path.join(INSTALLS_DIR, 'installers.json');
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Cache for loaded installer modules to avoid reloading
|
|
29
|
-
* @type {Map<string, object>}
|
|
30
|
-
*/
|
|
31
|
-
const installerCache = new Map();
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Cache for installer metadata from installers.json
|
|
35
|
-
* @type {Array<object>|null}
|
|
36
|
-
*/
|
|
37
|
-
let installersMetadata = null;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Load the installers.json metadata file
|
|
41
|
-
* @returns {Array<object>} Array of installer metadata objects
|
|
42
|
-
*/
|
|
43
|
-
function loadInstallersMetadata() {
|
|
44
|
-
if (installersMetadata !== null) {
|
|
45
|
-
return installersMetadata;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
if (!fs.existsSync(INSTALLERS_JSON)) {
|
|
50
|
-
console.warn('Warning: installers.json not found. Dependency resolution disabled.');
|
|
51
|
-
installersMetadata = [];
|
|
52
|
-
return installersMetadata;
|
|
53
|
-
}
|
|
54
|
-
const content = fs.readFileSync(INSTALLERS_JSON, 'utf8');
|
|
55
|
-
installersMetadata = JSON.parse(content);
|
|
56
|
-
return installersMetadata;
|
|
57
|
-
} catch (err) {
|
|
58
|
-
console.warn(`Warning: Failed to load installers.json: ${err.message}`);
|
|
59
|
-
installersMetadata = [];
|
|
60
|
-
return installersMetadata;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Get metadata for a specific installer by filename
|
|
66
|
-
* @param {string} filename - The installer filename (e.g., "node.js")
|
|
67
|
-
* @returns {object|null} The installer metadata or null if not found
|
|
68
|
-
*/
|
|
69
|
-
function getInstallerMetadata(filename) {
|
|
70
|
-
const metadata = loadInstallersMetadata();
|
|
71
|
-
return metadata.find(m => m.filename === filename) || null;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Load an installer module by name
|
|
76
|
-
* @param {string} name - Name of the installer (without .js extension)
|
|
77
|
-
* @returns {object|null} The installer module or null if not found
|
|
78
|
-
*/
|
|
79
|
-
function loadInstaller(name) {
|
|
80
|
-
const filename = `${name}.js`;
|
|
81
|
-
|
|
82
|
-
// Check cache first
|
|
83
|
-
if (installerCache.has(filename)) {
|
|
84
|
-
return installerCache.get(filename);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const scriptPath = path.join(INSTALLS_DIR, filename);
|
|
88
|
-
|
|
89
|
-
if (!fs.existsSync(scriptPath)) {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
try {
|
|
94
|
-
const installer = require(scriptPath);
|
|
95
|
-
installerCache.set(filename, installer);
|
|
96
|
-
return installer;
|
|
97
|
-
} catch (err) {
|
|
98
|
-
console.error(`Error loading installer ${name}: ${err.message}`);
|
|
99
|
-
return null;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Get list of available install scripts
|
|
105
|
-
* @returns {string[]} Array of install script names (without .js extension)
|
|
106
|
-
*/
|
|
107
|
-
function getAvailableInstalls() {
|
|
108
|
-
try {
|
|
109
|
-
if (!fs.existsSync(INSTALLS_DIR)) {
|
|
110
|
-
return [];
|
|
111
|
-
}
|
|
112
|
-
return fs.readdirSync(INSTALLS_DIR)
|
|
113
|
-
.filter(file => file.endsWith('.js'))
|
|
114
|
-
.map(file => file.replace('.js', ''))
|
|
115
|
-
.sort();
|
|
116
|
-
} catch {
|
|
117
|
-
return [];
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Prompt user for confirmation
|
|
123
|
-
* @param {string} question - Question to ask
|
|
124
|
-
* @returns {Promise<boolean>}
|
|
125
|
-
*/
|
|
126
|
-
function confirm(question) {
|
|
127
|
-
return new Promise(resolve => {
|
|
128
|
-
const rl = readline.createInterface({
|
|
129
|
-
input: process.stdin,
|
|
130
|
-
output: process.stdout
|
|
131
|
-
});
|
|
132
|
-
rl.question(`${question} (y/n): `, answer => {
|
|
133
|
-
rl.close();
|
|
134
|
-
resolve(answer.toLowerCase().startsWith('y'));
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Check if a technology is installed
|
|
141
|
-
* @param {string} name - Name of the technology (without .js extension)
|
|
142
|
-
* @returns {Promise<boolean>} True if installed, false otherwise
|
|
143
|
-
*/
|
|
144
|
-
async function checkIsInstalled(name) {
|
|
145
|
-
const installer = loadInstaller(name);
|
|
146
|
-
|
|
147
|
-
if (!installer) {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Check if installer has isInstalled function
|
|
152
|
-
if (typeof installer.isInstalled !== 'function') {
|
|
153
|
-
// If no isInstalled function, assume not installed (will try to install)
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
try {
|
|
158
|
-
// isInstalled may be sync or async
|
|
159
|
-
const result = installer.isInstalled();
|
|
160
|
-
if (result instanceof Promise) {
|
|
161
|
-
return await result;
|
|
162
|
-
}
|
|
163
|
-
return result;
|
|
164
|
-
} catch (err) {
|
|
165
|
-
// If check fails, assume not installed
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Check if a technology is eligible for the current platform
|
|
172
|
-
* @param {string} name - Name of the technology (without .js extension)
|
|
173
|
-
* @returns {boolean} True if eligible, false otherwise
|
|
174
|
-
*/
|
|
175
|
-
function checkIsEligible(name) {
|
|
176
|
-
const installer = loadInstaller(name);
|
|
177
|
-
|
|
178
|
-
if (!installer) {
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// Check if installer has isEligible function
|
|
183
|
-
if (typeof installer.isEligible !== 'function') {
|
|
184
|
-
// If no isEligible function, assume eligible (backwards compatibility)
|
|
185
|
-
return true;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
try {
|
|
189
|
-
return installer.isEligible();
|
|
190
|
-
} catch (err) {
|
|
191
|
-
// If check fails, assume not eligible
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/**
|
|
197
|
-
* Get the display name for a technology from metadata
|
|
198
|
-
* @param {string} filename - The installer filename
|
|
199
|
-
* @returns {string} The display name or the filename without extension
|
|
200
|
-
*/
|
|
201
|
-
function getDisplayName(filename) {
|
|
202
|
-
const metadata = getInstallerMetadata(filename);
|
|
203
|
-
if (metadata && metadata.name) {
|
|
204
|
-
return metadata.name;
|
|
205
|
-
}
|
|
206
|
-
return filename.replace('.js', '');
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Resolve dependencies for a technology, filtering by eligibility
|
|
211
|
-
*
|
|
212
|
-
* This function recursively resolves all dependencies for a given technology,
|
|
213
|
-
* returning them in the correct installation order (dependencies first).
|
|
214
|
-
*
|
|
215
|
-
* @param {string} name - Name of the technology (without .js extension)
|
|
216
|
-
* @param {Set<string>} visited - Set of already visited technologies (for cycle detection)
|
|
217
|
-
* @param {Set<string>} installing - Set of technologies currently being resolved (for cycle detection)
|
|
218
|
-
* @param {object} options - Command options
|
|
219
|
-
* @returns {Promise<Array<{name: string, displayName: string}>>} Array of technologies to install in order
|
|
220
|
-
*/
|
|
221
|
-
async function resolveDependencies(name, visited = new Set(), installing = new Set(), options = {}) {
|
|
222
|
-
const filename = `${name}.js`;
|
|
223
|
-
const result = [];
|
|
224
|
-
|
|
225
|
-
// Detect circular dependencies
|
|
226
|
-
if (installing.has(filename)) {
|
|
227
|
-
if (options.verbose) {
|
|
228
|
-
console.log(` [Skipping circular dependency: ${name}]`);
|
|
229
|
-
}
|
|
230
|
-
return result;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Skip if already processed
|
|
234
|
-
if (visited.has(filename)) {
|
|
235
|
-
return result;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Mark as being processed
|
|
239
|
-
installing.add(filename);
|
|
240
|
-
|
|
241
|
-
// Get metadata for this installer
|
|
242
|
-
const metadata = getInstallerMetadata(filename);
|
|
243
|
-
const dependencies = metadata?.depends_on || [];
|
|
244
|
-
|
|
245
|
-
// Sort dependencies by priority (lower priority = install first)
|
|
246
|
-
const sortedDeps = [...dependencies].sort((a, b) => (a.priority || 0) - (b.priority || 0));
|
|
247
|
-
|
|
248
|
-
// Get current platform for filtering platform-specific dependencies
|
|
249
|
-
const currentPlatform = os.detect().type;
|
|
250
|
-
|
|
251
|
-
// Process each dependency
|
|
252
|
-
for (const dep of sortedDeps) {
|
|
253
|
-
const depName = dep.name.replace('.js', '');
|
|
254
|
-
|
|
255
|
-
// Check if dependency is platform-specific and applies to current platform
|
|
256
|
-
// If 'platforms' is not specified, the dependency applies to all platforms
|
|
257
|
-
if (dep.platforms && dep.platforms.length > 0) {
|
|
258
|
-
if (!dep.platforms.includes(currentPlatform)) {
|
|
259
|
-
if (options.verbose) {
|
|
260
|
-
console.log(` [Skipping ${depName}: not needed on ${currentPlatform}]`);
|
|
261
|
-
}
|
|
262
|
-
continue;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Check if dependency is eligible for this platform
|
|
267
|
-
if (!checkIsEligible(depName)) {
|
|
268
|
-
if (options.verbose) {
|
|
269
|
-
console.log(` [Skipping ineligible dependency: ${depName}]`);
|
|
270
|
-
}
|
|
271
|
-
continue;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// Check if dependency is already installed
|
|
275
|
-
const isInstalled = await checkIsInstalled(depName);
|
|
276
|
-
if (isInstalled) {
|
|
277
|
-
if (options.verbose) {
|
|
278
|
-
console.log(` [Dependency already installed: ${depName}]`);
|
|
279
|
-
}
|
|
280
|
-
visited.add(dep.name);
|
|
281
|
-
continue;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Recursively resolve this dependency's dependencies
|
|
285
|
-
const subDeps = await resolveDependencies(depName, visited, installing, options);
|
|
286
|
-
result.push(...subDeps);
|
|
287
|
-
|
|
288
|
-
// Add this dependency if not already visited
|
|
289
|
-
if (!visited.has(dep.name)) {
|
|
290
|
-
result.push({
|
|
291
|
-
name: depName,
|
|
292
|
-
displayName: getDisplayName(dep.name)
|
|
293
|
-
});
|
|
294
|
-
visited.add(dep.name);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Mark as processed (no longer being resolved)
|
|
299
|
-
installing.delete(filename);
|
|
300
|
-
|
|
301
|
-
return result;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Install a single technology
|
|
306
|
-
* @param {string} name - Name of the technology to install
|
|
307
|
-
* @param {object} options - Command options
|
|
308
|
-
* @returns {Promise<boolean>} True if installation succeeded
|
|
309
|
-
*/
|
|
310
|
-
async function installSingle(name, options) {
|
|
311
|
-
const installer = loadInstaller(name);
|
|
312
|
-
|
|
313
|
-
if (!installer) {
|
|
314
|
-
console.error(`Error: Installer for "${name}" not found.`);
|
|
315
|
-
return false;
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
if (typeof installer.install !== 'function') {
|
|
319
|
-
console.error(`Error: Installer "${name}" does not export an install() function.`);
|
|
320
|
-
return false;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
try {
|
|
324
|
-
const installOptions = {
|
|
325
|
-
dryRun: options.dryRun || false,
|
|
326
|
-
verbose: options.verbose || false,
|
|
327
|
-
force: options.force || false
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
await installer.install(installOptions);
|
|
331
|
-
return true;
|
|
332
|
-
} catch (err) {
|
|
333
|
-
console.error(`Error installing ${name}: ${err.message}`);
|
|
334
|
-
if (options.verbose) {
|
|
335
|
-
console.error(err.stack);
|
|
336
|
-
}
|
|
337
|
-
return false;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* List all available install scripts
|
|
343
|
-
*/
|
|
344
|
-
function listInstalls() {
|
|
345
|
-
const installs = getAvailableInstalls();
|
|
346
|
-
|
|
347
|
-
if (installs.length === 0) {
|
|
348
|
-
console.log('\nNo install scripts available.');
|
|
349
|
-
console.log(`Install scripts should be placed in: ${INSTALLS_DIR}\n`);
|
|
350
|
-
return;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
console.log('\nAvailable install scripts:');
|
|
354
|
-
console.log('─'.repeat(40));
|
|
355
|
-
|
|
356
|
-
for (const name of installs) {
|
|
357
|
-
const filename = `${name}.js`;
|
|
358
|
-
const displayName = getDisplayName(filename);
|
|
359
|
-
const eligible = checkIsEligible(name);
|
|
360
|
-
const eligibleMark = eligible ? '' : ' (not available on this platform)';
|
|
361
|
-
console.log(` ${name}${eligibleMark}`);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
console.log(`\nUsage: dev install <name>`);
|
|
365
|
-
console.log('');
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/**
|
|
369
|
-
* Run an install with dependency resolution
|
|
370
|
-
* @param {string} name - Name of the install script
|
|
371
|
-
* @param {object} options - Command options
|
|
372
|
-
*/
|
|
373
|
-
async function runInstall(name, options) {
|
|
374
|
-
if (!name) {
|
|
375
|
-
console.error('\nError: No package specified.');
|
|
376
|
-
console.log('Usage: dev install <name>');
|
|
377
|
-
console.log('Run `dev install --list` to see available options.\n');
|
|
378
|
-
process.exit(1);
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
const scriptPath = path.join(INSTALLS_DIR, `${name}.js`);
|
|
382
|
-
const filename = `${name}.js`;
|
|
383
|
-
|
|
384
|
-
// Check if install script exists
|
|
385
|
-
if (!fs.existsSync(scriptPath)) {
|
|
386
|
-
console.error(`\nError: Unknown package "${name}".`);
|
|
387
|
-
console.log('Run `dev install --list` to see available options.\n');
|
|
388
|
-
process.exit(1);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// Get display name for output
|
|
392
|
-
const displayName = getDisplayName(filename);
|
|
393
|
-
|
|
394
|
-
console.log(`\nChecking ${displayName}...`);
|
|
395
|
-
|
|
396
|
-
// Step 1: Check if already installed
|
|
397
|
-
const isInstalled = await checkIsInstalled(name);
|
|
398
|
-
if (isInstalled) {
|
|
399
|
-
console.log(`${displayName} is already installed.`);
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Step 2: Check if eligible for this platform
|
|
404
|
-
const isEligible = checkIsEligible(name);
|
|
405
|
-
if (!isEligible) {
|
|
406
|
-
console.log(`${displayName} is not available for this platform.`);
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
// Step 3: Resolve dependencies
|
|
411
|
-
if (options.verbose) {
|
|
412
|
-
console.log(`Resolving dependencies for ${displayName}...`);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
const dependencies = await resolveDependencies(name, new Set(), new Set(), options);
|
|
416
|
-
|
|
417
|
-
// Build the full installation list (dependencies + target)
|
|
418
|
-
const toInstall = [
|
|
419
|
-
...dependencies,
|
|
420
|
-
{ name, displayName }
|
|
421
|
-
];
|
|
422
|
-
|
|
423
|
-
// Remove duplicates while preserving order
|
|
424
|
-
const seen = new Set();
|
|
425
|
-
const uniqueToInstall = toInstall.filter(item => {
|
|
426
|
-
if (seen.has(item.name)) {
|
|
427
|
-
return false;
|
|
428
|
-
}
|
|
429
|
-
seen.add(item.name);
|
|
430
|
-
return true;
|
|
431
|
-
});
|
|
432
|
-
|
|
433
|
-
// Show what will be installed
|
|
434
|
-
if (uniqueToInstall.length > 1) {
|
|
435
|
-
console.log(`\nThe following will be installed:`);
|
|
436
|
-
for (const item of uniqueToInstall) {
|
|
437
|
-
console.log(` - ${item.displayName}`);
|
|
438
|
-
}
|
|
439
|
-
console.log('');
|
|
440
|
-
} else {
|
|
441
|
-
console.log(`\nPreparing to install: ${displayName}`);
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
if (options.dryRun) {
|
|
445
|
-
console.log('[Dry run mode - no changes will be made]\n');
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// Confirm installation (unless --force)
|
|
449
|
-
if (!options.force) {
|
|
450
|
-
const shouldProceed = await confirm('Proceed with installation?');
|
|
451
|
-
if (!shouldProceed) {
|
|
452
|
-
console.log('Installation cancelled.');
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// Install each technology in order
|
|
458
|
-
let successCount = 0;
|
|
459
|
-
let failCount = 0;
|
|
460
|
-
|
|
461
|
-
for (const item of uniqueToInstall) {
|
|
462
|
-
console.log(`\n${'─'.repeat(50)}`);
|
|
463
|
-
console.log(`Installing ${item.displayName}...`);
|
|
464
|
-
console.log('─'.repeat(50));
|
|
465
|
-
|
|
466
|
-
if (options.verbose) {
|
|
467
|
-
console.log(`Script: ${path.join(INSTALLS_DIR, `${item.name}.js`)}`);
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
const success = await installSingle(item.name, options);
|
|
471
|
-
|
|
472
|
-
if (success) {
|
|
473
|
-
successCount++;
|
|
474
|
-
if (!options.dryRun) {
|
|
475
|
-
console.log(`${item.displayName} installed successfully.`);
|
|
476
|
-
}
|
|
477
|
-
} else {
|
|
478
|
-
failCount++;
|
|
479
|
-
console.error(`Failed to install ${item.displayName}.`);
|
|
480
|
-
|
|
481
|
-
// Ask if user wants to continue on failure (unless --force)
|
|
482
|
-
if (!options.force && uniqueToInstall.indexOf(item) < uniqueToInstall.length - 1) {
|
|
483
|
-
const shouldContinue = await confirm('Continue with remaining installations?');
|
|
484
|
-
if (!shouldContinue) {
|
|
485
|
-
console.log('Installation cancelled.');
|
|
486
|
-
break;
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// Summary
|
|
493
|
-
console.log(`\n${'─'.repeat(50)}`);
|
|
494
|
-
console.log('Installation Summary:');
|
|
495
|
-
console.log(` Successful: ${successCount}`);
|
|
496
|
-
if (failCount > 0) {
|
|
497
|
-
console.log(` Failed: ${failCount}`);
|
|
498
|
-
}
|
|
499
|
-
console.log('');
|
|
500
|
-
}
|
|
501
|
-
|
|
502
|
-
/**
|
|
503
|
-
* Handle the install command
|
|
504
|
-
* @param {string} name - Package name to install
|
|
505
|
-
* @param {object} options - Command options
|
|
506
|
-
*/
|
|
507
|
-
async function handleInstall(name, options) {
|
|
508
|
-
if (options.list) {
|
|
509
|
-
listInstalls();
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
await runInstall(name, options);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// Create and configure the command
|
|
517
|
-
const install = new Command('install')
|
|
518
|
-
.description('Platform-agnostic installation of development tools with automatic dependency resolution')
|
|
519
|
-
.argument('[name]', 'Name of the package to install')
|
|
520
|
-
.option('--list', 'List all available install scripts')
|
|
521
|
-
.option('--dry-run', 'Show what would be executed without running')
|
|
522
|
-
.option('--force', 'Skip confirmation prompts')
|
|
523
|
-
.option('--verbose', 'Show detailed output during installation')
|
|
524
|
-
.action(handleInstall);
|
|
525
|
-
|
|
526
|
-
module.exports = install;
|