@fredlackey/devutils 0.0.17 → 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 -1033
- 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 -216
- 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/utils/ubuntu/snap.js
DELETED
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Snap Package Manager Utilities
|
|
5
|
-
*
|
|
6
|
-
* Ubuntu-specific utilities for interacting with Snap packages.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const shell = require('../common/shell');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Checks if snapd is installed and the daemon is accessible.
|
|
13
|
-
*
|
|
14
|
-
* This function verifies both that the snap command exists AND that
|
|
15
|
-
* the snapd daemon is running and can be communicated with. This is
|
|
16
|
-
* important because in some environments (like Docker containers),
|
|
17
|
-
* the snap command may be installed but the daemon cannot run.
|
|
18
|
-
*
|
|
19
|
-
* @returns {boolean} True if snap command exists AND daemon is accessible
|
|
20
|
-
*/
|
|
21
|
-
function isInstalled() {
|
|
22
|
-
// First check if snap command exists
|
|
23
|
-
if (!shell.commandExists('snap')) {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Check if snapd daemon is accessible by checking snap version output
|
|
28
|
-
// Using syncExec for immediate result without spawning async process
|
|
29
|
-
const { execSync } = require('child_process');
|
|
30
|
-
try {
|
|
31
|
-
// Try to get snap version info with a short timeout
|
|
32
|
-
// In Docker without systemd, this may timeout or return "snapd unavailable"
|
|
33
|
-
const output = execSync('snap version 2>/dev/null', {
|
|
34
|
-
stdio: 'pipe',
|
|
35
|
-
timeout: 1000,
|
|
36
|
-
encoding: 'utf8'
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
// Check if snapd is listed as unavailable
|
|
40
|
-
// When snapd daemon is not running, snap version shows:
|
|
41
|
-
// snap 2.73+ubuntu22.04
|
|
42
|
-
// snapd unavailable
|
|
43
|
-
// series -
|
|
44
|
-
if (output.includes('snapd unavailable') || output.includes('snapd unavailable')) {
|
|
45
|
-
return false;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Also check for empty or malformed output
|
|
49
|
-
if (!output || output.trim().length === 0) {
|
|
50
|
-
return false;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return true;
|
|
54
|
-
} catch (err) {
|
|
55
|
-
// If snap version command fails (timeout, error), daemon is not accessible
|
|
56
|
-
// This handles the Docker case where snap command hangs trying to reach daemon
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Installs a snap package
|
|
63
|
-
* @param {string} snapName - The snap name to install
|
|
64
|
-
* @param {Object} [options] - Installation options
|
|
65
|
-
* @param {boolean} [options.classic=false] - Use classic confinement
|
|
66
|
-
* @param {string} [options.channel] - The channel to install from (stable, edge, etc.)
|
|
67
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
68
|
-
*/
|
|
69
|
-
async function install(snapName, options = {}) {
|
|
70
|
-
if (!isInstalled()) {
|
|
71
|
-
return {
|
|
72
|
-
success: false,
|
|
73
|
-
output: 'snap is not available'
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
let command = `sudo snap install ${snapName}`;
|
|
78
|
-
|
|
79
|
-
if (options.classic) {
|
|
80
|
-
command += ' --classic';
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (options.channel) {
|
|
84
|
-
command += ` --channel=${options.channel}`;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const result = await shell.exec(command);
|
|
88
|
-
return {
|
|
89
|
-
success: result.code === 0,
|
|
90
|
-
output: result.stdout || result.stderr
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Removes an installed snap
|
|
96
|
-
* @param {string} snapName - The snap name to remove
|
|
97
|
-
* @param {Object} [options] - Removal options
|
|
98
|
-
* @param {boolean} [options.purge=false] - Remove all data
|
|
99
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
100
|
-
*/
|
|
101
|
-
async function remove(snapName, options = {}) {
|
|
102
|
-
if (!isInstalled()) {
|
|
103
|
-
return {
|
|
104
|
-
success: false,
|
|
105
|
-
output: 'snap is not available'
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
let command = `sudo snap remove ${snapName}`;
|
|
110
|
-
|
|
111
|
-
if (options.purge) {
|
|
112
|
-
command += ' --purge';
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const result = await shell.exec(command);
|
|
116
|
-
return {
|
|
117
|
-
success: result.code === 0,
|
|
118
|
-
output: result.stdout || result.stderr
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Checks if a specific snap is installed
|
|
124
|
-
* @param {string} snapName - The snap name to check
|
|
125
|
-
* @returns {Promise<boolean>}
|
|
126
|
-
*/
|
|
127
|
-
async function isSnapInstalled(snapName) {
|
|
128
|
-
if (!isInstalled()) {
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const result = await shell.exec(`snap list ${snapName} 2>/dev/null`);
|
|
133
|
-
return result.code === 0;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Returns the installed version of a snap
|
|
138
|
-
* @param {string} snapName - The snap name
|
|
139
|
-
* @returns {Promise<string|null>}
|
|
140
|
-
*/
|
|
141
|
-
async function getSnapVersion(snapName) {
|
|
142
|
-
if (!isInstalled()) {
|
|
143
|
-
return null;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const result = await shell.exec(`snap list ${snapName} 2>/dev/null`);
|
|
147
|
-
if (result.code !== 0) {
|
|
148
|
-
return null;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Output format:
|
|
152
|
-
// Name Version Rev Tracking Publisher Notes
|
|
153
|
-
// code 1.85.0 151 latest/stable vscode classic
|
|
154
|
-
const lines = result.stdout.split('\n').filter(Boolean);
|
|
155
|
-
if (lines.length >= 2) {
|
|
156
|
-
const parts = lines[1].split(/\s+/);
|
|
157
|
-
if (parts.length >= 2) {
|
|
158
|
-
return parts[1]; // Version is the second column
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
return null;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
/**
|
|
166
|
-
* Updates a snap to the latest version
|
|
167
|
-
* @param {string} [snapName] - The snap to refresh (all if omitted)
|
|
168
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
169
|
-
*/
|
|
170
|
-
async function refresh(snapName) {
|
|
171
|
-
if (!isInstalled()) {
|
|
172
|
-
return {
|
|
173
|
-
success: false,
|
|
174
|
-
output: 'snap is not available'
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const command = snapName ? `sudo snap refresh ${snapName}` : 'sudo snap refresh';
|
|
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
|
-
* Lists all installed snaps
|
|
188
|
-
* @returns {Promise<Array<{ name: string, version: string, rev: string, tracking: string }>>}
|
|
189
|
-
*/
|
|
190
|
-
async function list() {
|
|
191
|
-
if (!isInstalled()) {
|
|
192
|
-
return [];
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
const result = await shell.exec('snap list');
|
|
196
|
-
if (result.code !== 0) {
|
|
197
|
-
return [];
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const lines = result.stdout.split('\n').filter(Boolean);
|
|
201
|
-
// Skip header line
|
|
202
|
-
if (lines.length <= 1) {
|
|
203
|
-
return [];
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return lines.slice(1).map((line) => {
|
|
207
|
-
const parts = line.split(/\s+/);
|
|
208
|
-
return {
|
|
209
|
-
name: parts[0] || '',
|
|
210
|
-
version: parts[1] || '',
|
|
211
|
-
rev: parts[2] || '',
|
|
212
|
-
tracking: parts[3] || ''
|
|
213
|
-
};
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Searches for snaps in the store
|
|
219
|
-
* @param {string} query - The search query
|
|
220
|
-
* @returns {Promise<Array<{ name: string, version: string, publisher: string, summary: string }>>}
|
|
221
|
-
*/
|
|
222
|
-
async function search(query) {
|
|
223
|
-
if (!isInstalled()) {
|
|
224
|
-
return [];
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const result = await shell.exec(`snap find "${query}"`);
|
|
228
|
-
if (result.code !== 0) {
|
|
229
|
-
return [];
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const lines = result.stdout.split('\n').filter(Boolean);
|
|
233
|
-
// Skip header line
|
|
234
|
-
if (lines.length <= 1) {
|
|
235
|
-
return [];
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return lines.slice(1).map((line) => {
|
|
239
|
-
const parts = line.split(/\s+/);
|
|
240
|
-
return {
|
|
241
|
-
name: parts[0] || '',
|
|
242
|
-
version: parts[1] || '',
|
|
243
|
-
publisher: parts[2] || '',
|
|
244
|
-
summary: parts.slice(3).join(' ') || ''
|
|
245
|
-
};
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Gets detailed information about a snap
|
|
251
|
-
* @param {string} snapName - The snap name
|
|
252
|
-
* @returns {Promise<string|null>}
|
|
253
|
-
*/
|
|
254
|
-
async function info(snapName) {
|
|
255
|
-
if (!isInstalled()) {
|
|
256
|
-
return null;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
const result = await shell.exec(`snap info ${snapName}`);
|
|
260
|
-
if (result.code === 0) {
|
|
261
|
-
return result.stdout;
|
|
262
|
-
}
|
|
263
|
-
return null;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Enables a disabled snap
|
|
268
|
-
* @param {string} snapName - The snap name
|
|
269
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
270
|
-
*/
|
|
271
|
-
async function enable(snapName) {
|
|
272
|
-
if (!isInstalled()) {
|
|
273
|
-
return {
|
|
274
|
-
success: false,
|
|
275
|
-
output: 'snap is not available'
|
|
276
|
-
};
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
const result = await shell.exec(`sudo snap enable ${snapName}`);
|
|
280
|
-
return {
|
|
281
|
-
success: result.code === 0,
|
|
282
|
-
output: result.stdout || result.stderr
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* Disables a snap without removing it
|
|
288
|
-
* @param {string} snapName - The snap name
|
|
289
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
290
|
-
*/
|
|
291
|
-
async function disable(snapName) {
|
|
292
|
-
if (!isInstalled()) {
|
|
293
|
-
return {
|
|
294
|
-
success: false,
|
|
295
|
-
output: 'snap is not available'
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
const result = await shell.exec(`sudo snap disable ${snapName}`);
|
|
300
|
-
return {
|
|
301
|
-
success: result.code === 0,
|
|
302
|
-
output: result.stdout || result.stderr
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Connects a snap interface
|
|
308
|
-
* @param {string} plug - The plug (e.g., 'snap-name:plug-name')
|
|
309
|
-
* @param {string} [slot] - The slot to connect to
|
|
310
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
311
|
-
*/
|
|
312
|
-
async function connect(plug, slot) {
|
|
313
|
-
if (!isInstalled()) {
|
|
314
|
-
return {
|
|
315
|
-
success: false,
|
|
316
|
-
output: 'snap is not available'
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
const command = slot
|
|
321
|
-
? `sudo snap connect ${plug} ${slot}`
|
|
322
|
-
: `sudo snap connect ${plug}`;
|
|
323
|
-
|
|
324
|
-
const result = await shell.exec(command);
|
|
325
|
-
return {
|
|
326
|
-
success: result.code === 0,
|
|
327
|
-
output: result.stdout || result.stderr
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
module.exports = {
|
|
332
|
-
isInstalled,
|
|
333
|
-
install,
|
|
334
|
-
remove,
|
|
335
|
-
isSnapInstalled,
|
|
336
|
-
getSnapVersion,
|
|
337
|
-
refresh,
|
|
338
|
-
list,
|
|
339
|
-
search,
|
|
340
|
-
info,
|
|
341
|
-
enable,
|
|
342
|
-
disable,
|
|
343
|
-
connect
|
|
344
|
-
};
|
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Systemd Service Management Utilities
|
|
5
|
-
*
|
|
6
|
-
* Linux-specific utilities for managing systemd services.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const shell = require('../common/shell');
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Checks if systemd is the init system
|
|
13
|
-
* @returns {boolean}
|
|
14
|
-
*/
|
|
15
|
-
function isSystemdAvailable() {
|
|
16
|
-
// Check if systemctl exists and systemd is running
|
|
17
|
-
if (!shell.commandExists('systemctl')) {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Verify systemd is actually running (not just installed)
|
|
22
|
-
const result = shell.execSync('systemctl is-system-running 2>/dev/null');
|
|
23
|
-
// Valid responses include: running, degraded, maintenance, initializing
|
|
24
|
-
return result !== '' && !result.includes('offline');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Checks if a systemd service is active (running)
|
|
29
|
-
* @param {string} service - The service name
|
|
30
|
-
* @returns {Promise<boolean>}
|
|
31
|
-
*/
|
|
32
|
-
async function isServiceRunning(service) {
|
|
33
|
-
if (!isSystemdAvailable()) {
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const result = await shell.exec(`systemctl is-active ${service}`);
|
|
38
|
-
return result.stdout.trim() === 'active';
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Checks if a service is enabled (starts on boot)
|
|
43
|
-
* @param {string} service - The service name
|
|
44
|
-
* @returns {Promise<boolean>}
|
|
45
|
-
*/
|
|
46
|
-
async function isServiceEnabled(service) {
|
|
47
|
-
if (!isSystemdAvailable()) {
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const result = await shell.exec(`systemctl is-enabled ${service}`);
|
|
52
|
-
return result.stdout.trim() === 'enabled';
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Starts a systemd service
|
|
57
|
-
* @param {string} service - The service name
|
|
58
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
59
|
-
*/
|
|
60
|
-
async function startService(service) {
|
|
61
|
-
if (!isSystemdAvailable()) {
|
|
62
|
-
return {
|
|
63
|
-
success: false,
|
|
64
|
-
output: 'systemd is not available'
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const result = await shell.exec(`sudo systemctl start ${service}`);
|
|
69
|
-
return {
|
|
70
|
-
success: result.code === 0,
|
|
71
|
-
output: result.stdout || result.stderr
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Stops a systemd service
|
|
77
|
-
* @param {string} service - The service name
|
|
78
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
79
|
-
*/
|
|
80
|
-
async function stopService(service) {
|
|
81
|
-
if (!isSystemdAvailable()) {
|
|
82
|
-
return {
|
|
83
|
-
success: false,
|
|
84
|
-
output: 'systemd is not available'
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const result = await shell.exec(`sudo systemctl stop ${service}`);
|
|
89
|
-
return {
|
|
90
|
-
success: result.code === 0,
|
|
91
|
-
output: result.stdout || result.stderr
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Restarts a systemd service
|
|
97
|
-
* @param {string} service - The service name
|
|
98
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
99
|
-
*/
|
|
100
|
-
async function restartService(service) {
|
|
101
|
-
if (!isSystemdAvailable()) {
|
|
102
|
-
return {
|
|
103
|
-
success: false,
|
|
104
|
-
output: 'systemd is not available'
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const result = await shell.exec(`sudo systemctl restart ${service}`);
|
|
109
|
-
return {
|
|
110
|
-
success: result.code === 0,
|
|
111
|
-
output: result.stdout || result.stderr
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Reloads a systemd service configuration
|
|
117
|
-
* @param {string} service - The service name
|
|
118
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
119
|
-
*/
|
|
120
|
-
async function reloadService(service) {
|
|
121
|
-
if (!isSystemdAvailable()) {
|
|
122
|
-
return {
|
|
123
|
-
success: false,
|
|
124
|
-
output: 'systemd is not available'
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const result = await shell.exec(`sudo systemctl reload ${service}`);
|
|
129
|
-
return {
|
|
130
|
-
success: result.code === 0,
|
|
131
|
-
output: result.stdout || result.stderr
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Enables a service to start on boot
|
|
137
|
-
* @param {string} service - The service name
|
|
138
|
-
* @param {Object} [options] - Options
|
|
139
|
-
* @param {boolean} [options.now=false] - Also start the service immediately
|
|
140
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
141
|
-
*/
|
|
142
|
-
async function enableService(service, options = {}) {
|
|
143
|
-
if (!isSystemdAvailable()) {
|
|
144
|
-
return {
|
|
145
|
-
success: false,
|
|
146
|
-
output: 'systemd is not available'
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
const nowFlag = options.now ? ' --now' : '';
|
|
151
|
-
const result = await shell.exec(`sudo systemctl enable${nowFlag} ${service}`);
|
|
152
|
-
return {
|
|
153
|
-
success: result.code === 0,
|
|
154
|
-
output: result.stdout || result.stderr
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Disables a service from starting on boot
|
|
160
|
-
* @param {string} service - The service name
|
|
161
|
-
* @param {Object} [options] - Options
|
|
162
|
-
* @param {boolean} [options.now=false] - Also stop the service immediately
|
|
163
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
164
|
-
*/
|
|
165
|
-
async function disableService(service, options = {}) {
|
|
166
|
-
if (!isSystemdAvailable()) {
|
|
167
|
-
return {
|
|
168
|
-
success: false,
|
|
169
|
-
output: 'systemd is not available'
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const nowFlag = options.now ? ' --now' : '';
|
|
174
|
-
const result = await shell.exec(`sudo systemctl disable${nowFlag} ${service}`);
|
|
175
|
-
return {
|
|
176
|
-
success: result.code === 0,
|
|
177
|
-
output: result.stdout || result.stderr
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Gets the status of a service
|
|
183
|
-
* @param {string} service - The service name
|
|
184
|
-
* @returns {Promise<string|null>}
|
|
185
|
-
*/
|
|
186
|
-
async function getServiceStatus(service) {
|
|
187
|
-
if (!isSystemdAvailable()) {
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const result = await shell.exec(`systemctl status ${service}`);
|
|
192
|
-
return result.stdout || result.stderr;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Lists all running services
|
|
197
|
-
* @returns {Promise<string[]>}
|
|
198
|
-
*/
|
|
199
|
-
async function listRunningServices() {
|
|
200
|
-
if (!isSystemdAvailable()) {
|
|
201
|
-
return [];
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const result = await shell.exec('systemctl list-units --type=service --state=running --no-pager --plain');
|
|
205
|
-
if (result.code !== 0) {
|
|
206
|
-
return [];
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return result.stdout
|
|
210
|
-
.split('\n')
|
|
211
|
-
.filter(Boolean)
|
|
212
|
-
.slice(0, -1) // Remove summary line
|
|
213
|
-
.map((line) => {
|
|
214
|
-
const parts = line.trim().split(/\s+/);
|
|
215
|
-
return parts[0] ? parts[0].replace('.service', '') : '';
|
|
216
|
-
})
|
|
217
|
-
.filter(Boolean);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Reloads the systemd daemon (after unit file changes)
|
|
222
|
-
* @returns {Promise<{ success: boolean, output: string }>}
|
|
223
|
-
*/
|
|
224
|
-
async function daemonReload() {
|
|
225
|
-
if (!isSystemdAvailable()) {
|
|
226
|
-
return {
|
|
227
|
-
success: false,
|
|
228
|
-
output: 'systemd is not available'
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const result = await shell.exec('sudo systemctl daemon-reload');
|
|
233
|
-
return {
|
|
234
|
-
success: result.code === 0,
|
|
235
|
-
output: result.stdout || result.stderr
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Checks if a service exists
|
|
241
|
-
* @param {string} service - The service name
|
|
242
|
-
* @returns {Promise<boolean>}
|
|
243
|
-
*/
|
|
244
|
-
async function serviceExists(service) {
|
|
245
|
-
if (!isSystemdAvailable()) {
|
|
246
|
-
return false;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
const result = await shell.exec(`systemctl cat ${service} 2>/dev/null`);
|
|
250
|
-
return result.code === 0;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Gets the logs for a service
|
|
255
|
-
* @param {string} service - The service name
|
|
256
|
-
* @param {Object} [options] - Options
|
|
257
|
-
* @param {number} [options.lines=50] - Number of lines to retrieve
|
|
258
|
-
* @param {boolean} [options.follow=false] - Follow the logs (not recommended for programmatic use)
|
|
259
|
-
* @returns {Promise<string|null>}
|
|
260
|
-
*/
|
|
261
|
-
async function getServiceLogs(service, options = {}) {
|
|
262
|
-
if (!shell.commandExists('journalctl')) {
|
|
263
|
-
return null;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const lines = options.lines || 50;
|
|
267
|
-
const result = await shell.exec(`journalctl -u ${service} -n ${lines} --no-pager`);
|
|
268
|
-
return result.code === 0 ? result.stdout : null;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
module.exports = {
|
|
272
|
-
isSystemdAvailable,
|
|
273
|
-
isServiceRunning,
|
|
274
|
-
isServiceEnabled,
|
|
275
|
-
startService,
|
|
276
|
-
stopService,
|
|
277
|
-
restartService,
|
|
278
|
-
reloadService,
|
|
279
|
-
enableService,
|
|
280
|
-
disableService,
|
|
281
|
-
getServiceStatus,
|
|
282
|
-
listRunningServices,
|
|
283
|
-
daemonReload,
|
|
284
|
-
serviceExists,
|
|
285
|
-
getServiceLogs
|
|
286
|
-
};
|