@xx-in/tools 0.0.2 → 0.0.4
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 +8 -6
- package/dist/cli.js +535 -863
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import process4 from "process";
|
|
|
7
7
|
// package.json
|
|
8
8
|
var package_default = {
|
|
9
9
|
name: "@xx-in/tools",
|
|
10
|
-
version: "0.0.
|
|
10
|
+
version: "0.0.4",
|
|
11
11
|
description: "A command-line tool to run in any system",
|
|
12
12
|
license: "MIT",
|
|
13
13
|
type: "module",
|
|
@@ -72,7 +72,7 @@ _xx() {
|
|
|
72
72
|
'create:\u9012\u5F52\u521B\u5EFA\u6587\u4EF6\u6216\u76EE\u5F55'
|
|
73
73
|
'format:\u4F7F\u7528 Prettier \u683C\u5F0F\u5316\u4EE3\u7801'
|
|
74
74
|
'help:\u663E\u793A\u6307\u5B9A\u547D\u4EE4\u7684\u5E2E\u52A9\u4FE1\u606F'
|
|
75
|
-
'install
|
|
75
|
+
'install:macOS/Windows \u672C\u5730\u5DE5\u5177\u5B89\u88C5\u5668 (\u652F\u6301\u53EF\u6267\u884C\u6587\u4EF6\u3001zip\u3001tar \u5305)'
|
|
76
76
|
'ip:\u672C\u5730\u6D3B\u8DC3\u7F51\u5361\u53CA\u7F51\u5173\u4FA6\u6D4B'
|
|
77
77
|
'list:\u5217\u51FA\u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u548C\u76EE\u5F55\uFF08\u542B\u9690\u85CF\u9879\uFF09'
|
|
78
78
|
'move:\u79FB\u52A8\u6216\u91CD\u547D\u540D\u6587\u4EF6\u53CA\u76EE\u5F55'
|
|
@@ -82,7 +82,7 @@ _xx() {
|
|
|
82
82
|
'remove:\u5B89\u5168\u5730\u5C06\u6307\u5B9A\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u79FB\u81F3\u7CFB\u7EDF\u56DE\u6536\u7AD9\uFF08\u652F\u6301\u901A\u914D\u7B26\u53CA\u591A\u9009\uFF09'
|
|
83
83
|
'search:\u9012\u5F52\u641C\u7D22\u76EE\u5F55\u4E0B\u5305\u542B\u6307\u5B9A\u5173\u952E\u8BCD\u7684\u6587\u4EF6\u6216\u76EE\u5F55'
|
|
84
84
|
'translate:\u7EC8\u7AEF\u7FFB\u8BD1\u5DE5\u5177'
|
|
85
|
-
'uninstall
|
|
85
|
+
'uninstall:macOS/Windows \u672C\u5730\u5DE5\u5177\u5378\u8F7D\u5668\uFF08\u79FB\u9664\u5B89\u88C5\u76EE\u5F55\u548C\u7EC8\u7AEF\u547D\u4EE4\u5165\u53E3\uFF09'
|
|
86
86
|
'unzip:\u89E3\u538B ZIP \u538B\u7F29\u5305'
|
|
87
87
|
'upgrade:\u81EA\u52A8\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177\u81F3\u6700\u65B0\u7248\u672C'
|
|
88
88
|
'zip:\u81EA\u52A8\u8FC7\u6EE4\u5E76\u6253\u5305\u4E3A ZIP'
|
|
@@ -111,7 +111,7 @@ _xx() {
|
|
|
111
111
|
'copy:\u590D\u5236\u6587\u4EF6\u6216\u76EE\u5F55\uFF08\u652F\u6301\u9012\u5F52\u590D\u5236\uFF09'
|
|
112
112
|
'create:\u9012\u5F52\u521B\u5EFA\u6587\u4EF6\u6216\u76EE\u5F55'
|
|
113
113
|
'format:\u4F7F\u7528 Prettier \u683C\u5F0F\u5316\u4EE3\u7801'
|
|
114
|
-
'install
|
|
114
|
+
'install:macOS/Windows \u672C\u5730\u5DE5\u5177\u5B89\u88C5\u5668 (\u652F\u6301\u53EF\u6267\u884C\u6587\u4EF6\u3001zip\u3001tar \u5305)'
|
|
115
115
|
'ip:\u672C\u5730\u6D3B\u8DC3\u7F51\u5361\u53CA\u7F51\u5173\u4FA6\u6D4B'
|
|
116
116
|
'list:\u5217\u51FA\u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u548C\u76EE\u5F55\uFF08\u542B\u9690\u85CF\u9879\uFF09'
|
|
117
117
|
'move:\u79FB\u52A8\u6216\u91CD\u547D\u540D\u6587\u4EF6\u53CA\u76EE\u5F55'
|
|
@@ -121,7 +121,7 @@ _xx() {
|
|
|
121
121
|
'remove:\u5B89\u5168\u5730\u5C06\u6307\u5B9A\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u79FB\u81F3\u7CFB\u7EDF\u56DE\u6536\u7AD9\uFF08\u652F\u6301\u901A\u914D\u7B26\u53CA\u591A\u9009\uFF09'
|
|
122
122
|
'search:\u9012\u5F52\u641C\u7D22\u76EE\u5F55\u4E0B\u5305\u542B\u6307\u5B9A\u5173\u952E\u8BCD\u7684\u6587\u4EF6\u6216\u76EE\u5F55'
|
|
123
123
|
'translate:\u7EC8\u7AEF\u7FFB\u8BD1\u5DE5\u5177'
|
|
124
|
-
'uninstall
|
|
124
|
+
'uninstall:macOS/Windows \u672C\u5730\u5DE5\u5177\u5378\u8F7D\u5668\uFF08\u79FB\u9664\u5B89\u88C5\u76EE\u5F55\u548C\u7EC8\u7AEF\u547D\u4EE4\u5165\u53E3\uFF09'
|
|
125
125
|
'unzip:\u89E3\u538B ZIP \u538B\u7F29\u5305'
|
|
126
126
|
'upgrade:\u81EA\u52A8\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177\u81F3\u6700\u65B0\u7248\u672C'
|
|
127
127
|
'zip:\u81EA\u52A8\u8FC7\u6EE4\u5E76\u6253\u5305\u4E3A ZIP'
|
|
@@ -547,12 +547,12 @@ function isCommandAvailable(cmd) {
|
|
|
547
547
|
}
|
|
548
548
|
function runCommand(cmd, args, options = {}) {
|
|
549
549
|
const stdio = options.stdio ?? "pipe";
|
|
550
|
-
return new Promise((
|
|
550
|
+
return new Promise((resolve13, reject) => {
|
|
551
551
|
const child = spawn(cmd, args, { stdio });
|
|
552
552
|
if (stdio === "inherit" || stdio === "ignore") {
|
|
553
553
|
child.on("error", reject);
|
|
554
554
|
child.on("close", (code) => {
|
|
555
|
-
|
|
555
|
+
resolve13({
|
|
556
556
|
success: code === 0,
|
|
557
557
|
code,
|
|
558
558
|
stdout: Buffer.alloc(0),
|
|
@@ -567,7 +567,7 @@ function runCommand(cmd, args, options = {}) {
|
|
|
567
567
|
child.stderr?.on("data", (chunk) => stderrChunks.push(chunk));
|
|
568
568
|
child.on("error", reject);
|
|
569
569
|
child.on("close", (code) => {
|
|
570
|
-
|
|
570
|
+
resolve13({
|
|
571
571
|
success: code === 0,
|
|
572
572
|
code,
|
|
573
573
|
stdout: Buffer.concat(stdoutChunks),
|
|
@@ -764,268 +764,396 @@ function registerFormatCommand(program2) {
|
|
|
764
764
|
}
|
|
765
765
|
|
|
766
766
|
// commands/install.ts
|
|
767
|
+
import fs6 from "fs/promises";
|
|
768
|
+
import pc6 from "picocolors";
|
|
769
|
+
import { resolve as resolve4, join as join5, basename as basename3 } from "path";
|
|
770
|
+
|
|
771
|
+
// utils/macos-apps.ts
|
|
767
772
|
import fs5 from "fs/promises";
|
|
773
|
+
import { basename as basename2, delimiter, extname, join as join4 } from "path";
|
|
768
774
|
import pc5 from "picocolors";
|
|
769
|
-
|
|
775
|
+
|
|
776
|
+
// utils/archive.ts
|
|
777
|
+
import AdmZip from "adm-zip";
|
|
778
|
+
import * as tar from "tar";
|
|
779
|
+
import { mkdir } from "fs/promises";
|
|
780
|
+
async function compressZip(sourceDir, outputPath) {
|
|
781
|
+
const zip = new AdmZip();
|
|
782
|
+
zip.addLocalFolder(sourceDir);
|
|
783
|
+
zip.writeZip(outputPath);
|
|
784
|
+
}
|
|
785
|
+
async function uncompressZip(src, destDir) {
|
|
786
|
+
await mkdir(destDir, { recursive: true });
|
|
787
|
+
const zip = new AdmZip(src);
|
|
788
|
+
zip.extractAllTo(destDir, true);
|
|
789
|
+
}
|
|
790
|
+
async function uncompressTar(src, destDir) {
|
|
791
|
+
await mkdir(destDir, { recursive: true });
|
|
792
|
+
await tar.x({ file: src, cwd: destDir });
|
|
793
|
+
}
|
|
794
|
+
async function uncompressTgz(src, destDir) {
|
|
795
|
+
await mkdir(destDir, { recursive: true });
|
|
796
|
+
await tar.x({ file: src, gzip: true, cwd: destDir });
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// utils/macos-apps.ts
|
|
800
|
+
var APP_DIR_NAME = ".xx-tools";
|
|
801
|
+
var PATH_MARKER_BEGIN = "# >>> xx-tools path >>>";
|
|
802
|
+
var PATH_MARKER_END = "# <<< xx-tools path <<<";
|
|
770
803
|
function getHomeDir() {
|
|
771
804
|
return process.env["HOME"] || process.env["USERPROFILE"] || process.cwd();
|
|
772
805
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
const applicationsDir = join4(home, ".local/share/applications");
|
|
776
|
-
let name = "";
|
|
777
|
-
let execLine = "";
|
|
778
|
-
let desktopFileName = "";
|
|
779
|
-
const isFlatpak = !targetPath.includes("/") && !targetPath.includes("\\") && targetPath.split(".").length >= 3;
|
|
780
|
-
if (isFlatpak) {
|
|
781
|
-
const segments = targetPath.split(".");
|
|
782
|
-
name = segments[segments.length - 1];
|
|
783
|
-
execLine = `flatpak run ${targetPath}`;
|
|
784
|
-
desktopFileName = `flatpak-${targetPath}.desktop`;
|
|
785
|
-
} else {
|
|
786
|
-
const absolutePath = resolve4(process.cwd(), targetPath);
|
|
787
|
-
try {
|
|
788
|
-
const stat = await fs5.stat(absolutePath);
|
|
789
|
-
if (!stat.isFile()) {
|
|
790
|
-
console.error(pc5.red(`\u274C \u9519\u8BEF: '${targetPath}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u6587\u4EF6\u3002`));
|
|
791
|
-
return;
|
|
792
|
-
}
|
|
793
|
-
} catch {
|
|
794
|
-
console.error(pc5.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u6587\u4EF6 '${targetPath}'\u3002`));
|
|
795
|
-
return;
|
|
796
|
-
}
|
|
797
|
-
const isAppImage = targetPath.toLowerCase().endsWith(".appimage");
|
|
798
|
-
name = basename2(absolutePath, isAppImage ? ".AppImage" : "");
|
|
799
|
-
try {
|
|
800
|
-
await fs5.chmod(absolutePath, 493);
|
|
801
|
-
} catch {
|
|
802
|
-
}
|
|
803
|
-
execLine = isAppImage ? `"${absolutePath}" --no-sandbox` : `"${absolutePath}"`;
|
|
804
|
-
desktopFileName = `${name.replace(/\s+/g, "-").toLowerCase()}.desktop`;
|
|
805
|
-
}
|
|
806
|
-
const desktopFilePath = join4(applicationsDir, desktopFileName);
|
|
807
|
-
const desktopContent = `[Desktop Entry]
|
|
808
|
-
Name=${name}
|
|
809
|
-
Exec=${execLine}
|
|
810
|
-
Type=Application
|
|
811
|
-
Terminal=false
|
|
812
|
-
Categories=Utility;
|
|
813
|
-
`;
|
|
814
|
-
try {
|
|
815
|
-
await fs5.mkdir(applicationsDir, { recursive: true });
|
|
816
|
-
await fs5.writeFile(desktopFilePath, desktopContent, "utf-8");
|
|
817
|
-
console.log(pc5.green(`\u2714 \u5FEB\u6377\u65B9\u5F0F\u5DF2\u521B\u5EFA: ${desktopFilePath}`));
|
|
818
|
-
console.log(pc5.dim(`\u542F\u52A8\u547D\u4EE4: ${execLine}`));
|
|
819
|
-
} catch (err) {
|
|
820
|
-
console.error(
|
|
821
|
-
pc5.red("\u274C \u521B\u5EFA\u5FEB\u6377\u65B9\u5F0F\u5931\u8D25:"),
|
|
822
|
-
err instanceof Error ? err.message : err
|
|
823
|
-
);
|
|
824
|
-
}
|
|
806
|
+
function getToolsRootDir() {
|
|
807
|
+
return join4(getHomeDir(), APP_DIR_NAME);
|
|
825
808
|
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
);
|
|
838
|
-
await fs5.copyFile(absPath, destPath);
|
|
839
|
-
await fs5.chmod(destPath, 493);
|
|
840
|
-
await createShortcut(destPath);
|
|
841
|
-
console.log(pc5.green(`\u2728 AppImage \u90E8\u7F72\u5B8C\u6210\uFF01`));
|
|
842
|
-
console.log(
|
|
843
|
-
pc5.green(
|
|
844
|
-
`
|
|
845
|
-
\u2728 \u5B89\u88C5\u6210\u529F\uFF01\u8BE5\u7EFF\u8272\u8F6F\u4EF6\u7684\u5378\u8F7D\u540D\u79F0\u4E3A: ${pc5.bold(appNameClean)}`
|
|
846
|
-
)
|
|
847
|
-
);
|
|
848
|
-
console.log(pc5.cyan(`\u{1F449} \u4EE5\u540E\u60A8\u53EF\u4EE5\u901A\u8FC7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5F7B\u5E95\u5378\u8F7D\u5B83\uFF1A`));
|
|
849
|
-
console.log(pc5.bold(pc5.yellow(` xx delete ${appNameClean}`)));
|
|
850
|
-
} catch (err) {
|
|
809
|
+
function getAppsDir() {
|
|
810
|
+
return join4(getToolsRootDir(), "apps");
|
|
811
|
+
}
|
|
812
|
+
function getBinDir() {
|
|
813
|
+
return join4(getToolsRootDir(), "bin");
|
|
814
|
+
}
|
|
815
|
+
function getManifestPath(appName) {
|
|
816
|
+
return join4(getAppsDir(), appName, ".xx-manifest.json");
|
|
817
|
+
}
|
|
818
|
+
function ensureSupportedDesktopOS() {
|
|
819
|
+
if (process.platform !== "darwin" && process.platform !== "win32") {
|
|
851
820
|
console.error(
|
|
852
|
-
pc5.red("\u274C
|
|
853
|
-
err instanceof Error ? err.message : err
|
|
821
|
+
pc5.red("\u274C \u5F53\u524D install/uninstall \u4EC5\u652F\u6301 macOS \u548C Windows\u3002")
|
|
854
822
|
);
|
|
823
|
+
return false;
|
|
855
824
|
}
|
|
825
|
+
return true;
|
|
856
826
|
}
|
|
857
|
-
async function
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
const packageName = decodeOutput(stdout).trim();
|
|
870
|
-
console.log(
|
|
871
|
-
pc5.green(
|
|
872
|
-
`
|
|
873
|
-
\u2728 \u5B89\u88C5\u6210\u529F\uFF01\u8BE5\u8F6F\u4EF6\u5305\u7684\u5B98\u65B9\u5378\u8F7D\u540D\u79F0\u4E3A: ${pc5.bold(packageName)}`
|
|
874
|
-
)
|
|
875
|
-
);
|
|
876
|
-
console.log(pc5.cyan(`\u{1F449} \u4EE5\u540E\u60A8\u53EF\u4EE5\u901A\u8FC7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5F7B\u5E95\u5378\u8F7D\u5B83\uFF1A`));
|
|
877
|
-
console.log(pc5.bold(pc5.yellow(` xx delete ${packageName}`)));
|
|
878
|
-
}
|
|
879
|
-
} catch {
|
|
880
|
-
}
|
|
827
|
+
async function ensureToolDirectories() {
|
|
828
|
+
await fs5.mkdir(getAppsDir(), { recursive: true });
|
|
829
|
+
await fs5.mkdir(getBinDir(), { recursive: true });
|
|
830
|
+
}
|
|
831
|
+
function getPreferredProfiles() {
|
|
832
|
+
const home = getHomeDir();
|
|
833
|
+
const shell = process.env["SHELL"] || "";
|
|
834
|
+
const profiles = [];
|
|
835
|
+
if (shell.includes("zsh")) {
|
|
836
|
+
profiles.push(join4(home, ".zshrc"), join4(home, ".zprofile"));
|
|
837
|
+
} else if (shell.includes("bash")) {
|
|
838
|
+
profiles.push(join4(home, ".bashrc"), join4(home, ".bash_profile"));
|
|
881
839
|
} else {
|
|
882
|
-
|
|
840
|
+
profiles.push(join4(home, ".zshrc"), join4(home, ".zprofile"));
|
|
883
841
|
}
|
|
842
|
+
return Array.from(new Set(profiles));
|
|
884
843
|
}
|
|
885
|
-
async function
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
844
|
+
async function ensureBinDirOnPath() {
|
|
845
|
+
if (process.platform === "win32") {
|
|
846
|
+
await ensureWindowsBinDirOnPath();
|
|
847
|
+
return;
|
|
848
|
+
}
|
|
849
|
+
const pathBlock = `${PATH_MARKER_BEGIN}
|
|
850
|
+
export PATH="$HOME/${APP_DIR_NAME}/bin:$PATH"
|
|
851
|
+
${PATH_MARKER_END}`;
|
|
852
|
+
for (const profilePath of getPreferredProfiles()) {
|
|
853
|
+
let content = "";
|
|
890
854
|
try {
|
|
891
|
-
|
|
892
|
-
"-qp",
|
|
893
|
-
"--queryformat",
|
|
894
|
-
"%{NAME}",
|
|
895
|
-
absPath
|
|
896
|
-
]);
|
|
897
|
-
if (success) {
|
|
898
|
-
const packageName = decodeOutput(stdout).trim();
|
|
899
|
-
console.log(
|
|
900
|
-
pc5.green(
|
|
901
|
-
`
|
|
902
|
-
\u2728 \u5B89\u88C5\u6210\u529F\uFF01\u8BE5\u8F6F\u4EF6\u5305\u7684\u5B98\u65B9\u5378\u8F7D\u540D\u79F0\u4E3A: ${pc5.bold(packageName)}`
|
|
903
|
-
)
|
|
904
|
-
);
|
|
905
|
-
console.log(pc5.cyan(`\u{1F449} \u4EE5\u540E\u60A8\u53EF\u4EE5\u901A\u8FC7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5F7B\u5E95\u5378\u8F7D\u5B83\uFF1A`));
|
|
906
|
-
console.log(pc5.bold(pc5.yellow(` xx delete ${packageName}`)));
|
|
907
|
-
}
|
|
855
|
+
content = await fs5.readFile(profilePath, "utf-8");
|
|
908
856
|
} catch {
|
|
909
857
|
}
|
|
910
|
-
|
|
911
|
-
|
|
858
|
+
if (!content.includes(PATH_MARKER_BEGIN)) {
|
|
859
|
+
const separator = content.endsWith("\n") || content === "" ? "" : "\n";
|
|
860
|
+
await fs5.writeFile(
|
|
861
|
+
profilePath,
|
|
862
|
+
`${content}${separator}${pathBlock}
|
|
863
|
+
`,
|
|
864
|
+
"utf-8"
|
|
865
|
+
);
|
|
866
|
+
console.log(pc5.green(`\u2714 \u5DF2\u5199\u5165 PATH \u914D\u7F6E: ${profilePath}`));
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
async function ensureWindowsBinDirOnPath() {
|
|
871
|
+
const binDir = getBinDir();
|
|
872
|
+
const currentUserPath = process.env["Path"] || process.env["PATH"] || "";
|
|
873
|
+
const alreadyInCurrentEnv = currentUserPath.split(delimiter).some((item) => item.trim().toLowerCase() === binDir.toLowerCase());
|
|
874
|
+
const script = [
|
|
875
|
+
"$binDir = [System.IO.Path]::GetFullPath($args[0])",
|
|
876
|
+
"$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')",
|
|
877
|
+
"if ([string]::IsNullOrWhiteSpace($userPath)) { $userPath = '' }",
|
|
878
|
+
"$items = $userPath -split ';' | Where-Object { $_ -and $_.Trim() -ne '' }",
|
|
879
|
+
"$exists = $items | Where-Object { $_.Trim().ToLower() -eq $binDir.ToLower() }",
|
|
880
|
+
"if (-not $exists) {",
|
|
881
|
+
' $newPath = if ($userPath) { "$binDir;$userPath" } else { $binDir }',
|
|
882
|
+
" [Environment]::SetEnvironmentVariable('Path', $newPath, 'User')",
|
|
883
|
+
" Write-Output 'UPDATED'",
|
|
884
|
+
"} else {",
|
|
885
|
+
" Write-Output 'UNCHANGED'",
|
|
886
|
+
"}"
|
|
887
|
+
].join(" ");
|
|
888
|
+
const { success, stdout } = await runCommand("powershell", [
|
|
889
|
+
"-NoProfile",
|
|
890
|
+
"-Command",
|
|
891
|
+
script,
|
|
892
|
+
binDir
|
|
893
|
+
]);
|
|
894
|
+
if (success) {
|
|
895
|
+
const output = decodeOutput(stdout).trim();
|
|
896
|
+
if (output.includes("UPDATED")) {
|
|
897
|
+
console.log(pc5.green(`\u2714 \u5DF2\u5199\u5165\u7528\u6237 PATH: ${binDir}`));
|
|
898
|
+
} else if (!alreadyInCurrentEnv) {
|
|
899
|
+
console.log(pc5.dim(`\u2796 \u7528\u6237 PATH \u4E2D\u5DF2\u5B58\u5728: ${binDir}`));
|
|
900
|
+
}
|
|
912
901
|
}
|
|
913
902
|
}
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
console.error(pc5.red("\u274C \u9519\u8BEF: \u65E0\u6CD5\u83B7\u53D6\u7528\u6237\u6839\u76EE\u5F55\u3002"));
|
|
918
|
-
return;
|
|
903
|
+
function getShellReloadCommand() {
|
|
904
|
+
if (process.platform === "win32") {
|
|
905
|
+
return "\u91CD\u65B0\u6253\u5F00 PowerShell \u6216 CMD";
|
|
919
906
|
}
|
|
920
|
-
const
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
907
|
+
const shell = process.env["SHELL"] || "";
|
|
908
|
+
if (shell.includes("zsh")) {
|
|
909
|
+
return "source ~/.zshrc";
|
|
910
|
+
}
|
|
911
|
+
if (shell.includes("bash")) {
|
|
912
|
+
return "source ~/.bashrc";
|
|
913
|
+
}
|
|
914
|
+
return "source ~/.zshrc";
|
|
915
|
+
}
|
|
916
|
+
function stripArchiveSuffix(filePath) {
|
|
917
|
+
const lower = filePath.toLowerCase();
|
|
918
|
+
const name = basename2(filePath);
|
|
919
|
+
const suffixes = [".tar.gz", ".tgz", ".tar.xz", ".txz", ".zip", ".tar"];
|
|
920
|
+
for (const suffix of suffixes) {
|
|
921
|
+
if (lower.endsWith(suffix)) {
|
|
922
|
+
return name.slice(0, name.length - suffix.length);
|
|
935
923
|
}
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
924
|
+
}
|
|
925
|
+
return basename2(filePath, extname(filePath));
|
|
926
|
+
}
|
|
927
|
+
async function removeDirectoryContents(dirPath) {
|
|
928
|
+
await fs5.rm(dirPath, { recursive: true, force: true });
|
|
929
|
+
await fs5.mkdir(dirPath, { recursive: true });
|
|
930
|
+
}
|
|
931
|
+
async function findExecutablesRecursively(rootDir) {
|
|
932
|
+
const matches = [];
|
|
933
|
+
async function walk(currentDir) {
|
|
934
|
+
for (const entry of await fs5.readdir(currentDir, { withFileTypes: true })) {
|
|
935
|
+
if (entry.name.startsWith(".")) continue;
|
|
936
|
+
const fullPath = join4(currentDir, entry.name);
|
|
937
|
+
if (entry.isDirectory()) {
|
|
938
|
+
if (["node_modules", "lib", "libs", "include", "share", "man"].includes(
|
|
939
|
+
entry.name
|
|
940
|
+
)) {
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
await walk(fullPath);
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
if (!entry.isFile()) continue;
|
|
947
|
+
const stat = await fs5.stat(fullPath);
|
|
948
|
+
if (process.platform === "win32") {
|
|
949
|
+
if (!/\.(exe|cmd|bat|ps1)$/i.test(entry.name)) {
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
} else {
|
|
944
953
|
const isExecutable = stat.mode ? (stat.mode & 73) !== 0 : false;
|
|
945
|
-
if (isExecutable
|
|
946
|
-
|
|
947
|
-
|
|
954
|
+
if (!isExecutable) continue;
|
|
955
|
+
if (/\.(dylib|so|a|o|txt|md|json|yaml|yml|ts|js|c|h|sh)$/i.test(
|
|
956
|
+
entry.name
|
|
957
|
+
)) {
|
|
958
|
+
continue;
|
|
948
959
|
}
|
|
949
960
|
}
|
|
961
|
+
matches.push(fullPath);
|
|
950
962
|
}
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
963
|
+
}
|
|
964
|
+
await walk(rootDir);
|
|
965
|
+
return matches;
|
|
966
|
+
}
|
|
967
|
+
async function createLinks(appName, executablePaths) {
|
|
968
|
+
const binDir = getBinDir();
|
|
969
|
+
const linkNames = [];
|
|
970
|
+
for (const executablePath of executablePaths) {
|
|
971
|
+
const executableBaseName = basename2(executablePath);
|
|
972
|
+
if (process.platform === "win32") {
|
|
973
|
+
const commandName = basename2(
|
|
974
|
+
executableBaseName,
|
|
975
|
+
extname(executableBaseName)
|
|
959
976
|
);
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
977
|
+
const cmdPath = join4(binDir, `${commandName}.cmd`);
|
|
978
|
+
const ps1Path = join4(binDir, `${commandName}.ps1`);
|
|
979
|
+
const quotedExecutable = executablePath.replace(/"/g, '""');
|
|
980
|
+
await fs5.rm(cmdPath, { force: true });
|
|
981
|
+
await fs5.rm(ps1Path, { force: true });
|
|
982
|
+
await fs5.writeFile(
|
|
983
|
+
cmdPath,
|
|
984
|
+
`@echo off\r
|
|
985
|
+
"${quotedExecutable}" %*\r
|
|
986
|
+
`,
|
|
987
|
+
"utf-8"
|
|
967
988
|
);
|
|
989
|
+
await fs5.writeFile(ps1Path, `& "${quotedExecutable}" @args
|
|
990
|
+
`, "utf-8");
|
|
991
|
+
linkNames.push(commandName);
|
|
992
|
+
} else {
|
|
993
|
+
const linkName = executableBaseName;
|
|
994
|
+
const linkPath = join4(binDir, linkName);
|
|
995
|
+
await fs5.rm(linkPath, { force: true });
|
|
996
|
+
await fs5.symlink(executablePath, linkPath);
|
|
997
|
+
linkNames.push(linkName);
|
|
968
998
|
}
|
|
969
|
-
}
|
|
999
|
+
}
|
|
1000
|
+
if (linkNames.length > 0) {
|
|
1001
|
+
console.log(
|
|
1002
|
+
pc5.green(
|
|
1003
|
+
`\u2714 \u5DF2\u4E3A ${pc5.bold(appName)} \u521B\u5EFA\u7EC8\u7AEF\u547D\u4EE4: ${linkNames.join(", ")}`
|
|
1004
|
+
)
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
1007
|
+
return linkNames;
|
|
1008
|
+
}
|
|
1009
|
+
async function writeManifest(manifest) {
|
|
1010
|
+
await fs5.writeFile(
|
|
1011
|
+
getManifestPath(manifest.appName),
|
|
1012
|
+
JSON.stringify(manifest, null, 2),
|
|
1013
|
+
"utf-8"
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
async function readManifest(appName) {
|
|
1017
|
+
try {
|
|
1018
|
+
const content = await fs5.readFile(getManifestPath(appName), "utf-8");
|
|
1019
|
+
return JSON.parse(content);
|
|
1020
|
+
} catch {
|
|
1021
|
+
return null;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
async function removeInstalledApp(appName) {
|
|
1025
|
+
const manifest = await readManifest(appName);
|
|
1026
|
+
if (!manifest) return false;
|
|
1027
|
+
for (const linkName of manifest.links) {
|
|
1028
|
+
if (process.platform === "win32") {
|
|
1029
|
+
await fs5.rm(join4(getBinDir(), `${linkName}.cmd`), { force: true });
|
|
1030
|
+
await fs5.rm(join4(getBinDir(), `${linkName}.ps1`), { force: true });
|
|
1031
|
+
} else {
|
|
1032
|
+
await fs5.rm(join4(getBinDir(), linkName), { force: true });
|
|
1033
|
+
}
|
|
1034
|
+
console.log(pc5.green(`\u2714 \u5DF2\u79FB\u9664\u7EC8\u7AEF\u547D\u4EE4: ${linkName}`));
|
|
1035
|
+
}
|
|
1036
|
+
await fs5.rm(manifest.installDir, { recursive: true, force: true });
|
|
1037
|
+
console.log(pc5.green(`\u2714 \u5DF2\u79FB\u9664\u5B89\u88C5\u76EE\u5F55: ${manifest.installDir}`));
|
|
1038
|
+
return true;
|
|
1039
|
+
}
|
|
1040
|
+
async function listInstalledApps() {
|
|
1041
|
+
try {
|
|
1042
|
+
const entries = await fs5.readdir(getAppsDir(), { withFileTypes: true });
|
|
1043
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
1044
|
+
} catch {
|
|
1045
|
+
return [];
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
async function extractArchiveToDir(archivePath, destDir) {
|
|
1049
|
+
const lower = archivePath.toLowerCase();
|
|
1050
|
+
if (lower.endsWith(".zip")) {
|
|
1051
|
+
await uncompressZip(archivePath, destDir);
|
|
1052
|
+
return true;
|
|
1053
|
+
}
|
|
1054
|
+
let args;
|
|
1055
|
+
if (lower.endsWith(".tar.gz") || lower.endsWith(".tgz")) {
|
|
1056
|
+
args = ["-xzf", archivePath, "-C", destDir];
|
|
1057
|
+
} else if (lower.endsWith(".tar.xz") || lower.endsWith(".txz")) {
|
|
1058
|
+
args = ["-xJf", archivePath, "-C", destDir];
|
|
1059
|
+
} else if (lower.endsWith(".tar")) {
|
|
1060
|
+
args = ["-xf", archivePath, "-C", destDir];
|
|
1061
|
+
} else {
|
|
1062
|
+
return false;
|
|
1063
|
+
}
|
|
1064
|
+
const result = await spawnCommand("tar", args);
|
|
1065
|
+
return result.success;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
// commands/install.ts
|
|
1069
|
+
function printReloadHint() {
|
|
1070
|
+
const reloadCommand = getShellReloadCommand();
|
|
1071
|
+
console.log(
|
|
1072
|
+
pc6.yellow(`\u{1F4A1} \u5982\u679C\u5F53\u524D\u7EC8\u7AEF\u8FD8\u4E0D\u80FD\u76F4\u63A5\u8FD0\u884C\u65B0\u547D\u4EE4\uFF0C\u8BF7\u6267\u884C: ${reloadCommand}`)
|
|
1073
|
+
);
|
|
1074
|
+
}
|
|
1075
|
+
async function installBinary(absPath) {
|
|
1076
|
+
const appName = basename3(absPath);
|
|
1077
|
+
const installDir = join5(getAppsDir(), appName);
|
|
1078
|
+
const targetDir = join5(installDir, "bin");
|
|
1079
|
+
const targetPath = join5(targetDir, appName);
|
|
1080
|
+
await fs6.mkdir(targetDir, { recursive: true });
|
|
1081
|
+
await fs6.copyFile(absPath, targetPath);
|
|
1082
|
+
await fs6.chmod(targetPath, 493);
|
|
1083
|
+
const links = await createLinks(appName, [targetPath]);
|
|
1084
|
+
await writeManifest({
|
|
1085
|
+
appName,
|
|
1086
|
+
installDir,
|
|
1087
|
+
links,
|
|
1088
|
+
type: "binary"
|
|
1089
|
+
});
|
|
1090
|
+
console.log(pc6.green(`\u2728 \u5B89\u88C5\u6210\u529F\uFF01\u53EF\u76F4\u63A5\u5728\u7EC8\u7AEF\u4E2D\u8FD0\u884C: ${pc6.bold(appName)}`));
|
|
1091
|
+
console.log(pc6.cyan(`\u{1F449} \u5378\u8F7D\u547D\u4EE4: ${pc6.bold(`xx uninstall ${appName}`)}`));
|
|
1092
|
+
printReloadHint();
|
|
1093
|
+
}
|
|
1094
|
+
async function installArchive(absPath) {
|
|
1095
|
+
const appName = stripArchiveSuffix(absPath);
|
|
1096
|
+
const installDir = join5(getAppsDir(), appName);
|
|
1097
|
+
await removeDirectoryContents(installDir);
|
|
1098
|
+
console.log(pc6.cyan(`\u{1F4E6} \u6B63\u5728\u89E3\u538B\u8F6F\u4EF6\u5305\u81F3: ${installDir}...`));
|
|
1099
|
+
const extracted = await extractArchiveToDir(absPath, installDir);
|
|
1100
|
+
if (!extracted) {
|
|
970
1101
|
console.error(
|
|
971
|
-
|
|
972
|
-
err instanceof Error ? err.message : err
|
|
1102
|
+
pc6.red("\u274C \u5F53\u524D\u4EC5\u652F\u6301 .tar.gz\u3001.tgz\u3001.tar.xz\u3001.txz\u3001.tar \u683C\u5F0F\u3002")
|
|
973
1103
|
);
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
const executables = await findExecutablesRecursively(installDir);
|
|
1107
|
+
if (executables.length === 0) {
|
|
1108
|
+
console.error(pc6.red("\u274C \u89E3\u538B\u5B8C\u6210\uFF0C\u4F46\u672A\u627E\u5230\u53EF\u6267\u884C\u6587\u4EF6\u3002"));
|
|
1109
|
+
return;
|
|
974
1110
|
}
|
|
1111
|
+
const links = await createLinks(appName, executables);
|
|
1112
|
+
await writeManifest({
|
|
1113
|
+
appName,
|
|
1114
|
+
installDir,
|
|
1115
|
+
links,
|
|
1116
|
+
type: "archive"
|
|
1117
|
+
});
|
|
1118
|
+
console.log(
|
|
1119
|
+
pc6.green(`\u2728 \u5B89\u88C5\u6210\u529F\uFF01\u53EF\u76F4\u63A5\u5728\u7EC8\u7AEF\u4E2D\u8FD0\u884C: ${pc6.bold(links.join(", "))}`)
|
|
1120
|
+
);
|
|
1121
|
+
console.log(pc6.cyan(`\u{1F449} \u5378\u8F7D\u547D\u4EE4: ${pc6.bold(`xx uninstall ${appName}`)}`));
|
|
1122
|
+
printReloadHint();
|
|
975
1123
|
}
|
|
976
1124
|
function registerInstallCommand(program2) {
|
|
977
1125
|
program2.command("install [path]").description(
|
|
978
|
-
"\
|
|
1126
|
+
"macOS/Windows \u672C\u5730\u5DE5\u5177\u5B89\u88C5\u5668\uFF08\u652F\u6301\u53EF\u6267\u884C\u6587\u4EF6\u3001.zip\u3001.tar.gz\u3001.tgz\u3001.tar.xz\u3001.txz\u3001.tar\uFF09"
|
|
979
1127
|
).action(async (target) => {
|
|
1128
|
+
if (!ensureSupportedDesktopOS()) return;
|
|
980
1129
|
if (!target) {
|
|
981
|
-
console.error(
|
|
982
|
-
return;
|
|
983
|
-
}
|
|
984
|
-
const isFlatpak = !target.includes("/") && !target.includes("\\") && target.split(".").length >= 3;
|
|
985
|
-
if (isFlatpak) {
|
|
986
|
-
await createShortcut(target);
|
|
987
|
-
console.log(
|
|
988
|
-
pc5.green(
|
|
989
|
-
`
|
|
990
|
-
\u2728 \u5B89\u88C5\u6210\u529F\uFF01\u8BE5 Flatpak \u5FEB\u6377\u56FE\u6807\u7684\u5378\u8F7D\u540D\u79F0\u4E3A: ${pc5.bold(target)}`
|
|
991
|
-
)
|
|
992
|
-
);
|
|
993
|
-
console.log(pc5.cyan(`\u{1F449} \u4EE5\u540E\u60A8\u53EF\u4EE5\u901A\u8FC7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u5220\u9664\u8BE5\u5FEB\u6377\u56FE\u6807\uFF1A`));
|
|
994
|
-
console.log(pc5.bold(pc5.yellow(` xx delete ${target}`)));
|
|
1130
|
+
console.error(pc6.red("\u274C \u8BF7\u63D0\u4F9B\u6709\u6548\u7684\u672C\u5730\u6587\u4EF6\u8DEF\u5F84\u3002"));
|
|
995
1131
|
return;
|
|
996
1132
|
}
|
|
997
1133
|
const absPath = resolve4(process.cwd(), target);
|
|
998
1134
|
try {
|
|
999
|
-
await
|
|
1135
|
+
const stat = await fs6.stat(absPath);
|
|
1136
|
+
if (!stat.isFile()) {
|
|
1137
|
+
console.error(pc6.red(`\u274C \u9519\u8BEF: '${target}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u6587\u4EF6\u3002`));
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1000
1140
|
} catch {
|
|
1001
|
-
console.error(
|
|
1141
|
+
console.error(pc6.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u6307\u5B9A\u6587\u4EF6\u6216\u5305\u8DEF\u5F84 '${target}'\u3002`));
|
|
1002
1142
|
return;
|
|
1003
1143
|
}
|
|
1144
|
+
await ensureToolDirectories();
|
|
1145
|
+
await ensureBinDirOnPath();
|
|
1004
1146
|
const lowerPath = target.toLowerCase();
|
|
1005
|
-
if (lowerPath.endsWith(".
|
|
1006
|
-
await
|
|
1007
|
-
} else if (lowerPath.endsWith(".deb")) {
|
|
1008
|
-
await installDeb(absPath);
|
|
1009
|
-
} else if (lowerPath.endsWith(".rpm")) {
|
|
1010
|
-
await installRpm(absPath);
|
|
1011
|
-
} else if (lowerPath.endsWith(".tar.gz") || lowerPath.endsWith(".tgz")) {
|
|
1012
|
-
await installTarGz(absPath);
|
|
1147
|
+
if (lowerPath.endsWith(".zip") || lowerPath.endsWith(".tar.gz") || lowerPath.endsWith(".tgz") || lowerPath.endsWith(".tar.xz") || lowerPath.endsWith(".txz") || lowerPath.endsWith(".tar")) {
|
|
1148
|
+
await installArchive(absPath);
|
|
1013
1149
|
} else {
|
|
1014
|
-
|
|
1015
|
-
pc5.cyan(`\u{1F4E6} \u68C0\u6D4B\u5230\u901A\u7528\u672C\u5730\u53EF\u6267\u884C\u6587\u4EF6\uFF0C\u6B63\u5728\u76F4\u63A5\u4E3A\u5176\u914D\u7F6E\u684C\u9762\u56FE\u6807...`)
|
|
1016
|
-
);
|
|
1017
|
-
await createShortcut(absPath);
|
|
1018
|
-
const execName = basename2(absPath);
|
|
1019
|
-
console.log(
|
|
1020
|
-
pc5.green(`
|
|
1021
|
-
\u2728 \u5FEB\u6377\u65B9\u5F0F\u521B\u5EFA\u6210\u529F\uFF01\u540D\u79F0\u4E3A: ${pc5.bold(execName)}`)
|
|
1022
|
-
);
|
|
1150
|
+
await installBinary(absPath);
|
|
1023
1151
|
}
|
|
1024
1152
|
});
|
|
1025
1153
|
}
|
|
1026
1154
|
|
|
1027
1155
|
// commands/ip.ts
|
|
1028
|
-
import
|
|
1156
|
+
import pc7 from "picocolors";
|
|
1029
1157
|
import os from "os";
|
|
1030
1158
|
function getInterfaceType(name) {
|
|
1031
1159
|
const lowerName = name.toLowerCase();
|
|
@@ -1199,7 +1327,7 @@ async function getDefaultRouteInfo() {
|
|
|
1199
1327
|
}
|
|
1200
1328
|
function registerIpCommand(program2) {
|
|
1201
1329
|
program2.command("ip").description("\u672C\u5730\u6D3B\u8DC3\u7F51\u5361\u3001\u672C\u673AIP\u53CA\u7F51\u5173\u4FA6\u6D4B\u5DE5\u5177").action(async () => {
|
|
1202
|
-
console.log(
|
|
1330
|
+
console.log(pc7.dim("\u6B63\u5728\u5206\u6790\u7F51\u7EDC\u914D\u7F6E\uFF0C\u8BF7\u7A0D\u5019...\n"));
|
|
1203
1331
|
try {
|
|
1204
1332
|
let defaultRoute = { gateway: "", interfaceName: "" };
|
|
1205
1333
|
let routeError = "";
|
|
@@ -1210,7 +1338,7 @@ function registerIpCommand(program2) {
|
|
|
1210
1338
|
}
|
|
1211
1339
|
const cards = getActiveNetworkCards();
|
|
1212
1340
|
if (cards.length === 0) {
|
|
1213
|
-
console.log(
|
|
1341
|
+
console.log(pc7.red("\u274C \u672A\u68C0\u6D4B\u5230\u4EFB\u4F55\u6D3B\u8DC3\u7684\u975E\u672C\u5730\u56DE\u73AF\u7F51\u5361\u3002"));
|
|
1214
1342
|
return;
|
|
1215
1343
|
}
|
|
1216
1344
|
cards.sort((a, b) => {
|
|
@@ -1247,76 +1375,76 @@ function registerIpCommand(program2) {
|
|
|
1247
1375
|
ipv4.netmask
|
|
1248
1376
|
);
|
|
1249
1377
|
}
|
|
1250
|
-
let cardGateway =
|
|
1378
|
+
let cardGateway = pc7.dim("(\u975E\u9ED8\u8BA4\u8DEF\u7531\u51FA\u53E3\u7F51\u5361)");
|
|
1251
1379
|
if (isDefaultRouteCard) {
|
|
1252
1380
|
if (defaultRoute.gateway && defaultRoute.gateway !== "0.0.0.0") {
|
|
1253
|
-
cardGateway =
|
|
1381
|
+
cardGateway = pc7.yellow(defaultRoute.gateway);
|
|
1254
1382
|
} else {
|
|
1255
|
-
cardGateway =
|
|
1383
|
+
cardGateway = pc7.yellow("\u76F4\u63A5\u70B9\u5BF9\u70B9\u96A7\u9053\u8FDE\u63A5 (Point-to-Point)");
|
|
1256
1384
|
}
|
|
1257
1385
|
} else if (routeError) {
|
|
1258
|
-
cardGateway =
|
|
1386
|
+
cardGateway = pc7.dim(`\u68C0\u6D4B\u5931\u8D25 (\u539F\u56E0: ${routeError})`);
|
|
1259
1387
|
}
|
|
1260
1388
|
console.log(
|
|
1261
|
-
|
|
1389
|
+
pc7.cyan(
|
|
1262
1390
|
`================ \u6D3B\u8DC3\u7F51\u5361\u53CA\u7F51\u5173\u4FE1\u606F [${card.type}] ================`
|
|
1263
1391
|
)
|
|
1264
1392
|
);
|
|
1265
1393
|
console.log(
|
|
1266
|
-
`${
|
|
1394
|
+
`${pc7.green("\u7F51\u5361\u540D\u79F0 (Name):")} ${pc7.bold(card.name)}`
|
|
1267
1395
|
);
|
|
1268
1396
|
console.log(
|
|
1269
|
-
`${
|
|
1397
|
+
`${pc7.green("\u672C\u673A IP \u5730\u5740 (IP):")} ${pc7.bold(primaryAddr.address)}`
|
|
1270
1398
|
);
|
|
1271
1399
|
console.log(
|
|
1272
|
-
`${
|
|
1400
|
+
`${pc7.green("\u5B50\u7F51\u63A9\u7801 (Mask):")} ${primaryAddr.netmask}`
|
|
1273
1401
|
);
|
|
1274
|
-
console.log(`${
|
|
1275
|
-
console.log(`${
|
|
1402
|
+
console.log(`${pc7.green("\u9ED8\u8BA4\u7F51\u5173 (Gateway):")} ${cardGateway}`);
|
|
1403
|
+
console.log(`${pc7.green("MAC \u5730\u5740 (MAC):")} ${card.mac}`);
|
|
1276
1404
|
console.log(
|
|
1277
|
-
`${
|
|
1405
|
+
`${pc7.green("IP \u534F\u8BAE\u7248\u672C:")} ${primaryAddr.family === "IPv4" || primaryAddr.family === "4" ? "IPv4" : "IPv6"}`
|
|
1278
1406
|
);
|
|
1279
1407
|
if (ipv4 && ipv6) {
|
|
1280
1408
|
console.log(
|
|
1281
|
-
`${
|
|
1409
|
+
`${pc7.green("\u672C\u5730 IPv6 \u5730\u5740:")} ${pc7.dim(ipv6.address)}`
|
|
1282
1410
|
);
|
|
1283
1411
|
}
|
|
1284
1412
|
console.log(
|
|
1285
|
-
|
|
1413
|
+
pc7.cyan("====================================================")
|
|
1286
1414
|
);
|
|
1287
1415
|
console.log("");
|
|
1288
1416
|
}
|
|
1289
1417
|
} catch (error) {
|
|
1290
|
-
console.error(
|
|
1418
|
+
console.error(pc7.red("\u274C \u68C0\u6D4B\u5931\u8D25\u3002"));
|
|
1291
1419
|
if (error instanceof Error) {
|
|
1292
|
-
console.error(
|
|
1420
|
+
console.error(pc7.red("\u9519\u8BEF\u8BE6\u60C5:"), error.message);
|
|
1293
1421
|
}
|
|
1294
1422
|
}
|
|
1295
1423
|
});
|
|
1296
1424
|
}
|
|
1297
1425
|
|
|
1298
1426
|
// commands/list.ts
|
|
1299
|
-
import
|
|
1300
|
-
import
|
|
1427
|
+
import fs7 from "fs/promises";
|
|
1428
|
+
import pc8 from "picocolors";
|
|
1301
1429
|
import { resolve as resolve5 } from "path";
|
|
1302
1430
|
function registerLsCommand(program2) {
|
|
1303
1431
|
program2.command("list [path]").description("\u5217\u51FA\u76EE\u5F55\u4E2D\u7684\u6240\u6709\u6587\u4EF6\u548C\u76EE\u5F55\uFF08\u542B\u9690\u85CF\u9879\uFF09").action(async (targetPath) => {
|
|
1304
1432
|
const inputPath = targetPath || ".";
|
|
1305
1433
|
const absolutePath = resolve5(process.cwd(), inputPath);
|
|
1306
1434
|
try {
|
|
1307
|
-
const stat = await
|
|
1435
|
+
const stat = await fs7.stat(absolutePath);
|
|
1308
1436
|
if (!stat.isDirectory()) {
|
|
1309
|
-
console.error(
|
|
1437
|
+
console.error(pc8.red(`\u274C \u9519\u8BEF: '${inputPath}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
|
|
1310
1438
|
return;
|
|
1311
1439
|
}
|
|
1312
1440
|
const entries = [];
|
|
1313
|
-
for (const entry of await
|
|
1441
|
+
for (const entry of await fs7.readdir(absolutePath, {
|
|
1314
1442
|
withFileTypes: true
|
|
1315
1443
|
})) {
|
|
1316
1444
|
entries.push(entry);
|
|
1317
1445
|
}
|
|
1318
1446
|
if (entries.length === 0) {
|
|
1319
|
-
console.log(
|
|
1447
|
+
console.log(pc8.dim("\uFF08\u7A7A\u76EE\u5F55\uFF09"));
|
|
1320
1448
|
return;
|
|
1321
1449
|
}
|
|
1322
1450
|
entries.sort((a, b) => {
|
|
@@ -1328,13 +1456,13 @@ function registerLsCommand(program2) {
|
|
|
1328
1456
|
const isHidden = entry.name.startsWith(".");
|
|
1329
1457
|
if (entry.isDirectory()) {
|
|
1330
1458
|
if (isHidden) {
|
|
1331
|
-
console.log(
|
|
1459
|
+
console.log(pc8.dim(`\u{1F4C1} ${pc8.blue(entry.name)}/`));
|
|
1332
1460
|
} else {
|
|
1333
|
-
console.log(`\u{1F4C1} ${
|
|
1461
|
+
console.log(`\u{1F4C1} ${pc8.blue(pc8.bold(entry.name))}/`);
|
|
1334
1462
|
}
|
|
1335
1463
|
} else {
|
|
1336
1464
|
if (isHidden) {
|
|
1337
|
-
console.log(
|
|
1465
|
+
console.log(pc8.dim(`\u{1F4C4} ${entry.name}`));
|
|
1338
1466
|
} else {
|
|
1339
1467
|
console.log(`\u{1F4C4} ${entry.name}`);
|
|
1340
1468
|
}
|
|
@@ -1342,7 +1470,7 @@ function registerLsCommand(program2) {
|
|
|
1342
1470
|
}
|
|
1343
1471
|
} catch (err) {
|
|
1344
1472
|
console.error(
|
|
1345
|
-
|
|
1473
|
+
pc8.red(`\u274C \u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\u5185\u5BB9:`),
|
|
1346
1474
|
err instanceof Error ? err.message : err
|
|
1347
1475
|
);
|
|
1348
1476
|
}
|
|
@@ -1350,55 +1478,55 @@ function registerLsCommand(program2) {
|
|
|
1350
1478
|
}
|
|
1351
1479
|
|
|
1352
1480
|
// commands/move.ts
|
|
1353
|
-
import
|
|
1354
|
-
import
|
|
1355
|
-
import { dirname as
|
|
1481
|
+
import fs8 from "fs/promises";
|
|
1482
|
+
import pc9 from "picocolors";
|
|
1483
|
+
import { dirname as dirname3, resolve as resolve6, join as join6, basename as basename4 } from "path";
|
|
1356
1484
|
async function copyRecursive2(src, dest) {
|
|
1357
|
-
const fileInfo = await
|
|
1485
|
+
const fileInfo = await fs8.stat(src);
|
|
1358
1486
|
if (fileInfo.isDirectory()) {
|
|
1359
|
-
await
|
|
1360
|
-
for (const entry of await
|
|
1361
|
-
await copyRecursive2(
|
|
1487
|
+
await fs8.mkdir(dest, { recursive: true });
|
|
1488
|
+
for (const entry of await fs8.readdir(src, { withFileTypes: true })) {
|
|
1489
|
+
await copyRecursive2(join6(src, entry.name), join6(dest, entry.name));
|
|
1362
1490
|
}
|
|
1363
1491
|
} else if (fileInfo.isFile()) {
|
|
1364
|
-
await
|
|
1365
|
-
await
|
|
1492
|
+
await fs8.mkdir(dirname3(dest), { recursive: true });
|
|
1493
|
+
await fs8.copyFile(src, dest);
|
|
1366
1494
|
}
|
|
1367
1495
|
}
|
|
1368
1496
|
function registerMoveCommand(program2) {
|
|
1369
1497
|
program2.command("move <source> <target>").description("\u79FB\u52A8\u6216\u91CD\u547D\u540D\u6587\u4EF6\u53CA\u76EE\u5F55").action(async (source, target) => {
|
|
1370
1498
|
if (!source || !target) {
|
|
1371
|
-
console.error(
|
|
1499
|
+
console.error(pc9.red("\u274C \u8BF7\u63D0\u4F9B\u6E90\u8DEF\u5F84\u548C\u76EE\u6807\u8DEF\u5F84"));
|
|
1372
1500
|
return;
|
|
1373
1501
|
}
|
|
1374
1502
|
const absSource = resolve6(process.cwd(), source);
|
|
1375
1503
|
const absTarget = resolve6(process.cwd(), target);
|
|
1376
1504
|
try {
|
|
1377
|
-
await
|
|
1505
|
+
await fs8.stat(absSource);
|
|
1378
1506
|
let finalTarget = absTarget;
|
|
1379
1507
|
try {
|
|
1380
|
-
const targetStat = await
|
|
1508
|
+
const targetStat = await fs8.stat(absTarget);
|
|
1381
1509
|
if (targetStat.isDirectory()) {
|
|
1382
|
-
finalTarget =
|
|
1510
|
+
finalTarget = join6(absTarget, basename4(absSource));
|
|
1383
1511
|
}
|
|
1384
1512
|
} catch {
|
|
1385
1513
|
}
|
|
1386
|
-
const targetParentDir =
|
|
1387
|
-
await
|
|
1388
|
-
console.log(
|
|
1514
|
+
const targetParentDir = dirname3(finalTarget);
|
|
1515
|
+
await fs8.mkdir(targetParentDir, { recursive: true });
|
|
1516
|
+
console.log(pc9.cyan(`\u{1F4E6} \u6B63\u5728\u79FB\u52A8: ${source} \u27A1\uFE0F ${target}...`));
|
|
1389
1517
|
try {
|
|
1390
|
-
await
|
|
1518
|
+
await fs8.rename(absSource, finalTarget);
|
|
1391
1519
|
} catch {
|
|
1392
1520
|
await copyRecursive2(absSource, finalTarget);
|
|
1393
|
-
await
|
|
1521
|
+
await fs8.rm(absSource, { recursive: true });
|
|
1394
1522
|
}
|
|
1395
|
-
console.log(
|
|
1523
|
+
console.log(pc9.green(`\u2728 \u79FB\u52A8\u6210\u529F: ${source} \u27A1\uFE0F ${target}`));
|
|
1396
1524
|
} catch (err) {
|
|
1397
1525
|
if (isNotFoundError(err)) {
|
|
1398
|
-
console.error(
|
|
1526
|
+
console.error(pc9.red(`\u274C \u9519\u8BEF: \u6E90\u8DEF\u5F84\u4E0D\u5B58\u5728: ${absSource}`));
|
|
1399
1527
|
} else {
|
|
1400
1528
|
console.error(
|
|
1401
|
-
|
|
1529
|
+
pc9.red("\u274C \u79FB\u52A8\u5931\u8D25:"),
|
|
1402
1530
|
err instanceof Error ? err.message : err
|
|
1403
1531
|
);
|
|
1404
1532
|
}
|
|
@@ -1407,21 +1535,21 @@ function registerMoveCommand(program2) {
|
|
|
1407
1535
|
}
|
|
1408
1536
|
|
|
1409
1537
|
// commands/open.ts
|
|
1410
|
-
import
|
|
1411
|
-
import
|
|
1538
|
+
import fs9 from "fs/promises";
|
|
1539
|
+
import pc10 from "picocolors";
|
|
1412
1540
|
import { resolve as resolve7 } from "path";
|
|
1413
1541
|
function registerOpenCommand(program2) {
|
|
1414
1542
|
program2.command("open [path]").description("\u5728\u7CFB\u7EDF\u6587\u4EF6\u7BA1\u7406\u5668\u4E2D\u6253\u5F00\u6307\u5B9A\u76EE\u5F55\uFF08\u9ED8\u8BA4\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF09").action(async (targetPath) => {
|
|
1415
1543
|
const inputPath = targetPath || ".";
|
|
1416
1544
|
const absolutePath = resolve7(process.cwd(), inputPath);
|
|
1417
1545
|
try {
|
|
1418
|
-
const stat = await
|
|
1546
|
+
const stat = await fs9.stat(absolutePath);
|
|
1419
1547
|
if (!stat.isDirectory()) {
|
|
1420
|
-
console.error(
|
|
1548
|
+
console.error(pc10.red(`\u274C \u9519\u8BEF: '${inputPath}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
|
|
1421
1549
|
return;
|
|
1422
1550
|
}
|
|
1423
1551
|
} catch {
|
|
1424
|
-
console.error(
|
|
1552
|
+
console.error(pc10.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u76EE\u5F55 '${inputPath}'\u3002`));
|
|
1425
1553
|
return;
|
|
1426
1554
|
}
|
|
1427
1555
|
const os3 = process.platform;
|
|
@@ -1437,16 +1565,16 @@ function registerOpenCommand(program2) {
|
|
|
1437
1565
|
cmd = "xdg-open";
|
|
1438
1566
|
args = [absolutePath];
|
|
1439
1567
|
} else {
|
|
1440
|
-
console.error(
|
|
1568
|
+
console.error(pc10.red("\u274C \u6682\u4E0D\u652F\u6301\u5728\u5F53\u524D\u7CFB\u7EDF\u4E0B\u8C03\u8D77\u6587\u4EF6\u7BA1\u7406\u5668\u3002"));
|
|
1441
1569
|
return;
|
|
1442
1570
|
}
|
|
1443
1571
|
try {
|
|
1444
|
-
console.log(
|
|
1572
|
+
console.log(pc10.cyan(`\u{1F4C2} \u6B63\u5728\u6253\u5F00\u6587\u4EF6\u5939: ${absolutePath}...`));
|
|
1445
1573
|
await spawnCommand(cmd, args);
|
|
1446
|
-
console.log(
|
|
1574
|
+
console.log(pc10.green("\u2728 \u6210\u529F\u8C03\u8D77\u6587\u4EF6\u7BA1\u7406\u5668\uFF01"));
|
|
1447
1575
|
} catch (err) {
|
|
1448
1576
|
console.error(
|
|
1449
|
-
|
|
1577
|
+
pc10.red("\u274C \u65E0\u6CD5\u6253\u5F00\u7BA1\u7406\u5668:"),
|
|
1450
1578
|
err instanceof Error ? err.message : err
|
|
1451
1579
|
);
|
|
1452
1580
|
}
|
|
@@ -1454,19 +1582,19 @@ function registerOpenCommand(program2) {
|
|
|
1454
1582
|
}
|
|
1455
1583
|
|
|
1456
1584
|
// commands/park.ts
|
|
1457
|
-
import
|
|
1585
|
+
import fs10, { open } from "fs/promises";
|
|
1458
1586
|
import process2 from "process";
|
|
1459
|
-
import
|
|
1460
|
-
import { join as
|
|
1587
|
+
import pc11 from "picocolors";
|
|
1588
|
+
import { join as join7, isAbsolute, resolve as resolve8, dirname as dirname4 } from "path";
|
|
1461
1589
|
var CONFIG_FILE_NAME = ".park_config.json";
|
|
1462
1590
|
function getConfigFile() {
|
|
1463
1591
|
const home = process2.env["HOME"] || process2.env["USERPROFILE"] || process2.cwd();
|
|
1464
|
-
return
|
|
1592
|
+
return join7(home, CONFIG_FILE_NAME);
|
|
1465
1593
|
}
|
|
1466
1594
|
async function readConfig() {
|
|
1467
1595
|
try {
|
|
1468
1596
|
const path = getConfigFile();
|
|
1469
|
-
const content = await
|
|
1597
|
+
const content = await fs10.readFile(path, "utf-8");
|
|
1470
1598
|
return JSON.parse(content);
|
|
1471
1599
|
} catch {
|
|
1472
1600
|
return {};
|
|
@@ -1475,9 +1603,9 @@ async function readConfig() {
|
|
|
1475
1603
|
async function writeConfig(config) {
|
|
1476
1604
|
try {
|
|
1477
1605
|
const path = getConfigFile();
|
|
1478
|
-
await
|
|
1606
|
+
await fs10.writeFile(path, JSON.stringify(config, null, 2));
|
|
1479
1607
|
} catch (err) {
|
|
1480
|
-
console.error(
|
|
1608
|
+
console.error(pc11.red("\u274C \u5199\u5165\u5168\u5C40\u914D\u7F6E\u6587\u4EF6\u5931\u8D25:"), err);
|
|
1481
1609
|
}
|
|
1482
1610
|
}
|
|
1483
1611
|
async function downloadImage(imageName, outputFilename, targetDir) {
|
|
@@ -1489,8 +1617,8 @@ async function downloadImage(imageName, outputFilename, targetDir) {
|
|
|
1489
1617
|
cleanName = decodeURIComponent(cleanName).substring(prefix.length);
|
|
1490
1618
|
}
|
|
1491
1619
|
const fullImageName = prefix + cleanName;
|
|
1492
|
-
console.log(
|
|
1493
|
-
console.log(
|
|
1620
|
+
console.log(pc11.cyan(`\u{1F4E6} \u76EE\u6807\u955C\u50CF: ${pc11.bold(fullImageName)}`));
|
|
1621
|
+
console.log(pc11.dim("\u6B63\u5728\u5411\u6253\u5305\u670D\u52A1\u5668\u63D0\u4EA4\u4EFB\u52A1\uFF0C\u8BF7\u7A0D\u5019...\n"));
|
|
1494
1622
|
try {
|
|
1495
1623
|
const response = await fetch("https://city189.cn:1091/", {
|
|
1496
1624
|
method: "POST",
|
|
@@ -1527,15 +1655,15 @@ async function downloadImage(imageName, outputFilename, targetDir) {
|
|
|
1527
1655
|
matchedFilename = match[0];
|
|
1528
1656
|
downloadUrl = `https://city189.cn:1091/download/${matchedFilename}`;
|
|
1529
1657
|
} else {
|
|
1530
|
-
console.error(
|
|
1531
|
-
console.log(
|
|
1658
|
+
console.error(pc11.red("\u274C \u672A\u80FD\u5728\u670D\u52A1\u5668\u54CD\u5E94\u4E2D\u5339\u914D\u5230\u6253\u5305\u6587\u4EF6\u540D\u3002"));
|
|
1659
|
+
console.log(pc11.yellow("\u670D\u52A1\u5668\u539F\u59CB\u54CD\u5E94\u5982\u4E0B\uFF1A"));
|
|
1532
1660
|
console.log(text);
|
|
1533
1661
|
throw new Error("\u65E0\u6CD5\u63D0\u53D6\u6253\u5305\u540E\u7684\u6587\u4EF6\u540D");
|
|
1534
1662
|
}
|
|
1535
1663
|
}
|
|
1536
|
-
console.log(
|
|
1537
|
-
console.log(
|
|
1538
|
-
console.log(
|
|
1664
|
+
console.log(pc11.green(`\u2705 \u6253\u5305\u4EFB\u52A1\u63D0\u4EA4\u6210\u529F!`));
|
|
1665
|
+
console.log(pc11.green(`\u{1F517} \u4E0B\u8F7D\u94FE\u63A5: ${pc11.underline(downloadUrl)}`));
|
|
1666
|
+
console.log(pc11.cyan(`
|
|
1539
1667
|
\u{1F4E5} \u5F00\u59CB\u4E0B\u8F7D: ${matchedFilename}...`));
|
|
1540
1668
|
const downloadRes = await fetch(downloadUrl, {
|
|
1541
1669
|
headers: {
|
|
@@ -1560,10 +1688,10 @@ async function downloadImage(imageName, outputFilename, targetDir) {
|
|
|
1560
1688
|
downloadDir = config.defaultDownloadDir ? config.defaultDownloadDir : process2.cwd();
|
|
1561
1689
|
}
|
|
1562
1690
|
const baseFilename = outputFilename || matchedFilename || "bundle.tar";
|
|
1563
|
-
const finalPath = isAbsolute(baseFilename) ? baseFilename :
|
|
1564
|
-
const targetDirToCreate =
|
|
1691
|
+
const finalPath = isAbsolute(baseFilename) ? baseFilename : join7(downloadDir, baseFilename);
|
|
1692
|
+
const targetDirToCreate = dirname4(finalPath);
|
|
1565
1693
|
try {
|
|
1566
|
-
await
|
|
1694
|
+
await fs10.mkdir(targetDirToCreate, { recursive: true });
|
|
1567
1695
|
} catch {
|
|
1568
1696
|
}
|
|
1569
1697
|
const file = await open(finalPath, "w");
|
|
@@ -1590,11 +1718,11 @@ async function downloadImage(imageName, outputFilename, targetDir) {
|
|
|
1590
1718
|
}
|
|
1591
1719
|
}
|
|
1592
1720
|
await file.close();
|
|
1593
|
-
console.log("\n" +
|
|
1721
|
+
console.log("\n" + pc11.green(`\u2728 \u4E0B\u8F7D\u5E76\u4FDD\u5B58\u6210\u529F! \u6587\u4EF6\u8DEF\u5F84: ${finalPath}`));
|
|
1594
1722
|
} catch (error) {
|
|
1595
|
-
console.error(
|
|
1723
|
+
console.error(pc11.red("\n\u274C \u6267\u884C\u5931\u8D25\u3002"));
|
|
1596
1724
|
if (error instanceof Error) {
|
|
1597
|
-
console.error(
|
|
1725
|
+
console.error(pc11.red("\u9519\u8BEF\u8BE6\u60C5:"), error.message);
|
|
1598
1726
|
}
|
|
1599
1727
|
}
|
|
1600
1728
|
}
|
|
@@ -1607,11 +1735,11 @@ function registerParkCommand(program2) {
|
|
|
1607
1735
|
if (options.global) {
|
|
1608
1736
|
const absPath = resolve8(process2.cwd(), options.global);
|
|
1609
1737
|
await writeConfig({ defaultDownloadDir: absPath });
|
|
1610
|
-
console.log(
|
|
1738
|
+
console.log(pc11.green(`\u2728 \u5DF2\u6210\u529F\u8BBE\u7F6E\u5168\u5C40\u9ED8\u8BA4\u4E0B\u8F7D\u76EE\u5F55\u4E3A: ${absPath}`));
|
|
1611
1739
|
return;
|
|
1612
1740
|
}
|
|
1613
1741
|
if (!image) {
|
|
1614
|
-
console.error(
|
|
1742
|
+
console.error(pc11.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u9700\u8981\u4E0B\u8F7D\u7684\u955C\u50CF\u540D\u79F0\u3002"));
|
|
1615
1743
|
cmd.outputHelp();
|
|
1616
1744
|
return;
|
|
1617
1745
|
}
|
|
@@ -1621,7 +1749,7 @@ function registerParkCommand(program2) {
|
|
|
1621
1749
|
}
|
|
1622
1750
|
|
|
1623
1751
|
// commands/proxy.ts
|
|
1624
|
-
import
|
|
1752
|
+
import pc12 from "picocolors";
|
|
1625
1753
|
function registerProxyCommand(program2) {
|
|
1626
1754
|
program2.command("proxy [action] [port]").description(
|
|
1627
1755
|
"\u7BA1\u7406\u7EC8\u7AEF\u4E34\u65F6\u4EE3\u7406 (\u652F\u6301 proxy on [port] \u6216 proxy off\uFF0C\u65E0\u53C2\u6570\u65F6\u67E5\u770B\u5F53\u524D\u72B6\u6001)"
|
|
@@ -1629,29 +1757,29 @@ function registerProxyCommand(program2) {
|
|
|
1629
1757
|
if (action === "on") {
|
|
1630
1758
|
const p = port || "7890";
|
|
1631
1759
|
console.log(
|
|
1632
|
-
|
|
1760
|
+
pc12.yellow(
|
|
1633
1761
|
`\u26A0\uFE0F \u8B66\u544A: \u76F4\u63A5\u8FD0\u884C\u4E8C\u8FDB\u5236\u65E0\u6CD5\u76F4\u63A5\u4FEE\u6539\u5F53\u524D\u7EC8\u7AEF\u7684\u4E3B\u73AF\u5883\u53D8\u91CF\u3002`
|
|
1634
1762
|
)
|
|
1635
1763
|
);
|
|
1636
|
-
console.log(
|
|
1637
|
-
console.log(
|
|
1638
|
-
console.log(
|
|
1639
|
-
console.log(
|
|
1764
|
+
console.log(pc12.cyan(`\u{1F449} \u8BF7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u624B\u52A8\u542F\u7528\u4EE3\u7406\uFF1A`));
|
|
1765
|
+
console.log(pc12.bold(` export http_proxy="http://127.0.0.1:${p}"`));
|
|
1766
|
+
console.log(pc12.bold(` export https_proxy="http://127.0.0.1:${p}"`));
|
|
1767
|
+
console.log(pc12.bold(` export all_proxy="socks5://127.0.0.1:${p}"`));
|
|
1640
1768
|
console.log(
|
|
1641
|
-
|
|
1769
|
+
pc12.dim(
|
|
1642
1770
|
`
|
|
1643
1771
|
\u{1F4A1} \u63D0\u793A\uFF1A\u6267\u884C\u4E00\u6B21 'xx completion' \u5E76\u91CD\u5F00\u7EC8\u7AEF\u540E\uFF0C\u5373\u53EF\u76F4\u63A5\u8FD0\u884C 'xx proxy on' \u4E00\u952E\u5F00\u542F\uFF01`
|
|
1644
1772
|
)
|
|
1645
1773
|
);
|
|
1646
1774
|
} else if (action === "off") {
|
|
1647
1775
|
console.log(
|
|
1648
|
-
|
|
1776
|
+
pc12.yellow(
|
|
1649
1777
|
`\u26A0\uFE0F \u8B66\u544A: \u76F4\u63A5\u8FD0\u884C\u4E8C\u8FDB\u5236\u65E0\u6CD5\u76F4\u63A5\u4FEE\u6539\u5F53\u524D\u7EC8\u7AEF\u7684\u4E3B\u73AF\u5883\u53D8\u91CF\u3002`
|
|
1650
1778
|
)
|
|
1651
1779
|
);
|
|
1652
|
-
console.log(
|
|
1780
|
+
console.log(pc12.cyan(`\u{1F449} \u8BF7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u624B\u52A8\u5173\u95ED\u4EE3\u7406\uFF1A`));
|
|
1653
1781
|
console.log(
|
|
1654
|
-
|
|
1782
|
+
pc12.bold(
|
|
1655
1783
|
` unset http_proxy https_proxy all_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY`
|
|
1656
1784
|
)
|
|
1657
1785
|
);
|
|
@@ -1660,15 +1788,15 @@ function registerProxyCommand(program2) {
|
|
|
1660
1788
|
const httpsProxy = process.env["https_proxy"] || process.env["HTTPS_PROXY"];
|
|
1661
1789
|
const allProxy = process.env["all_proxy"] || process.env["ALL_PROXY"];
|
|
1662
1790
|
if (httpProxy || httpsProxy || allProxy) {
|
|
1663
|
-
console.log(
|
|
1664
|
-
if (httpProxy) console.log(` http_proxy = ${
|
|
1665
|
-
if (httpsProxy) console.log(` https_proxy = ${
|
|
1666
|
-
if (allProxy) console.log(` all_proxy = ${
|
|
1791
|
+
console.log(pc12.yellow("\u{1F50D} [xx] \u68C0\u6D4B\u5230\u5F53\u524D\u7EC8\u7AEF\u5DF2\u914D\u7F6E\u4E34\u65F6\u4EE3\u7406\uFF1A"));
|
|
1792
|
+
if (httpProxy) console.log(` http_proxy = ${pc12.bold(httpProxy)}`);
|
|
1793
|
+
if (httpsProxy) console.log(` https_proxy = ${pc12.bold(httpsProxy)}`);
|
|
1794
|
+
if (allProxy) console.log(` all_proxy = ${pc12.bold(allProxy)}`);
|
|
1667
1795
|
} else {
|
|
1668
|
-
console.log(
|
|
1796
|
+
console.log(pc12.green("\u{1F50D} [xx] \u5F53\u524D\u7EC8\u7AEF\u672A\u914D\u7F6E\u4EFB\u4F55\u4EE3\u7406 (\u76F4\u8FDE\u6A21\u5F0F)"));
|
|
1669
1797
|
}
|
|
1670
1798
|
console.log(
|
|
1671
|
-
|
|
1799
|
+
pc12.dim(
|
|
1672
1800
|
"\n\u{1F4A1} \u63D0\u793A\uFF1A\u60A8\u53EF\u4EE5\u4F7F\u7528 'xx proxy on [port]' \u5F00\u542F\u6216 'xx proxy off' \u5173\u95ED\u4E34\u65F6\u4EE3\u7406\u3002"
|
|
1673
1801
|
)
|
|
1674
1802
|
);
|
|
@@ -1677,15 +1805,15 @@ function registerProxyCommand(program2) {
|
|
|
1677
1805
|
}
|
|
1678
1806
|
|
|
1679
1807
|
// commands/remove.ts
|
|
1680
|
-
import
|
|
1681
|
-
import
|
|
1808
|
+
import fs11 from "fs/promises";
|
|
1809
|
+
import pc13 from "picocolors";
|
|
1682
1810
|
import { resolve as resolve9 } from "path";
|
|
1683
1811
|
import fg from "fast-glob";
|
|
1684
1812
|
import trash from "trash";
|
|
1685
1813
|
function registerRemoveCommand(program2) {
|
|
1686
1814
|
program2.command("remove <paths...>").description("\u5B89\u5168\u5730\u5C06\u6307\u5B9A\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u79FB\u81F3\u7CFB\u7EDF\u56DE\u6536\u7AD9\uFF08\u652F\u6301\u901A\u914D\u7B26\u53CA\u591A\u9009\uFF09").action(async (paths) => {
|
|
1687
1815
|
if (!paths || paths.length === 0) {
|
|
1688
|
-
console.error(
|
|
1816
|
+
console.error(pc13.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u653E\u5165\u56DE\u6536\u7AD9\u7684\u8DEF\u5F84\u6216\u901A\u914D\u7B26\u89C4\u5219"));
|
|
1689
1817
|
return;
|
|
1690
1818
|
}
|
|
1691
1819
|
const resolvedPathsToDelete = /* @__PURE__ */ new Set();
|
|
@@ -1705,21 +1833,21 @@ function registerRemoveCommand(program2) {
|
|
|
1705
1833
|
}
|
|
1706
1834
|
} catch (err) {
|
|
1707
1835
|
console.error(
|
|
1708
|
-
|
|
1836
|
+
pc13.red(`\u274C \u5339\u914D\u901A\u914D\u7B26 '${pattern}' \u65F6\u53D1\u751F\u5F02\u5E38:`),
|
|
1709
1837
|
err instanceof Error ? err.message : err
|
|
1710
1838
|
);
|
|
1711
1839
|
}
|
|
1712
1840
|
} else {
|
|
1713
1841
|
const absolutePath = resolve9(process.cwd(), pattern);
|
|
1714
1842
|
try {
|
|
1715
|
-
await
|
|
1843
|
+
await fs11.stat(absolutePath);
|
|
1716
1844
|
resolvedPathsToDelete.add(absolutePath);
|
|
1717
1845
|
} catch (err) {
|
|
1718
1846
|
if (isNotFoundError(err)) {
|
|
1719
1847
|
notFoundPaths.push(absolutePath);
|
|
1720
1848
|
} else {
|
|
1721
1849
|
console.error(
|
|
1722
|
-
|
|
1850
|
+
pc13.red(`\u274C \u83B7\u53D6\u8DEF\u5F84\u72B6\u6001\u5931\u8D25 [${pattern}]:`),
|
|
1723
1851
|
err instanceof Error ? err.message : err
|
|
1724
1852
|
);
|
|
1725
1853
|
}
|
|
@@ -1728,31 +1856,31 @@ function registerRemoveCommand(program2) {
|
|
|
1728
1856
|
}
|
|
1729
1857
|
if (notFoundPaths.length > 0) {
|
|
1730
1858
|
for (const path of notFoundPaths) {
|
|
1731
|
-
console.error(
|
|
1859
|
+
console.error(pc13.red(`\u274C \u8DEF\u5F84\u4E0D\u5B58\u5728: ${path}`));
|
|
1732
1860
|
}
|
|
1733
1861
|
}
|
|
1734
1862
|
if (resolvedPathsToDelete.size === 0) {
|
|
1735
|
-
console.log(
|
|
1863
|
+
console.log(pc13.yellow("\u2139\uFE0F \u672A\u80FD\u627E\u5230\u4EFB\u4F55\u4E0E\u6307\u5B9A\u6761\u4EF6\u5339\u914D\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u3002"));
|
|
1736
1864
|
return;
|
|
1737
1865
|
}
|
|
1738
1866
|
try {
|
|
1739
1867
|
console.log(
|
|
1740
|
-
|
|
1868
|
+
pc13.cyan(
|
|
1741
1869
|
`\u{1F4E6} \u6B63\u5728\u5C06 ${resolvedPathsToDelete.size} \u4E2A\u9879\u79FB\u81F3\u7CFB\u7EDF\u56DE\u6536\u7AD9...`
|
|
1742
1870
|
)
|
|
1743
1871
|
);
|
|
1744
1872
|
await trash(Array.from(resolvedPathsToDelete));
|
|
1745
1873
|
for (const path of resolvedPathsToDelete) {
|
|
1746
|
-
console.log(
|
|
1874
|
+
console.log(pc13.dim(` - \u5DF2\u79FB\u5165\u5783\u573E\u7BB1: ${path}`));
|
|
1747
1875
|
}
|
|
1748
1876
|
console.log(
|
|
1749
|
-
|
|
1877
|
+
pc13.green(
|
|
1750
1878
|
`\u2728 \u6210\u529F\uFF01\u5171 ${resolvedPathsToDelete.size} \u4E2A\u6587\u4EF6/\u76EE\u5F55\u5DF2\u5B89\u5168\u9001\u81F3\u7CFB\u7EDF\u56DE\u6536\u7AD9\u3002`
|
|
1751
1879
|
)
|
|
1752
1880
|
);
|
|
1753
1881
|
} catch (err) {
|
|
1754
1882
|
console.error(
|
|
1755
|
-
|
|
1883
|
+
pc13.red("\u274C \u79FB\u81F3\u56DE\u6536\u7AD9\u5931\u8D25:"),
|
|
1756
1884
|
err instanceof Error ? err.message : err
|
|
1757
1885
|
);
|
|
1758
1886
|
}
|
|
@@ -1760,32 +1888,32 @@ function registerRemoveCommand(program2) {
|
|
|
1760
1888
|
}
|
|
1761
1889
|
|
|
1762
1890
|
// commands/search.ts
|
|
1763
|
-
import
|
|
1764
|
-
import
|
|
1765
|
-
import { resolve as resolve10, basename as
|
|
1891
|
+
import fs12 from "fs/promises";
|
|
1892
|
+
import pc14 from "picocolors";
|
|
1893
|
+
import { resolve as resolve10, basename as basename5, relative } from "path";
|
|
1766
1894
|
import fg2 from "fast-glob";
|
|
1767
1895
|
function registerSearchCommand(program2) {
|
|
1768
1896
|
program2.command("search <keyword> [directory]").description(
|
|
1769
1897
|
"\u9012\u5F52\u641C\u7D22\u76EE\u5F55\u4E0B\u5305\u542B\u6307\u5B9A\u5173\u952E\u8BCD\u7684\u6587\u4EF6\u6216\u76EE\u5F55\uFF08\u652F\u6301 Ctrl+\u70B9\u51FB \u5FEB\u6377\u6253\u5F00\uFF09"
|
|
1770
1898
|
).action(async (keyword, directory) => {
|
|
1771
1899
|
if (!keyword) {
|
|
1772
|
-
console.error(
|
|
1900
|
+
console.error(pc14.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u641C\u7D22\u7684\u6587\u4EF6\u540D\u5173\u952E\u8BCD"));
|
|
1773
1901
|
return;
|
|
1774
1902
|
}
|
|
1775
1903
|
const startDir = directory || ".";
|
|
1776
1904
|
const absoluteStartDir = resolve10(process.cwd(), startDir);
|
|
1777
1905
|
try {
|
|
1778
|
-
const stat = await
|
|
1906
|
+
const stat = await fs12.stat(absoluteStartDir);
|
|
1779
1907
|
if (!stat.isDirectory()) {
|
|
1780
|
-
console.error(
|
|
1908
|
+
console.error(pc14.red(`\u274C \u9519\u8BEF: '${startDir}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
|
|
1781
1909
|
return;
|
|
1782
1910
|
}
|
|
1783
1911
|
} catch {
|
|
1784
|
-
console.error(
|
|
1912
|
+
console.error(pc14.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u8D77\u70B9\u76EE\u5F55 '${startDir}'\u3002`));
|
|
1785
1913
|
return;
|
|
1786
1914
|
}
|
|
1787
1915
|
console.log(
|
|
1788
|
-
|
|
1916
|
+
pc14.cyan(
|
|
1789
1917
|
`\u{1F50D} \u6B63\u5728\u76EE\u5F55 ${absoluteStartDir} \u4E2D\u9012\u5F52\u641C\u5BFB\u5305\u542B "${keyword}" \u7684\u9879\u76EE...
|
|
1790
1918
|
`
|
|
1791
1919
|
)
|
|
@@ -1806,30 +1934,30 @@ function registerSearchCommand(program2) {
|
|
|
1806
1934
|
]
|
|
1807
1935
|
});
|
|
1808
1936
|
for (const entryPath of entries) {
|
|
1809
|
-
const name =
|
|
1937
|
+
const name = basename5(entryPath);
|
|
1810
1938
|
if (name.toLowerCase().includes(keyword.toLowerCase())) {
|
|
1811
1939
|
matchCount++;
|
|
1812
1940
|
const relativePath = relative(absoluteStartDir, entryPath);
|
|
1813
1941
|
const isDirectory = !name.includes(".") || entryPath.endsWith("/");
|
|
1814
1942
|
let isDir = isDirectory;
|
|
1815
1943
|
try {
|
|
1816
|
-
const entryStat = await
|
|
1944
|
+
const entryStat = await fs12.stat(entryPath);
|
|
1817
1945
|
isDir = entryStat.isDirectory();
|
|
1818
1946
|
} catch {
|
|
1819
1947
|
}
|
|
1820
1948
|
const typeIcon = isDir ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
1821
1949
|
const fileUri = `file://${entryPath}`;
|
|
1822
|
-
const hyperlink = `\x1B]8;;${fileUri}\x1B\\${
|
|
1823
|
-
console.log(`${typeIcon} ${hyperlink} -> ${
|
|
1950
|
+
const hyperlink = `\x1B]8;;${fileUri}\x1B\\${pc14.bold(name)}\x1B]8;;\x1B\\`;
|
|
1951
|
+
console.log(`${typeIcon} ${hyperlink} -> ${pc14.dim(fileUri)}`);
|
|
1824
1952
|
}
|
|
1825
1953
|
}
|
|
1826
1954
|
console.log(
|
|
1827
|
-
|
|
1955
|
+
pc14.green(`
|
|
1828
1956
|
\u2728 \u641C\u7D22\u5B8C\u6210\uFF01\u5171\u627E\u5230 ${matchCount} \u4E2A\u5339\u914D\u7684\u9879\u76EE\u3002`)
|
|
1829
1957
|
);
|
|
1830
1958
|
} catch (err) {
|
|
1831
1959
|
console.error(
|
|
1832
|
-
|
|
1960
|
+
pc14.red("\u274C \u641C\u5BFB\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:"),
|
|
1833
1961
|
err instanceof Error ? err.message : err
|
|
1834
1962
|
);
|
|
1835
1963
|
}
|
|
@@ -1837,7 +1965,7 @@ function registerSearchCommand(program2) {
|
|
|
1837
1965
|
}
|
|
1838
1966
|
|
|
1839
1967
|
// commands/translate.ts
|
|
1840
|
-
import
|
|
1968
|
+
import pc15 from "picocolors";
|
|
1841
1969
|
import { translate } from "google-translate-api-x";
|
|
1842
1970
|
import readline from "readline";
|
|
1843
1971
|
import process3 from "process";
|
|
@@ -1854,13 +1982,13 @@ async function performTranslation(text, userSpecifiedLang) {
|
|
|
1854
1982
|
to: targetLang
|
|
1855
1983
|
});
|
|
1856
1984
|
console.log(
|
|
1857
|
-
`${
|
|
1985
|
+
`${pc15.green("\u8BD1\u6587:")} ${pc15.bold(res.text)} ${pc15.dim(`(${res.from.language.iso} -> ${targetLang})`)}`
|
|
1858
1986
|
);
|
|
1859
1987
|
} catch (err) {
|
|
1860
1988
|
if (err instanceof Error) {
|
|
1861
|
-
console.error(
|
|
1989
|
+
console.error(pc15.red("\u274C \u7FFB\u8BD1\u51FA\u9519:"), err.message);
|
|
1862
1990
|
} else {
|
|
1863
|
-
console.error(
|
|
1991
|
+
console.error(pc15.red("\u274C \u7FFB\u8BD1\u51FA\u9519:"), String(err));
|
|
1864
1992
|
}
|
|
1865
1993
|
}
|
|
1866
1994
|
}
|
|
@@ -1868,11 +1996,11 @@ function startInteractiveMode(userSpecifiedLang) {
|
|
|
1868
1996
|
const rl = readline.createInterface({
|
|
1869
1997
|
input: process3.stdin,
|
|
1870
1998
|
output: process3.stdout,
|
|
1871
|
-
prompt:
|
|
1999
|
+
prompt: pc15.cyan("\u7FFB\u8BD1\u8F93\u5165 > ")
|
|
1872
2000
|
});
|
|
1873
2001
|
const modeTip = userSpecifiedLang === "auto" ? "\u667A\u80FD\u81EA\u52A8\u8BC6\u522B" : `\u5F3A\u5236\u76EE\u6807\u8BED\u8A00: ${userSpecifiedLang}`;
|
|
1874
|
-
console.log(
|
|
1875
|
-
console.log(
|
|
2002
|
+
console.log(pc15.yellow(`\u2728 \u5DF2\u8FDB\u5165\u4EA4\u4E92\u6A21\u5F0F (${modeTip})`));
|
|
2003
|
+
console.log(pc15.dim('\u8F93\u5165 "exit" \u6216\u6309 Ctrl+C \u9000\u51FA\n'));
|
|
1876
2004
|
rl.prompt();
|
|
1877
2005
|
rl.on("line", async (line) => {
|
|
1878
2006
|
const input = line.trim();
|
|
@@ -1886,7 +2014,7 @@ function startInteractiveMode(userSpecifiedLang) {
|
|
|
1886
2014
|
console.log();
|
|
1887
2015
|
rl.prompt();
|
|
1888
2016
|
}).on("close", () => {
|
|
1889
|
-
console.log(
|
|
2017
|
+
console.log(pc15.blue("\n\u518D\u89C1!"));
|
|
1890
2018
|
process3.exit(0);
|
|
1891
2019
|
});
|
|
1892
2020
|
}
|
|
@@ -1905,464 +2033,33 @@ function registerTanslateCommand(program2) {
|
|
|
1905
2033
|
}
|
|
1906
2034
|
|
|
1907
2035
|
// commands/uninstall.ts
|
|
1908
|
-
import
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
if (!await isCommandAvailable("snap")) return false;
|
|
1916
|
-
try {
|
|
1917
|
-
const { success } = await runCommand("snap", ["list", packageName]);
|
|
1918
|
-
return success;
|
|
1919
|
-
} catch {
|
|
1920
|
-
return false;
|
|
1921
|
-
}
|
|
1922
|
-
}
|
|
1923
|
-
async function isSystemPackageInstalled(packageName) {
|
|
1924
|
-
try {
|
|
1925
|
-
const osRelease = await fs12.readFile("/etc/os-release", "utf-8");
|
|
1926
|
-
if (osRelease.includes("fedora") || osRelease.includes("rhel") || osRelease.includes("centos")) {
|
|
1927
|
-
const { success } = await runCommand("rpm", ["-q", packageName]);
|
|
1928
|
-
return success;
|
|
1929
|
-
} else {
|
|
1930
|
-
const { success, stdout } = await runCommand("dpkg-query", [
|
|
1931
|
-
"-W",
|
|
1932
|
-
"-f=${Status}",
|
|
1933
|
-
packageName
|
|
1934
|
-
]);
|
|
1935
|
-
if (success) {
|
|
1936
|
-
const status = decodeOutput(stdout).trim();
|
|
1937
|
-
return status.includes("installed");
|
|
1938
|
-
}
|
|
1939
|
-
return false;
|
|
1940
|
-
}
|
|
1941
|
-
} catch {
|
|
1942
|
-
return false;
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
async function findGreenAppPath(appName) {
|
|
1946
|
-
const home = getHomeDir2();
|
|
1947
|
-
const greenAppDir = join7(home, "GreenApp");
|
|
1948
|
-
const dirPath = join7(greenAppDir, appName);
|
|
1949
|
-
try {
|
|
1950
|
-
const stat = await fs12.stat(dirPath);
|
|
1951
|
-
if (stat.isDirectory()) return dirPath;
|
|
1952
|
-
} catch {
|
|
1953
|
-
}
|
|
1954
|
-
const appImagePath = join7(greenAppDir, `${appName}.AppImage`);
|
|
1955
|
-
const appImageLowerPath = join7(greenAppDir, `${appName}.appimage`);
|
|
1956
|
-
try {
|
|
1957
|
-
const stat = await fs12.stat(appImagePath);
|
|
1958
|
-
if (stat.isFile()) return appImagePath;
|
|
1959
|
-
} catch {
|
|
1960
|
-
try {
|
|
1961
|
-
const stat = await fs12.stat(appImageLowerPath);
|
|
1962
|
-
if (stat.isFile()) return appImageLowerPath;
|
|
1963
|
-
} catch {
|
|
1964
|
-
}
|
|
1965
|
-
}
|
|
1966
|
-
if (appName.toLowerCase().endsWith(".appimage")) {
|
|
1967
|
-
const directPath = join7(greenAppDir, appName);
|
|
1968
|
-
try {
|
|
1969
|
-
const stat = await fs12.stat(directPath);
|
|
1970
|
-
if (stat.isFile()) return directPath;
|
|
1971
|
-
} catch {
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
return null;
|
|
1975
|
-
}
|
|
1976
|
-
async function extractDebPackageName(absPath) {
|
|
1977
|
-
try {
|
|
1978
|
-
const { success, stdout } = await runCommand("dpkg-deb", [
|
|
1979
|
-
"-f",
|
|
1980
|
-
absPath,
|
|
1981
|
-
"Package"
|
|
1982
|
-
]);
|
|
1983
|
-
if (success) {
|
|
1984
|
-
return decodeOutput(stdout).trim();
|
|
1985
|
-
}
|
|
1986
|
-
} catch {
|
|
1987
|
-
}
|
|
1988
|
-
return void 0;
|
|
1989
|
-
}
|
|
1990
|
-
async function extractRpmPackageName(absPath) {
|
|
1991
|
-
try {
|
|
1992
|
-
const { success, stdout } = await runCommand("rpm", [
|
|
1993
|
-
"-qp",
|
|
1994
|
-
"--queryformat",
|
|
1995
|
-
"%{NAME}",
|
|
1996
|
-
absPath
|
|
1997
|
-
]);
|
|
1998
|
-
if (success) {
|
|
1999
|
-
return decodeOutput(stdout).trim();
|
|
2000
|
-
}
|
|
2001
|
-
} catch {
|
|
2002
|
-
}
|
|
2003
|
-
return void 0;
|
|
2004
|
-
}
|
|
2005
|
-
async function searchGreenApps(query) {
|
|
2006
|
-
const home = getHomeDir2();
|
|
2007
|
-
const greenAppDir = join7(home, "GreenApp");
|
|
2008
|
-
const candidates = [];
|
|
2009
|
-
try {
|
|
2010
|
-
for (const entry of await fs12.readdir(greenAppDir, {
|
|
2011
|
-
withFileTypes: true
|
|
2012
|
-
})) {
|
|
2013
|
-
if (entry.name.toLowerCase().includes(query.toLowerCase())) {
|
|
2014
|
-
candidates.push(entry.name.replace(/\.appimage/i, ""));
|
|
2015
|
-
}
|
|
2016
|
-
}
|
|
2017
|
-
} catch {
|
|
2018
|
-
}
|
|
2019
|
-
return candidates;
|
|
2020
|
-
}
|
|
2021
|
-
async function searchFlatpaks(query) {
|
|
2022
|
-
const candidates = [];
|
|
2023
|
-
if (!await isCommandAvailable("flatpak")) return candidates;
|
|
2024
|
-
try {
|
|
2025
|
-
const { success, stdout } = await runCommand("flatpak", [
|
|
2026
|
-
"list",
|
|
2027
|
-
"--columns=application,name"
|
|
2028
|
-
]);
|
|
2029
|
-
if (success) {
|
|
2030
|
-
const output = decodeOutput(stdout).trim();
|
|
2031
|
-
const lines = output.split("\n");
|
|
2032
|
-
for (const line of lines) {
|
|
2033
|
-
const parts = line.split(" ").map((p) => p.trim());
|
|
2034
|
-
if (parts.length >= 2) {
|
|
2035
|
-
const [id, name] = parts;
|
|
2036
|
-
if (id.toLowerCase().includes(query.toLowerCase()) || name.toLowerCase().includes(query.toLowerCase())) {
|
|
2037
|
-
candidates.push({ id, name });
|
|
2038
|
-
}
|
|
2039
|
-
}
|
|
2040
|
-
}
|
|
2041
|
-
}
|
|
2042
|
-
} catch {
|
|
2043
|
-
}
|
|
2044
|
-
return candidates;
|
|
2045
|
-
}
|
|
2046
|
-
async function searchDebPackages(query) {
|
|
2047
|
-
const pkgs = [];
|
|
2048
|
-
try {
|
|
2049
|
-
const { success, stdout } = await runCommand("dpkg-query", [
|
|
2050
|
-
"-W",
|
|
2051
|
-
"-f=${Package}\n",
|
|
2052
|
-
`*${query}*`
|
|
2053
|
-
]);
|
|
2054
|
-
if (success) {
|
|
2055
|
-
const output = decodeOutput(stdout).trim();
|
|
2056
|
-
const lines = output.split("\n");
|
|
2057
|
-
for (const line of lines) {
|
|
2058
|
-
const name = line.trim();
|
|
2059
|
-
if (name && !name.startsWith("-f=")) {
|
|
2060
|
-
pkgs.push(name);
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
} catch {
|
|
2065
|
-
}
|
|
2066
|
-
return pkgs;
|
|
2067
|
-
}
|
|
2068
|
-
async function searchRpmPackages(query) {
|
|
2069
|
-
const pkgs = [];
|
|
2070
|
-
try {
|
|
2071
|
-
const { success, stdout } = await runCommand("rpm", [
|
|
2072
|
-
"-qa",
|
|
2073
|
-
"--queryformat",
|
|
2074
|
-
"%{NAME}\n",
|
|
2075
|
-
`*${query}*`
|
|
2076
|
-
]);
|
|
2077
|
-
if (success) {
|
|
2078
|
-
const output = decodeOutput(stdout).trim();
|
|
2079
|
-
const lines = output.split("\n");
|
|
2080
|
-
const uniquePkgs = /* @__PURE__ */ new Set();
|
|
2081
|
-
for (const line of lines) {
|
|
2082
|
-
const name = line.trim();
|
|
2083
|
-
if (name) {
|
|
2084
|
-
uniquePkgs.add(name);
|
|
2085
|
-
}
|
|
2086
|
-
}
|
|
2087
|
-
pkgs.push(...uniquePkgs);
|
|
2088
|
-
}
|
|
2089
|
-
} catch {
|
|
2090
|
-
}
|
|
2091
|
-
return pkgs;
|
|
2092
|
-
}
|
|
2093
|
-
async function removeDeb(packageName) {
|
|
2094
|
-
console.log(pc15.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 apt \u5378\u8F7D DEB \u8F6F\u4EF6\u5305: ${packageName}...`));
|
|
2095
|
-
const status = await spawnCommand("sudo", [
|
|
2096
|
-
"apt-get",
|
|
2097
|
-
"remove",
|
|
2098
|
-
"-y",
|
|
2099
|
-
packageName
|
|
2100
|
-
]);
|
|
2101
|
-
if (status.success) {
|
|
2102
|
-
console.log(pc15.green(`\u2714 \u8F6F\u4EF6\u5305 ${packageName} \u5DF2\u6210\u529F\u4ECE\u7CFB\u7EDF\u4E2D\u79FB\u9664\u3002`));
|
|
2103
|
-
} else {
|
|
2104
|
-
console.error(pc15.red(`\u274C \u5378\u8F7D\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`));
|
|
2105
|
-
}
|
|
2106
|
-
}
|
|
2107
|
-
async function removeRpm(packageName) {
|
|
2108
|
-
console.log(pc15.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 dnf \u5378\u8F7D RPM \u8F6F\u4EF6\u5305: ${packageName}...`));
|
|
2109
|
-
const status = await spawnCommand("sudo", [
|
|
2110
|
-
"dnf",
|
|
2111
|
-
"remove",
|
|
2112
|
-
"-y",
|
|
2113
|
-
packageName
|
|
2114
|
-
]);
|
|
2115
|
-
if (status.success) {
|
|
2116
|
-
console.log(pc15.green(`\u2714 \u8F6F\u4EF6\u5305 ${packageName} \u5DF2\u6210\u529F\u4ECE\u7CFB\u7EDF\u4E2D\u79FB\u9664\u3002`));
|
|
2117
|
-
} else {
|
|
2118
|
-
console.error(pc15.red(`\u274C \u5378\u8F7D\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`));
|
|
2119
|
-
}
|
|
2120
|
-
}
|
|
2121
|
-
async function removeSnap(packageName) {
|
|
2122
|
-
console.log(pc15.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 snap \u5378\u8F7D\u8F6F\u4EF6\u5305: ${packageName}...`));
|
|
2123
|
-
const status = await spawnCommand("sudo", ["snap", "remove", packageName]);
|
|
2124
|
-
if (status.success) {
|
|
2125
|
-
console.log(pc15.green(`\u2714 Snap \u8F6F\u4EF6\u5305 ${packageName} \u5DF2\u6210\u529F\u4ECE\u7CFB\u7EDF\u4E2D\u79FB\u9664\u3002`));
|
|
2126
|
-
} else {
|
|
2127
|
-
console.error(pc15.red(`\u274C \u5378\u8F7D\u5931\u8D25\uFF0C\u9000\u51FA\u7801: ${status.code}`));
|
|
2128
|
-
}
|
|
2129
|
-
}
|
|
2130
|
-
async function uninstallFlatpak(packageName) {
|
|
2131
|
-
if (!await isCommandAvailable("flatpak")) {
|
|
2132
|
-
console.error(pc15.red("\u274C \u5F53\u524D\u7CFB\u7EDF\u4E2D\u672A\u68C0\u6D4B\u5230\u5DF2\u5B89\u88C5\u7684 flatpak \u5DE5\u5177\u3002"));
|
|
2133
|
-
return;
|
|
2134
|
-
}
|
|
2135
|
-
console.log(pc15.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 flatpak \u5378\u8F7D\u5E94\u7528: ${packageName}...`));
|
|
2136
|
-
const status = await spawnCommand("flatpak", [
|
|
2137
|
-
"uninstall",
|
|
2138
|
-
"-y",
|
|
2139
|
-
packageName
|
|
2140
|
-
]);
|
|
2141
|
-
if (status.success) {
|
|
2142
|
-
const home = getHomeDir2();
|
|
2143
|
-
const desktopPath = join7(
|
|
2144
|
-
home,
|
|
2145
|
-
".local/share/applications",
|
|
2146
|
-
`flatpak-${packageName}.desktop`
|
|
2147
|
-
);
|
|
2148
|
-
try {
|
|
2149
|
-
await fs12.rm(desktopPath);
|
|
2150
|
-
console.log(pc15.green(`\u2714 \u5DF2\u6E05\u9664 Flatpak \u5173\u8054\u684C\u9762\u5FEB\u6377\u56FE\u6807\u3002`));
|
|
2151
|
-
} catch {
|
|
2152
|
-
}
|
|
2153
|
-
console.log(pc15.green("\u2728 Flatpak \u5E94\u7528\u53CA\u56FE\u6807\u6E05\u7406\u5B8C\u6210\uFF01"));
|
|
2154
|
-
}
|
|
2155
|
-
}
|
|
2156
|
-
async function performRemoveGreenApp(greenPath, appName) {
|
|
2157
|
-
const home = getHomeDir2();
|
|
2158
|
-
const applicationsDir = join7(home, ".local/share/applications");
|
|
2159
|
-
try {
|
|
2160
|
-
for (const entry of await fs12.readdir(applicationsDir, {
|
|
2161
|
-
withFileTypes: true
|
|
2162
|
-
})) {
|
|
2163
|
-
if (entry.isFile() && entry.name.endsWith(".desktop")) {
|
|
2164
|
-
const filePath = join7(applicationsDir, entry.name);
|
|
2165
|
-
const content = await fs12.readFile(filePath, "utf-8");
|
|
2166
|
-
if (content.includes(greenPath) || content.includes(appName)) {
|
|
2167
|
-
await fs12.rm(filePath);
|
|
2168
|
-
console.log(pc15.green(`\u2714 \u5DF2\u6E05\u9664\u684C\u9762\u5FEB\u6377\u56FE\u6807: ${filePath}`));
|
|
2169
|
-
}
|
|
2170
|
-
}
|
|
2036
|
+
import pc16 from "picocolors";
|
|
2037
|
+
function registerUninstallCommand(program2) {
|
|
2038
|
+
program2.command("uninstall <package>").description("macOS/Windows \u672C\u5730\u5DE5\u5177\u5378\u8F7D\u5668\uFF08\u79FB\u9664\u5B89\u88C5\u76EE\u5F55\u548C\u7EC8\u7AEF\u547D\u4EE4\u5165\u53E3\uFF09").action(async (pkg) => {
|
|
2039
|
+
if (!ensureSupportedDesktopOS()) return;
|
|
2040
|
+
if (!pkg) {
|
|
2041
|
+
console.error(pc16.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u5378\u8F7D\u7684\u5E94\u7528\u540D\u3002"));
|
|
2042
|
+
return;
|
|
2171
2043
|
}
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
console.log(pc15.green(`\u2714 \u5DF2\u6210\u529F\u6E05\u9664\u7EFF\u8272\u8F6F\u4EF6\u4E3B\u4F53: ${greenPath}`));
|
|
2177
|
-
} catch (err) {
|
|
2178
|
-
console.error(
|
|
2179
|
-
pc15.red(`\u274C \u6E05\u9664\u8F6F\u4EF6\u4E3B\u4F53\u5931\u8D25:`),
|
|
2180
|
-
err instanceof Error ? err.message : err
|
|
2181
|
-
);
|
|
2182
|
-
}
|
|
2183
|
-
}
|
|
2184
|
-
async function performFuzzySearchAndRecommendation(query) {
|
|
2185
|
-
const hasSnap = await isCommandAvailable("snap");
|
|
2186
|
-
const [greenCands, flatpakCands, snapCands] = await Promise.all([
|
|
2187
|
-
searchGreenApps(query),
|
|
2188
|
-
searchFlatpaks(query),
|
|
2189
|
-
hasSnap ? (async () => {
|
|
2190
|
-
const candidates = [];
|
|
2191
|
-
try {
|
|
2192
|
-
const { success, stdout } = await runCommand("snap", ["list"]);
|
|
2193
|
-
if (success) {
|
|
2194
|
-
const lines = decodeOutput(stdout).split("\n");
|
|
2195
|
-
for (let i = 1; i < lines.length; i++) {
|
|
2196
|
-
const name = lines[i].trim().split(/\s+/)[0];
|
|
2197
|
-
if (name && name.toLowerCase().includes(query.toLowerCase())) {
|
|
2198
|
-
candidates.push(name);
|
|
2199
|
-
}
|
|
2200
|
-
}
|
|
2201
|
-
}
|
|
2202
|
-
} catch {
|
|
2203
|
-
}
|
|
2204
|
-
return candidates;
|
|
2205
|
-
})() : Promise.resolve([])
|
|
2206
|
-
]);
|
|
2207
|
-
let systemCands = [];
|
|
2208
|
-
try {
|
|
2209
|
-
const osRelease = await fs12.readFile("/etc/os-release", "utf-8");
|
|
2210
|
-
if (osRelease.includes("fedora") || osRelease.includes("rhel") || osRelease.includes("centos")) {
|
|
2211
|
-
systemCands = await searchRpmPackages(query);
|
|
2212
|
-
} else {
|
|
2213
|
-
systemCands = await searchDebPackages(query);
|
|
2044
|
+
const removed = await removeInstalledApp(pkg);
|
|
2045
|
+
if (removed) {
|
|
2046
|
+
console.log(pc16.green("\u2728 \u5378\u8F7D\u5B8C\u6210\uFF01\u76F8\u5173\u7EC8\u7AEF\u547D\u4EE4\u5165\u53E3\u4E5F\u5DF2\u6E05\u7406\u3002"));
|
|
2047
|
+
return;
|
|
2214
2048
|
}
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
}
|
|
2218
|
-
const totalCands = greenCands.length + flatpakCands.length + snapCands.length + systemCands.length;
|
|
2219
|
-
if (totalCands > 0) {
|
|
2220
|
-
console.log(
|
|
2221
|
-
pc15.cyan(
|
|
2222
|
-
`\u{1F4A1} \u5E2E\u60A8\u5728\u7CFB\u7EDF\u4E2D\u641C\u5BFB\u5230\u4EE5\u4E0B ${totalCands} \u4E2A\u5305\u542B "${query}" \u7684\u76F8\u5173\u5339\u914D\u9879\uFF1A
|
|
2223
|
-
`
|
|
2224
|
-
)
|
|
2049
|
+
const candidates = (await listInstalledApps()).filter(
|
|
2050
|
+
(name) => name.toLowerCase().includes(pkg.toLowerCase())
|
|
2225
2051
|
);
|
|
2226
|
-
if (
|
|
2227
|
-
console.log(
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
` - ${cand} ${pc15.dim(`(\u5378\u8F7D\u547D\u4EE4: xx uninstall ${cand})`)}`
|
|
2231
|
-
);
|
|
2232
|
-
}
|
|
2233
|
-
}
|
|
2234
|
-
if (flatpakCands.length > 0) {
|
|
2235
|
-
console.log(pc15.bold(pc15.magenta("\n\u{1F4E6} [Flatpak] \u5019\u9009\uFF1A")));
|
|
2236
|
-
for (const cand of flatpakCands) {
|
|
2237
|
-
console.log(
|
|
2238
|
-
` - ${cand.id} [${cand.name}] ${pc15.dim(`(\u5378\u8F7D\u547D\u4EE4: xx uninstall ${cand.id})`)}`
|
|
2239
|
-
);
|
|
2240
|
-
}
|
|
2241
|
-
}
|
|
2242
|
-
if (snapCands.length > 0) {
|
|
2243
|
-
console.log(pc15.bold(pc15.yellow("\n\u26A1 [Snap] \u5019\u9009\uFF1A")));
|
|
2244
|
-
for (const cand of snapCands) {
|
|
2245
|
-
console.log(
|
|
2246
|
-
` - ${cand} ${pc15.dim(`(\u5378\u8F7D\u547D\u4EE4: xx uninstall ${cand})`)}`
|
|
2247
|
-
);
|
|
2248
|
-
}
|
|
2249
|
-
}
|
|
2250
|
-
if (systemCands.length > 0) {
|
|
2251
|
-
console.log(pc15.bold(pc15.blue("\n\u2699 [\u7CFB\u7EDF\u6E90\u7EA7] \u5019\u9009\uFF1A")));
|
|
2252
|
-
for (const cand of systemCands) {
|
|
2052
|
+
if (candidates.length > 0) {
|
|
2053
|
+
console.log(pc16.yellow("\u274C \u672A\u627E\u5230\u7CBE\u786E\u5339\u914D\u7684\u5DF2\u5B89\u88C5\u5E94\u7528\u3002"));
|
|
2054
|
+
console.log(pc16.cyan("\u4F60\u53EF\u80FD\u60F3\u5378\u8F7D\u4EE5\u4E0B\u9879\u76EE\uFF1A"));
|
|
2055
|
+
for (const candidate of candidates) {
|
|
2253
2056
|
console.log(
|
|
2254
|
-
` - ${
|
|
2057
|
+
` - ${candidate} ${pc16.dim(`(xx uninstall ${candidate})`)}`
|
|
2255
2058
|
);
|
|
2256
2059
|
}
|
|
2257
|
-
}
|
|
2258
|
-
console.log(pc15.cyan(`
|
|
2259
|
-
\u{1F3C1} \u641C\u5BFB\u5B8C\u6210\uFF01`));
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
async function parseUninstallTarget(target) {
|
|
2263
|
-
const lower = target.toLowerCase();
|
|
2264
|
-
const greenPath = await findGreenAppPath(target);
|
|
2265
|
-
if (greenPath) {
|
|
2266
|
-
return { type: "green", raw: target, greenPath };
|
|
2267
|
-
}
|
|
2268
|
-
const isFlatpak = !target.includes("/") && !target.includes("\\") && target.split(".").length >= 3;
|
|
2269
|
-
if (isFlatpak) {
|
|
2270
|
-
return { type: "flatpak", raw: target };
|
|
2271
|
-
}
|
|
2272
|
-
if (lower.endsWith(".deb")) {
|
|
2273
|
-
const absPath = resolve11(process.cwd(), target);
|
|
2274
|
-
try {
|
|
2275
|
-
const stat = await fs12.stat(absPath);
|
|
2276
|
-
if (stat.isFile()) {
|
|
2277
|
-
const extractedPackageName = await extractDebPackageName(absPath);
|
|
2278
|
-
return {
|
|
2279
|
-
type: "deb",
|
|
2280
|
-
raw: target,
|
|
2281
|
-
resolvedPath: absPath,
|
|
2282
|
-
extractedPackageName
|
|
2283
|
-
};
|
|
2284
|
-
}
|
|
2285
|
-
} catch {
|
|
2286
|
-
}
|
|
2287
|
-
}
|
|
2288
|
-
if (lower.endsWith(".rpm")) {
|
|
2289
|
-
const absPath = resolve11(process.cwd(), target);
|
|
2290
|
-
try {
|
|
2291
|
-
const stat = await fs12.stat(absPath);
|
|
2292
|
-
if (stat.isFile()) {
|
|
2293
|
-
const extractedPackageName = await extractRpmPackageName(absPath);
|
|
2294
|
-
return {
|
|
2295
|
-
type: "rpm",
|
|
2296
|
-
raw: target,
|
|
2297
|
-
resolvedPath: absPath,
|
|
2298
|
-
extractedPackageName
|
|
2299
|
-
};
|
|
2300
|
-
}
|
|
2301
|
-
} catch {
|
|
2302
|
-
}
|
|
2303
|
-
}
|
|
2304
|
-
if (await isSnapInstalled(target)) {
|
|
2305
|
-
return { type: "snap", raw: target };
|
|
2306
|
-
}
|
|
2307
|
-
if (await isSystemPackageInstalled(target)) {
|
|
2308
|
-
return { type: "system", raw: target };
|
|
2309
|
-
}
|
|
2310
|
-
return { type: "unknown", raw: target };
|
|
2311
|
-
}
|
|
2312
|
-
function registerUninstallCommand(program2) {
|
|
2313
|
-
program2.command("uninstall <package>").description("\u901A\u7528\u5E94\u7528\u5378\u8F7D\u5668\uFF08\u652F\u6301\u5305\u540D\u3001Flatpak\u3001Snap\u3001\u672C\u5730\u5305\u6216\u7EFF\u8272\u8F6F\u4EF6\uFF09").action(async (pkg) => {
|
|
2314
|
-
if (!pkg) {
|
|
2315
|
-
console.error(
|
|
2316
|
-
pc15.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u5378\u8F7D\u7684\u8F6F\u4EF6\u5305\u540D\u79F0\u3001\u5B89\u88C5\u5305\u6216\u7EFF\u8272\u8F6F\u4EF6\u540D\u3002")
|
|
2317
|
-
);
|
|
2318
|
-
return;
|
|
2319
|
-
}
|
|
2320
|
-
try {
|
|
2321
|
-
const parsed = await parseUninstallTarget(pkg);
|
|
2322
|
-
switch (parsed.type) {
|
|
2323
|
-
case "green":
|
|
2324
|
-
await performRemoveGreenApp(parsed.greenPath, parsed.raw);
|
|
2325
|
-
console.log(pc15.green("\u2728 \u7EFF\u8272\u5E94\u7528\u53CA\u684C\u9762\u5FEB\u6377\u65B9\u5F0F\u6E05\u7406\u5B8C\u6210\uFF01"));
|
|
2326
|
-
break;
|
|
2327
|
-
case "flatpak":
|
|
2328
|
-
await uninstallFlatpak(parsed.raw);
|
|
2329
|
-
break;
|
|
2330
|
-
case "snap":
|
|
2331
|
-
await removeSnap(parsed.raw);
|
|
2332
|
-
break;
|
|
2333
|
-
case "deb": {
|
|
2334
|
-
const debPkgName = parsed.extractedPackageName || parsed.raw;
|
|
2335
|
-
await removeDeb(debPkgName);
|
|
2336
|
-
break;
|
|
2337
|
-
}
|
|
2338
|
-
case "rpm": {
|
|
2339
|
-
const rpmPkgName = parsed.extractedPackageName || parsed.raw;
|
|
2340
|
-
await removeRpm(rpmPkgName);
|
|
2341
|
-
break;
|
|
2342
|
-
}
|
|
2343
|
-
case "system": {
|
|
2344
|
-
const osRelease = await fs12.readFile("/etc/os-release", "utf-8");
|
|
2345
|
-
if (osRelease.includes("fedora") || osRelease.includes("rhel") || osRelease.includes("centos")) {
|
|
2346
|
-
await removeRpm(parsed.raw);
|
|
2347
|
-
} else {
|
|
2348
|
-
await removeDeb(parsed.raw);
|
|
2349
|
-
}
|
|
2350
|
-
break;
|
|
2351
|
-
}
|
|
2352
|
-
case "unknown":
|
|
2353
|
-
await performFuzzySearchAndRecommendation(parsed.raw);
|
|
2354
|
-
break;
|
|
2355
|
-
default: {
|
|
2356
|
-
const _exhaustiveCheck = parsed;
|
|
2357
|
-
throw new Error(
|
|
2358
|
-
`\u672A\u5904\u7406\u7684\u5378\u8F7D\u5206\u652F\u7C7B\u578B: ${JSON.stringify(_exhaustiveCheck)}`
|
|
2359
|
-
);
|
|
2360
|
-
}
|
|
2361
|
-
}
|
|
2362
|
-
} catch (err) {
|
|
2060
|
+
} else {
|
|
2363
2061
|
console.error(
|
|
2364
|
-
|
|
2365
|
-
err instanceof Error ? err.message : String(err)
|
|
2062
|
+
pc16.red(`\u274C \u672A\u627E\u5230\u5DF2\u5B89\u88C5\u5E94\u7528 '${pkg}'\u3002\u8BF7\u5148\u8FD0\u884C xx install \u5B89\u88C5\u3002`)
|
|
2366
2063
|
);
|
|
2367
2064
|
}
|
|
2368
2065
|
});
|
|
@@ -2370,37 +2067,12 @@ function registerUninstallCommand(program2) {
|
|
|
2370
2067
|
|
|
2371
2068
|
// commands/unzip.ts
|
|
2372
2069
|
import fs13 from "fs/promises";
|
|
2373
|
-
import
|
|
2374
|
-
import { join as join8, basename as basename6, extname, resolve as
|
|
2375
|
-
|
|
2376
|
-
// utils/archive.ts
|
|
2377
|
-
import AdmZip from "adm-zip";
|
|
2378
|
-
import * as tar from "tar";
|
|
2379
|
-
import { mkdir } from "fs/promises";
|
|
2380
|
-
async function compressZip(sourceDir, outputPath) {
|
|
2381
|
-
const zip = new AdmZip();
|
|
2382
|
-
zip.addLocalFolder(sourceDir);
|
|
2383
|
-
zip.writeZip(outputPath);
|
|
2384
|
-
}
|
|
2385
|
-
async function uncompressZip(src, destDir) {
|
|
2386
|
-
await mkdir(destDir, { recursive: true });
|
|
2387
|
-
const zip = new AdmZip(src);
|
|
2388
|
-
zip.extractAllTo(destDir, true);
|
|
2389
|
-
}
|
|
2390
|
-
async function uncompressTar(src, destDir) {
|
|
2391
|
-
await mkdir(destDir, { recursive: true });
|
|
2392
|
-
await tar.x({ file: src, cwd: destDir });
|
|
2393
|
-
}
|
|
2394
|
-
async function uncompressTgz(src, destDir) {
|
|
2395
|
-
await mkdir(destDir, { recursive: true });
|
|
2396
|
-
await tar.x({ file: src, gzip: true, cwd: destDir });
|
|
2397
|
-
}
|
|
2398
|
-
|
|
2399
|
-
// commands/unzip.ts
|
|
2070
|
+
import pc17 from "picocolors";
|
|
2071
|
+
import { join as join8, basename as basename6, extname as extname2, resolve as resolve11 } from "path";
|
|
2400
2072
|
async function uncompressRar(src, dest) {
|
|
2401
2073
|
const hasUnrar = isCommandAvailable("unrar");
|
|
2402
2074
|
if (hasUnrar) {
|
|
2403
|
-
console.log(
|
|
2075
|
+
console.log(pc17.cyan(`\u{1F4E6} \u6B63\u5728\u8C03\u7528\u7CFB\u7EDF unrar \u63D0\u53D6 RAR \u538B\u7F29\u5305...`));
|
|
2404
2076
|
const status = await spawnCommand("unrar", ["x", "-y", src, dest]);
|
|
2405
2077
|
if (!status.success) {
|
|
2406
2078
|
throw new Error(`unrar \u6267\u884C\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`);
|
|
@@ -2409,7 +2081,7 @@ async function uncompressRar(src, dest) {
|
|
|
2409
2081
|
}
|
|
2410
2082
|
const hasRar = isCommandAvailable("rar");
|
|
2411
2083
|
if (hasRar) {
|
|
2412
|
-
console.log(
|
|
2084
|
+
console.log(pc17.cyan(`\u{1F4E6} \u6B63\u5728\u8C03\u7528\u7CFB\u7EDF rar \u63D0\u53D6 RAR \u538B\u7F29\u5305...`));
|
|
2413
2085
|
const status = await spawnCommand("rar", ["x", "-y", src, dest]);
|
|
2414
2086
|
if (!status.success) {
|
|
2415
2087
|
throw new Error(`rar \u6267\u884C\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`);
|
|
@@ -2430,20 +2102,20 @@ function registerUnzipCommand(program2) {
|
|
|
2430
2102
|
"\u8BF7\u8F93\u5165\u8981\u89E3\u538B\u7684\u538B\u7F29\u5305\u6587\u4EF6\u8DEF\u5F84 (Enter compressed file path):"
|
|
2431
2103
|
);
|
|
2432
2104
|
if (!input) {
|
|
2433
|
-
console.error(
|
|
2105
|
+
console.error(pc17.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u6709\u6548\u7684\u538B\u7F29\u5305\u6587\u4EF6\u3002"));
|
|
2434
2106
|
return;
|
|
2435
2107
|
}
|
|
2436
2108
|
srcFile = input.trim();
|
|
2437
2109
|
}
|
|
2438
|
-
const absSrcFile =
|
|
2110
|
+
const absSrcFile = resolve11(srcFile);
|
|
2439
2111
|
try {
|
|
2440
2112
|
const stat = await fs13.stat(absSrcFile);
|
|
2441
2113
|
if (!stat.isFile()) {
|
|
2442
|
-
console.error(
|
|
2114
|
+
console.error(pc17.red(`\u274C \u9519\u8BEF: '${srcFile}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u6587\u4EF6\u3002`));
|
|
2443
2115
|
return;
|
|
2444
2116
|
}
|
|
2445
2117
|
} catch {
|
|
2446
|
-
console.error(
|
|
2118
|
+
console.error(pc17.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u6587\u4EF6 '${srcFile}'\u3002`));
|
|
2447
2119
|
return;
|
|
2448
2120
|
}
|
|
2449
2121
|
const lowerSrc = absSrcFile.toLowerCase();
|
|
@@ -2453,17 +2125,17 @@ function registerUnzipCommand(program2) {
|
|
|
2453
2125
|
} else if (lowerSrc.endsWith(".tgz")) {
|
|
2454
2126
|
folderName = basename6(absSrcFile, ".tgz");
|
|
2455
2127
|
} else {
|
|
2456
|
-
folderName = basename6(absSrcFile,
|
|
2128
|
+
folderName = basename6(absSrcFile, extname2(absSrcFile));
|
|
2457
2129
|
}
|
|
2458
2130
|
let destDir = options.dir;
|
|
2459
2131
|
if (!destDir) {
|
|
2460
2132
|
destDir = join8(process.cwd(), folderName);
|
|
2461
2133
|
} else {
|
|
2462
|
-
destDir =
|
|
2134
|
+
destDir = resolve11(process.cwd(), destDir);
|
|
2463
2135
|
}
|
|
2464
2136
|
try {
|
|
2465
|
-
console.log(
|
|
2466
|
-
console.log(
|
|
2137
|
+
console.log(pc17.cyan(`\u{1F4E6} \u6B63\u5728\u51C6\u5907\u89E3\u538B: ${absSrcFile}...`));
|
|
2138
|
+
console.log(pc17.cyan(`\u{1F4E5} \u76EE\u6807\u8F93\u51FA\u76EE\u5F55: ${destDir}`));
|
|
2467
2139
|
await fs13.mkdir(destDir, { recursive: true });
|
|
2468
2140
|
if (lowerSrc.endsWith(".tar.gz") || lowerSrc.endsWith(".tgz")) {
|
|
2469
2141
|
await uncompressTgz(absSrcFile, destDir);
|
|
@@ -2475,16 +2147,16 @@ function registerUnzipCommand(program2) {
|
|
|
2475
2147
|
await uncompressRar(absSrcFile, destDir);
|
|
2476
2148
|
} else {
|
|
2477
2149
|
console.log(
|
|
2478
|
-
|
|
2150
|
+
pc17.yellow(
|
|
2479
2151
|
"\u26A0\uFE0F \u672A\u80FD\u8BC6\u522B\u7684\u538B\u7F29\u5305\u683C\u5F0F\u540E\u7F00\u3002\u5C06\u9ED8\u8BA4\u5C1D\u8BD5\u4F5C\u4E3A\u6807\u51C6 ZIP \u8FDB\u884C\u63D0\u53D6..."
|
|
2480
2152
|
)
|
|
2481
2153
|
);
|
|
2482
2154
|
await uncompressZip(absSrcFile, destDir);
|
|
2483
2155
|
}
|
|
2484
|
-
console.log(
|
|
2156
|
+
console.log(pc17.green(`\u2728 \u63D0\u53D6\u6210\u529F\uFF01\u5DF2\u4FDD\u5B58\u5230: ${destDir}`));
|
|
2485
2157
|
} catch (error) {
|
|
2486
2158
|
console.error(
|
|
2487
|
-
|
|
2159
|
+
pc17.red("\u274C \u63D0\u53D6\u5931\u8D25:"),
|
|
2488
2160
|
error instanceof Error ? error.message : error
|
|
2489
2161
|
);
|
|
2490
2162
|
}
|
|
@@ -2492,7 +2164,7 @@ function registerUnzipCommand(program2) {
|
|
|
2492
2164
|
}
|
|
2493
2165
|
|
|
2494
2166
|
// commands/upgrade.ts
|
|
2495
|
-
import
|
|
2167
|
+
import pc18 from "picocolors";
|
|
2496
2168
|
function registerUpgradeCommand(program2) {
|
|
2497
2169
|
program2.command("upgrade").description("\u68C0\u67E5\u5E76\u81EA\u52A8\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177\u81F3\u6700\u65B0\u7248\u672C").option("-r, --registry", "\u5F3A\u5236\u4F7F\u7528 npm \u5B98\u65B9\u6E90 https://registry.npmjs.org/").action(async (options) => {
|
|
2498
2170
|
const args = ["install", "-g"];
|
|
@@ -2500,33 +2172,33 @@ function registerUpgradeCommand(program2) {
|
|
|
2500
2172
|
args.push("--registry=https://registry.npmjs.org/");
|
|
2501
2173
|
}
|
|
2502
2174
|
args.push("@xx-in/tools@latest");
|
|
2503
|
-
console.log(
|
|
2504
|
-
console.log(
|
|
2175
|
+
console.log(pc18.cyan("\u{1F916} \u6B63\u5728\u4E3A\u60A8\u68C0\u67E5\u5E76\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177..."));
|
|
2176
|
+
console.log(pc18.dim(`\u6267\u884C\u547D\u4EE4: npm ${args.join(" ")}
|
|
2505
2177
|
`));
|
|
2506
2178
|
try {
|
|
2507
2179
|
const status = await spawnCommand("npm", args);
|
|
2508
2180
|
if (status.success) {
|
|
2509
2181
|
console.log(
|
|
2510
|
-
|
|
2182
|
+
pc18.cyan("\n\u{1F916} \u6B63\u5728\u4E3A\u60A8\u5F3A\u5236\u8986\u76D6\u5E76\u5237\u65B0\u7EC8\u7AEF\u81EA\u52A8\u8865\u5168\u811A\u672C...")
|
|
2511
2183
|
);
|
|
2512
2184
|
await autoInstallCompletion();
|
|
2513
2185
|
console.log(
|
|
2514
|
-
|
|
2186
|
+
pc18.green("\n\u2728 xx \u81EA\u52A8\u66F4\u65B0\u5E76\u91CD\u5237\u8865\u5168\u6210\u529F\uFF01\u5DF2\u6210\u529F\u52A0\u8F7D\u6700\u65B0\u7248\u672C\u3002")
|
|
2515
2187
|
);
|
|
2516
2188
|
} else {
|
|
2517
2189
|
console.error(
|
|
2518
|
-
|
|
2190
|
+
pc18.red(`
|
|
2519
2191
|
\u274C \u66F4\u65B0\u5931\u8D25\uFF0C\u9000\u51FA\u4EE3\u7801 (Exit Code): ${status.code}`)
|
|
2520
2192
|
);
|
|
2521
2193
|
}
|
|
2522
2194
|
} catch (err) {
|
|
2523
2195
|
console.error(
|
|
2524
|
-
|
|
2196
|
+
pc18.red(
|
|
2525
2197
|
"\n\u274C \u65E0\u6CD5\u6267\u884C\u66F4\u65B0\u547D\u4EE4\uFF0C\u8BF7\u786E\u8BA4\u7CFB\u7EDF\u73AF\u5883\u53D8\u91CF\u4E2D\u662F\u5426\u5DF2\u6B63\u786E\u914D\u7F6E Node.js \u4E0E npm\u3002"
|
|
2526
2198
|
)
|
|
2527
2199
|
);
|
|
2528
2200
|
if (err instanceof Error) {
|
|
2529
|
-
console.error(
|
|
2201
|
+
console.error(pc18.red("\u9519\u8BEF\u8BE6\u60C5:"), err.message);
|
|
2530
2202
|
}
|
|
2531
2203
|
}
|
|
2532
2204
|
});
|
|
@@ -2535,8 +2207,8 @@ function registerUpgradeCommand(program2) {
|
|
|
2535
2207
|
// commands/zip.ts
|
|
2536
2208
|
import fs14 from "fs/promises";
|
|
2537
2209
|
import os2 from "os";
|
|
2538
|
-
import
|
|
2539
|
-
import { join as join9, basename as basename7, relative as relative2, resolve as
|
|
2210
|
+
import pc19 from "picocolors";
|
|
2211
|
+
import { join as join9, basename as basename7, relative as relative2, resolve as resolve12 } from "path";
|
|
2540
2212
|
var IGNORE_FILE_NAME = ".cpzipignore";
|
|
2541
2213
|
var DEFAULT_BLACKLIST = [
|
|
2542
2214
|
"# cpzip \u5FFD\u7565\u914D\u7F6E\u6587\u4EF6",
|
|
@@ -2555,20 +2227,20 @@ async function getBlacklist(absSrcDir) {
|
|
|
2555
2227
|
const cwdIgnorePath = join9(process.cwd(), IGNORE_FILE_NAME);
|
|
2556
2228
|
try {
|
|
2557
2229
|
const content = await fs14.readFile(targetIgnorePath, "utf-8");
|
|
2558
|
-
console.log(
|
|
2230
|
+
console.log(pc19.cyan(`[zip] \u627E\u5230\u76EE\u6807\u76EE\u5F55\u4E0B\u7684\u5FFD\u7565\u6587\u4EF6: ${targetIgnorePath}`));
|
|
2559
2231
|
return parseIgnoreContent(content);
|
|
2560
2232
|
} catch {
|
|
2561
2233
|
}
|
|
2562
2234
|
try {
|
|
2563
2235
|
const content = await fs14.readFile(cwdIgnorePath, "utf-8");
|
|
2564
|
-
console.log(
|
|
2236
|
+
console.log(pc19.cyan(`[zip] \u627E\u5230\u5F53\u524D\u76EE\u5F55\u4E0B\u7684\u5FFD\u7565\u6587\u4EF6: ${cwdIgnorePath}`));
|
|
2565
2237
|
return parseIgnoreContent(content);
|
|
2566
2238
|
} catch (err) {
|
|
2567
2239
|
if (isNotFoundError(err)) {
|
|
2568
|
-
console.log(
|
|
2240
|
+
console.log(pc19.dim(`[zip] \u672A\u627E\u5230\u5FFD\u7565\u6587\u4EF6\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u8FC7\u6EE4\u89C4\u5219\u3002`));
|
|
2569
2241
|
return parseIgnoreContent(DEFAULT_BLACKLIST.join("\n"));
|
|
2570
2242
|
}
|
|
2571
|
-
console.error(
|
|
2243
|
+
console.error(pc19.red(`[zip] \u8BFB\u53D6\u5FFD\u7565\u6587\u4EF6\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u89C4\u5219\u3002`), err);
|
|
2572
2244
|
return parseIgnoreContent(DEFAULT_BLACKLIST.join("\n"));
|
|
2573
2245
|
}
|
|
2574
2246
|
}
|
|
@@ -2617,20 +2289,20 @@ function registerZipCommand(program2) {
|
|
|
2617
2289
|
if (!srcDir) {
|
|
2618
2290
|
const input = prompt("\u8BF7\u8F93\u5165\u8981\u6253\u5305\u7684\u76EE\u5F55\u8DEF\u5F84 (Enter directory path):");
|
|
2619
2291
|
if (!input) {
|
|
2620
|
-
console.error(
|
|
2292
|
+
console.error(pc19.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u6709\u6548\u7684\u8F93\u5165\u76EE\u5F55\u3002"));
|
|
2621
2293
|
return;
|
|
2622
2294
|
}
|
|
2623
2295
|
srcDir = input.trim();
|
|
2624
2296
|
}
|
|
2625
|
-
const absSrcDir =
|
|
2297
|
+
const absSrcDir = resolve12(srcDir);
|
|
2626
2298
|
try {
|
|
2627
2299
|
const stat = await fs14.stat(absSrcDir);
|
|
2628
2300
|
if (!stat.isDirectory()) {
|
|
2629
|
-
console.error(
|
|
2301
|
+
console.error(pc19.red(`\u274C \u9519\u8BEF: '${srcDir}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
|
|
2630
2302
|
return;
|
|
2631
2303
|
}
|
|
2632
2304
|
} catch {
|
|
2633
|
-
console.error(
|
|
2305
|
+
console.error(pc19.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u76EE\u5F55 '${srcDir}'\u3002`));
|
|
2634
2306
|
return;
|
|
2635
2307
|
}
|
|
2636
2308
|
const dirName = basename7(absSrcDir);
|
|
@@ -2639,13 +2311,13 @@ function registerZipCommand(program2) {
|
|
|
2639
2311
|
const tempDir = await fs14.mkdtemp(join9(os2.tmpdir(), "cpzip_temp_"));
|
|
2640
2312
|
const tempCopyTarget = join9(tempDir, dirName);
|
|
2641
2313
|
try {
|
|
2642
|
-
console.log(
|
|
2314
|
+
console.log(pc19.cyan(`\u{1F4E6} \u6B63\u5728\u590D\u5236\u76EE\u5F55\u5E76\u8FC7\u6EE4\u5FFD\u7565\u9879...`));
|
|
2643
2315
|
await copyRecursive3(absSrcDir, tempCopyTarget, absSrcDir, blacklist);
|
|
2644
|
-
console.log(
|
|
2316
|
+
console.log(pc19.cyan(`\u26A1 \u6B63\u5728\u6253\u5305\u4E3A ZIP \u538B\u7F29\u5305...`));
|
|
2645
2317
|
await compressZip(tempCopyTarget, outputZip);
|
|
2646
|
-
console.log(
|
|
2318
|
+
console.log(pc19.green(`\u2728 \u6253\u5305\u6210\u529F\uFF01\u538B\u7F29\u5305\u4FDD\u5B58\u4E3A: ${outputZip}`));
|
|
2647
2319
|
} catch (error) {
|
|
2648
|
-
console.error(
|
|
2320
|
+
console.error(pc19.red("\u274C \u6253\u5305\u5931\u8D25:"), error);
|
|
2649
2321
|
} finally {
|
|
2650
2322
|
try {
|
|
2651
2323
|
await fs14.rm(tempDir, { recursive: true });
|