@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.
Files changed (3) hide show
  1. package/README.md +8 -6
  2. package/dist/cli.js +535 -863
  3. 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.2",
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:\u81EA\u52A8\u5206\u53D1\u90E8\u7F72\u5B89\u88C5\u5305 (\u652F\u6301 AppImage\u3001Flatpak ID\u3001tar.gz\u3001deb\u3001rpm)'
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:\u901A\u7528\u5E94\u7528\u5378\u8F7D\u5668\uFF08\u652F\u6301\u5305\u540D\u3001Flatpak\u3001Snap\u3001\u672C\u5730\u5305\u6216\u7EFF\u8272\u8F6F\u4EF6\uFF09'
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:\u81EA\u52A8\u5206\u53D1\u90E8\u7F72\u5B89\u88C5\u5305 (\u652F\u6301 AppImage\u3001Flatpak ID\u3001tar.gz\u3001deb\u3001rpm)'
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:\u901A\u7528\u5E94\u7528\u5378\u8F7D\u5668\uFF08\u652F\u6301\u5305\u540D\u3001Flatpak\u3001Snap\u3001\u672C\u5730\u5305\u6216\u7EFF\u8272\u8F6F\u4EF6\uFF09'
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((resolve14, reject) => {
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
- resolve14({
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
- resolve14({
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
- import { resolve as resolve4, join as join4, basename as basename2 } from "path";
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
- async function createShortcut(targetPath) {
774
- const home = getHomeDir();
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
- async function installAppImage(absPath) {
827
- const home = getHomeDir();
828
- const greenAppDir = join4(home, "GreenApp");
829
- const fileName = basename2(absPath);
830
- const destPath = join4(greenAppDir, fileName);
831
- const isAppImage = fileName.toLowerCase().endsWith(".appimage");
832
- const appNameClean = basename2(absPath, isAppImage ? ".AppImage" : "");
833
- try {
834
- await fs5.mkdir(greenAppDir, { recursive: true });
835
- console.log(
836
- pc5.cyan(`\u{1F4E6} \u6B63\u5728\u5C06 AppImage \u90E8\u7F72\u81F3\u7EFF\u8272\u8F6F\u4EF6\u76EE\u5F55: ${destPath}...`)
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 AppImage \u90E8\u7F72\u5931\u8D25:"),
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 installDeb(absPath) {
858
- console.log(pc5.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 dpkg \u672C\u5730\u5B89\u88C5 DEB \u8F6F\u4EF6\u5305: ${absPath}...`));
859
- const status = await spawnCommand("sudo", ["dpkg", "-i", absPath]);
860
- if (status.success) {
861
- console.log(pc5.green("\u2714 DEB \u8F6F\u4EF6\u5305\u90E8\u7F72\u6210\u529F\uFF01"));
862
- try {
863
- const { success, stdout } = await runCommand("dpkg-deb", [
864
- "-f",
865
- absPath,
866
- "Package"
867
- ]);
868
- if (success) {
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
- console.error(pc5.red(`\u274C \u5B89\u88C5\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`));
840
+ profiles.push(join4(home, ".zshrc"), join4(home, ".zprofile"));
883
841
  }
842
+ return Array.from(new Set(profiles));
884
843
  }
885
- async function installRpm(absPath) {
886
- console.log(pc5.cyan(`\u{1F4E6} \u6B63\u5728\u901A\u8FC7 dnf \u672C\u5730\u5B89\u88C5 RPM \u8F6F\u4EF6\u5305: ${absPath}...`));
887
- const status = await spawnCommand("sudo", ["dnf", "install", "-y", absPath]);
888
- if (status.success) {
889
- console.log(pc5.green("\u2714 RPM \u8F6F\u4EF6\u5305\u90E8\u7F72\u6210\u529F\uFF01"));
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
- const { success, stdout } = await runCommand("rpm", [
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
- } else {
911
- console.error(pc5.red(`\u274C \u5B89\u88C5\u5931\u8D25\uFF0C\u8FDB\u7A0B\u9000\u51FA\u7801: ${status.code}`));
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
- async function installTarGz(absPath) {
915
- const home = getHomeDir();
916
- if (!home) {
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 greenAppDir = join4(home, "GreenApp");
921
- const folderName = basename2(absPath, ".tar.gz").replace(".tar", "");
922
- const destDir = join4(greenAppDir, folderName);
923
- try {
924
- await fs5.mkdir(destDir, { recursive: true });
925
- console.log(pc5.cyan(`\u{1F4E6} \u6B63\u5728\u89E3\u538B\u7EFF\u8272\u8F6F\u4EF6\u81F3: ${destDir}...`));
926
- const tarStatus = await spawnCommand("tar", [
927
- "-xzf",
928
- absPath,
929
- "-C",
930
- destDir
931
- ]);
932
- if (!tarStatus.success) {
933
- console.error(pc5.red("\u274C \u89E3\u538B\u5931\u8D25\u3002"));
934
- return;
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
- console.log(
937
- pc5.green("\u2714 \u89E3\u538B\u5B8C\u6210\u3002\u6B63\u5728\u626B\u63CF\u4E3B\u6267\u884C\u6587\u4EF6\u4EE5\u81EA\u52A8\u914D\u7F6E\u5FEB\u6377\u65B9\u5F0F...")
938
- );
939
- let exePath = "";
940
- for (const entry of await fs5.readdir(destDir, { withFileTypes: true })) {
941
- if (entry.isFile()) {
942
- const fullPath = join4(destDir, entry.name);
943
- const stat = await fs5.stat(fullPath);
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 && !entry.name.endsWith(".sh") && !entry.name.endsWith(".so")) {
946
- exePath = fullPath;
947
- break;
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
- if (exePath) {
952
- console.log(pc5.cyan(`\u{1F50D} \u53D1\u73B0\u53EF\u6267\u884C\u4E8C\u8FDB\u5236\u6587\u4EF6: ${exePath}`));
953
- await createShortcut(exePath);
954
- console.log(
955
- pc5.green(
956
- `
957
- \u2728 \u5B89\u88C5\u6210\u529F\uFF01\u8BE5\u7EFF\u8272\u5E94\u7528\u7684\u5378\u8F7D\u540D\u79F0\u4E3A: ${pc5.bold(folderName)}`
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
- 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`));
961
- console.log(pc5.bold(pc5.yellow(` xx delete ${folderName}`)));
962
- } else {
963
- console.log(
964
- pc5.yellow(
965
- "\u26A0\uFE0F \u672A\u80FD\u5728\u89E3\u538B\u76EE\u5F55\u4E0B\u5B9A\u4F4D\u5230\u660E\u786E\u7684\u53EF\u6267\u884C\u4E8C\u8FDB\u5236\u6587\u4EF6\uFF0C\u8BF7\u540E\u7EED\u624B\u52A8\u521B\u5EFA\u3002"
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
- } catch (err) {
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
- pc5.red("\u274C \u7EFF\u8272\u8F6F\u4EF6\u5B89\u88C5\u5931\u8D25:"),
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
- "\u901A\u7528\u5E94\u7528\u90E8\u7F72\u5B89\u88C5\uFF08\u81EA\u52A8\u5206\u53D1\u9002\u914D AppImage\u3001Flatpak ID\u3001tar.gz\u3001deb \u53CA rpm \u683C\u5F0F\u5305\uFF09"
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(pc5.red("\u274C \u8BF7\u63D0\u4F9B\u6709\u6548\u7684\u5B89\u88C5\u5305\u6587\u4EF6\u8DEF\u5F84\u6216 Flatpak ID\u3002"));
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 fs5.stat(absPath);
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(pc5.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u6307\u5B9A\u6587\u4EF6\u6216\u5305\u8DEF\u5F84 '${target}'\u3002`));
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(".appimage")) {
1006
- await installAppImage(absPath);
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
- console.log(
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 pc6 from "picocolors";
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(pc6.dim("\u6B63\u5728\u5206\u6790\u7F51\u7EDC\u914D\u7F6E\uFF0C\u8BF7\u7A0D\u5019...\n"));
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(pc6.red("\u274C \u672A\u68C0\u6D4B\u5230\u4EFB\u4F55\u6D3B\u8DC3\u7684\u975E\u672C\u5730\u56DE\u73AF\u7F51\u5361\u3002"));
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 = pc6.dim("(\u975E\u9ED8\u8BA4\u8DEF\u7531\u51FA\u53E3\u7F51\u5361)");
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 = pc6.yellow(defaultRoute.gateway);
1381
+ cardGateway = pc7.yellow(defaultRoute.gateway);
1254
1382
  } else {
1255
- cardGateway = pc6.yellow("\u76F4\u63A5\u70B9\u5BF9\u70B9\u96A7\u9053\u8FDE\u63A5 (Point-to-Point)");
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 = pc6.dim(`\u68C0\u6D4B\u5931\u8D25 (\u539F\u56E0: ${routeError})`);
1386
+ cardGateway = pc7.dim(`\u68C0\u6D4B\u5931\u8D25 (\u539F\u56E0: ${routeError})`);
1259
1387
  }
1260
1388
  console.log(
1261
- pc6.cyan(
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
- `${pc6.green("\u7F51\u5361\u540D\u79F0 (Name):")} ${pc6.bold(card.name)}`
1394
+ `${pc7.green("\u7F51\u5361\u540D\u79F0 (Name):")} ${pc7.bold(card.name)}`
1267
1395
  );
1268
1396
  console.log(
1269
- `${pc6.green("\u672C\u673A IP \u5730\u5740 (IP):")} ${pc6.bold(primaryAddr.address)}`
1397
+ `${pc7.green("\u672C\u673A IP \u5730\u5740 (IP):")} ${pc7.bold(primaryAddr.address)}`
1270
1398
  );
1271
1399
  console.log(
1272
- `${pc6.green("\u5B50\u7F51\u63A9\u7801 (Mask):")} ${primaryAddr.netmask}`
1400
+ `${pc7.green("\u5B50\u7F51\u63A9\u7801 (Mask):")} ${primaryAddr.netmask}`
1273
1401
  );
1274
- console.log(`${pc6.green("\u9ED8\u8BA4\u7F51\u5173 (Gateway):")} ${cardGateway}`);
1275
- console.log(`${pc6.green("MAC \u5730\u5740 (MAC):")} ${card.mac}`);
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
- `${pc6.green("IP \u534F\u8BAE\u7248\u672C:")} ${primaryAddr.family === "IPv4" || primaryAddr.family === "4" ? "IPv4" : "IPv6"}`
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
- `${pc6.green("\u672C\u5730 IPv6 \u5730\u5740:")} ${pc6.dim(ipv6.address)}`
1409
+ `${pc7.green("\u672C\u5730 IPv6 \u5730\u5740:")} ${pc7.dim(ipv6.address)}`
1282
1410
  );
1283
1411
  }
1284
1412
  console.log(
1285
- pc6.cyan("====================================================")
1413
+ pc7.cyan("====================================================")
1286
1414
  );
1287
1415
  console.log("");
1288
1416
  }
1289
1417
  } catch (error) {
1290
- console.error(pc6.red("\u274C \u68C0\u6D4B\u5931\u8D25\u3002"));
1418
+ console.error(pc7.red("\u274C \u68C0\u6D4B\u5931\u8D25\u3002"));
1291
1419
  if (error instanceof Error) {
1292
- console.error(pc6.red("\u9519\u8BEF\u8BE6\u60C5:"), error.message);
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 fs6 from "fs/promises";
1300
- import pc7 from "picocolors";
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 fs6.stat(absolutePath);
1435
+ const stat = await fs7.stat(absolutePath);
1308
1436
  if (!stat.isDirectory()) {
1309
- console.error(pc7.red(`\u274C \u9519\u8BEF: '${inputPath}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
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 fs6.readdir(absolutePath, {
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(pc7.dim("\uFF08\u7A7A\u76EE\u5F55\uFF09"));
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(pc7.dim(`\u{1F4C1} ${pc7.blue(entry.name)}/`));
1459
+ console.log(pc8.dim(`\u{1F4C1} ${pc8.blue(entry.name)}/`));
1332
1460
  } else {
1333
- console.log(`\u{1F4C1} ${pc7.blue(pc7.bold(entry.name))}/`);
1461
+ console.log(`\u{1F4C1} ${pc8.blue(pc8.bold(entry.name))}/`);
1334
1462
  }
1335
1463
  } else {
1336
1464
  if (isHidden) {
1337
- console.log(pc7.dim(`\u{1F4C4} ${entry.name}`));
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
- pc7.red(`\u274C \u65E0\u6CD5\u8BFB\u53D6\u76EE\u5F55\u5185\u5BB9:`),
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 fs7 from "fs/promises";
1354
- import pc8 from "picocolors";
1355
- import { dirname as dirname4, resolve as resolve6, join as join5, basename as basename3 } from "path";
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 fs7.stat(src);
1485
+ const fileInfo = await fs8.stat(src);
1358
1486
  if (fileInfo.isDirectory()) {
1359
- await fs7.mkdir(dest, { recursive: true });
1360
- for (const entry of await fs7.readdir(src, { withFileTypes: true })) {
1361
- await copyRecursive2(join5(src, entry.name), join5(dest, entry.name));
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 fs7.mkdir(dirname4(dest), { recursive: true });
1365
- await fs7.copyFile(src, dest);
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(pc8.red("\u274C \u8BF7\u63D0\u4F9B\u6E90\u8DEF\u5F84\u548C\u76EE\u6807\u8DEF\u5F84"));
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 fs7.stat(absSource);
1505
+ await fs8.stat(absSource);
1378
1506
  let finalTarget = absTarget;
1379
1507
  try {
1380
- const targetStat = await fs7.stat(absTarget);
1508
+ const targetStat = await fs8.stat(absTarget);
1381
1509
  if (targetStat.isDirectory()) {
1382
- finalTarget = join5(absTarget, basename3(absSource));
1510
+ finalTarget = join6(absTarget, basename4(absSource));
1383
1511
  }
1384
1512
  } catch {
1385
1513
  }
1386
- const targetParentDir = dirname4(finalTarget);
1387
- await fs7.mkdir(targetParentDir, { recursive: true });
1388
- console.log(pc8.cyan(`\u{1F4E6} \u6B63\u5728\u79FB\u52A8: ${source} \u27A1\uFE0F ${target}...`));
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 fs7.rename(absSource, finalTarget);
1518
+ await fs8.rename(absSource, finalTarget);
1391
1519
  } catch {
1392
1520
  await copyRecursive2(absSource, finalTarget);
1393
- await fs7.rm(absSource, { recursive: true });
1521
+ await fs8.rm(absSource, { recursive: true });
1394
1522
  }
1395
- console.log(pc8.green(`\u2728 \u79FB\u52A8\u6210\u529F: ${source} \u27A1\uFE0F ${target}`));
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(pc8.red(`\u274C \u9519\u8BEF: \u6E90\u8DEF\u5F84\u4E0D\u5B58\u5728: ${absSource}`));
1526
+ console.error(pc9.red(`\u274C \u9519\u8BEF: \u6E90\u8DEF\u5F84\u4E0D\u5B58\u5728: ${absSource}`));
1399
1527
  } else {
1400
1528
  console.error(
1401
- pc8.red("\u274C \u79FB\u52A8\u5931\u8D25:"),
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 fs8 from "fs/promises";
1411
- import pc9 from "picocolors";
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 fs8.stat(absolutePath);
1546
+ const stat = await fs9.stat(absolutePath);
1419
1547
  if (!stat.isDirectory()) {
1420
- console.error(pc9.red(`\u274C \u9519\u8BEF: '${inputPath}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
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(pc9.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u76EE\u5F55 '${inputPath}'\u3002`));
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(pc9.red("\u274C \u6682\u4E0D\u652F\u6301\u5728\u5F53\u524D\u7CFB\u7EDF\u4E0B\u8C03\u8D77\u6587\u4EF6\u7BA1\u7406\u5668\u3002"));
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(pc9.cyan(`\u{1F4C2} \u6B63\u5728\u6253\u5F00\u6587\u4EF6\u5939: ${absolutePath}...`));
1572
+ console.log(pc10.cyan(`\u{1F4C2} \u6B63\u5728\u6253\u5F00\u6587\u4EF6\u5939: ${absolutePath}...`));
1445
1573
  await spawnCommand(cmd, args);
1446
- console.log(pc9.green("\u2728 \u6210\u529F\u8C03\u8D77\u6587\u4EF6\u7BA1\u7406\u5668\uFF01"));
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
- pc9.red("\u274C \u65E0\u6CD5\u6253\u5F00\u7BA1\u7406\u5668:"),
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 fs9, { open } from "fs/promises";
1585
+ import fs10, { open } from "fs/promises";
1458
1586
  import process2 from "process";
1459
- import pc10 from "picocolors";
1460
- import { join as join6, isAbsolute, resolve as resolve8, dirname as dirname5 } from "path";
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 join6(home, CONFIG_FILE_NAME);
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 fs9.readFile(path, "utf-8");
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 fs9.writeFile(path, JSON.stringify(config, null, 2));
1606
+ await fs10.writeFile(path, JSON.stringify(config, null, 2));
1479
1607
  } catch (err) {
1480
- console.error(pc10.red("\u274C \u5199\u5165\u5168\u5C40\u914D\u7F6E\u6587\u4EF6\u5931\u8D25:"), err);
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(pc10.cyan(`\u{1F4E6} \u76EE\u6807\u955C\u50CF: ${pc10.bold(fullImageName)}`));
1493
- console.log(pc10.dim("\u6B63\u5728\u5411\u6253\u5305\u670D\u52A1\u5668\u63D0\u4EA4\u4EFB\u52A1\uFF0C\u8BF7\u7A0D\u5019...\n"));
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(pc10.red("\u274C \u672A\u80FD\u5728\u670D\u52A1\u5668\u54CD\u5E94\u4E2D\u5339\u914D\u5230\u6253\u5305\u6587\u4EF6\u540D\u3002"));
1531
- console.log(pc10.yellow("\u670D\u52A1\u5668\u539F\u59CB\u54CD\u5E94\u5982\u4E0B\uFF1A"));
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(pc10.green(`\u2705 \u6253\u5305\u4EFB\u52A1\u63D0\u4EA4\u6210\u529F!`));
1537
- console.log(pc10.green(`\u{1F517} \u4E0B\u8F7D\u94FE\u63A5: ${pc10.underline(downloadUrl)}`));
1538
- console.log(pc10.cyan(`
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 : join6(downloadDir, baseFilename);
1564
- const targetDirToCreate = dirname5(finalPath);
1691
+ const finalPath = isAbsolute(baseFilename) ? baseFilename : join7(downloadDir, baseFilename);
1692
+ const targetDirToCreate = dirname4(finalPath);
1565
1693
  try {
1566
- await fs9.mkdir(targetDirToCreate, { recursive: true });
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" + pc10.green(`\u2728 \u4E0B\u8F7D\u5E76\u4FDD\u5B58\u6210\u529F! \u6587\u4EF6\u8DEF\u5F84: ${finalPath}`));
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(pc10.red("\n\u274C \u6267\u884C\u5931\u8D25\u3002"));
1723
+ console.error(pc11.red("\n\u274C \u6267\u884C\u5931\u8D25\u3002"));
1596
1724
  if (error instanceof Error) {
1597
- console.error(pc10.red("\u9519\u8BEF\u8BE6\u60C5:"), error.message);
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(pc10.green(`\u2728 \u5DF2\u6210\u529F\u8BBE\u7F6E\u5168\u5C40\u9ED8\u8BA4\u4E0B\u8F7D\u76EE\u5F55\u4E3A: ${absPath}`));
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(pc10.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u9700\u8981\u4E0B\u8F7D\u7684\u955C\u50CF\u540D\u79F0\u3002"));
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 pc11 from "picocolors";
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
- pc11.yellow(
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(pc11.cyan(`\u{1F449} \u8BF7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u624B\u52A8\u542F\u7528\u4EE3\u7406\uFF1A`));
1637
- console.log(pc11.bold(` export http_proxy="http://127.0.0.1:${p}"`));
1638
- console.log(pc11.bold(` export https_proxy="http://127.0.0.1:${p}"`));
1639
- console.log(pc11.bold(` export all_proxy="socks5://127.0.0.1:${p}"`));
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
- pc11.dim(
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
- pc11.yellow(
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(pc11.cyan(`\u{1F449} \u8BF7\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u6765\u624B\u52A8\u5173\u95ED\u4EE3\u7406\uFF1A`));
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
- pc11.bold(
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(pc11.yellow("\u{1F50D} [xx] \u68C0\u6D4B\u5230\u5F53\u524D\u7EC8\u7AEF\u5DF2\u914D\u7F6E\u4E34\u65F6\u4EE3\u7406\uFF1A"));
1664
- if (httpProxy) console.log(` http_proxy = ${pc11.bold(httpProxy)}`);
1665
- if (httpsProxy) console.log(` https_proxy = ${pc11.bold(httpsProxy)}`);
1666
- if (allProxy) console.log(` all_proxy = ${pc11.bold(allProxy)}`);
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(pc11.green("\u{1F50D} [xx] \u5F53\u524D\u7EC8\u7AEF\u672A\u914D\u7F6E\u4EFB\u4F55\u4EE3\u7406 (\u76F4\u8FDE\u6A21\u5F0F)"));
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
- pc11.dim(
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 fs10 from "fs/promises";
1681
- import pc12 from "picocolors";
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(pc12.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u653E\u5165\u56DE\u6536\u7AD9\u7684\u8DEF\u5F84\u6216\u901A\u914D\u7B26\u89C4\u5219"));
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
- pc12.red(`\u274C \u5339\u914D\u901A\u914D\u7B26 '${pattern}' \u65F6\u53D1\u751F\u5F02\u5E38:`),
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 fs10.stat(absolutePath);
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
- pc12.red(`\u274C \u83B7\u53D6\u8DEF\u5F84\u72B6\u6001\u5931\u8D25 [${pattern}]:`),
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(pc12.red(`\u274C \u8DEF\u5F84\u4E0D\u5B58\u5728: ${path}`));
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(pc12.yellow("\u2139\uFE0F \u672A\u80FD\u627E\u5230\u4EFB\u4F55\u4E0E\u6307\u5B9A\u6761\u4EF6\u5339\u914D\u7684\u6587\u4EF6\u6216\u76EE\u5F55\u3002"));
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
- pc12.cyan(
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(pc12.dim(` - \u5DF2\u79FB\u5165\u5783\u573E\u7BB1: ${path}`));
1874
+ console.log(pc13.dim(` - \u5DF2\u79FB\u5165\u5783\u573E\u7BB1: ${path}`));
1747
1875
  }
1748
1876
  console.log(
1749
- pc12.green(
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
- pc12.red("\u274C \u79FB\u81F3\u56DE\u6536\u7AD9\u5931\u8D25:"),
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 fs11 from "fs/promises";
1764
- import pc13 from "picocolors";
1765
- import { resolve as resolve10, basename as basename4, relative } from "path";
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(pc13.red("\u274C \u8BF7\u63D0\u4F9B\u8981\u641C\u7D22\u7684\u6587\u4EF6\u540D\u5173\u952E\u8BCD"));
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 fs11.stat(absoluteStartDir);
1906
+ const stat = await fs12.stat(absoluteStartDir);
1779
1907
  if (!stat.isDirectory()) {
1780
- console.error(pc13.red(`\u274C \u9519\u8BEF: '${startDir}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
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(pc13.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u8D77\u70B9\u76EE\u5F55 '${startDir}'\u3002`));
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
- pc13.cyan(
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 = basename4(entryPath);
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 fs11.stat(entryPath);
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\\${pc13.bold(name)}\x1B]8;;\x1B\\`;
1823
- console.log(`${typeIcon} ${hyperlink} -> ${pc13.dim(fileUri)}`);
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
- pc13.green(`
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
- pc13.red("\u274C \u641C\u5BFB\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF:"),
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 pc14 from "picocolors";
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
- `${pc14.green("\u8BD1\u6587:")} ${pc14.bold(res.text)} ${pc14.dim(`(${res.from.language.iso} -> ${targetLang})`)}`
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(pc14.red("\u274C \u7FFB\u8BD1\u51FA\u9519:"), err.message);
1989
+ console.error(pc15.red("\u274C \u7FFB\u8BD1\u51FA\u9519:"), err.message);
1862
1990
  } else {
1863
- console.error(pc14.red("\u274C \u7FFB\u8BD1\u51FA\u9519:"), String(err));
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: pc14.cyan("\u7FFB\u8BD1\u8F93\u5165 > ")
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(pc14.yellow(`\u2728 \u5DF2\u8FDB\u5165\u4EA4\u4E92\u6A21\u5F0F (${modeTip})`));
1875
- console.log(pc14.dim('\u8F93\u5165 "exit" \u6216\u6309 Ctrl+C \u9000\u51FA\n'));
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(pc14.blue("\n\u518D\u89C1!"));
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 fs12 from "fs/promises";
1909
- import pc15 from "picocolors";
1910
- import { resolve as resolve11, join as join7 } from "path";
1911
- function getHomeDir2() {
1912
- return process.env["HOME"] || process.env["USERPROFILE"] || process.cwd();
1913
- }
1914
- async function isSnapInstalled(packageName) {
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
- } catch {
2173
- }
2174
- try {
2175
- await fs12.rm(greenPath, { recursive: true });
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
- } catch {
2216
- systemCands = await searchDebPackages(query);
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 (greenCands.length > 0) {
2227
- console.log(pc15.bold(pc15.green("\u{1F4C1} [\u7EFF\u8272\u5E94\u7528] \u5019\u9009\uFF1A")));
2228
- for (const cand of greenCands) {
2229
- console.log(
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
- ` - ${cand} ${pc15.dim(`(\u5378\u8F7D\u547D\u4EE4: xx uninstall ${cand})`)}`
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
- pc15.red("\u274C \u5378\u8F7D\u90E8\u7F72\u5931\u8D25:"),
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 pc16 from "picocolors";
2374
- import { join as join8, basename as basename6, extname, resolve as resolve12 } from "path";
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(pc16.cyan(`\u{1F4E6} \u6B63\u5728\u8C03\u7528\u7CFB\u7EDF unrar \u63D0\u53D6 RAR \u538B\u7F29\u5305...`));
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(pc16.cyan(`\u{1F4E6} \u6B63\u5728\u8C03\u7528\u7CFB\u7EDF rar \u63D0\u53D6 RAR \u538B\u7F29\u5305...`));
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(pc16.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u6709\u6548\u7684\u538B\u7F29\u5305\u6587\u4EF6\u3002"));
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 = resolve12(srcFile);
2110
+ const absSrcFile = resolve11(srcFile);
2439
2111
  try {
2440
2112
  const stat = await fs13.stat(absSrcFile);
2441
2113
  if (!stat.isFile()) {
2442
- console.error(pc16.red(`\u274C \u9519\u8BEF: '${srcFile}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u6587\u4EF6\u3002`));
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(pc16.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u6587\u4EF6 '${srcFile}'\u3002`));
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, extname(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 = resolve12(process.cwd(), destDir);
2134
+ destDir = resolve11(process.cwd(), destDir);
2463
2135
  }
2464
2136
  try {
2465
- console.log(pc16.cyan(`\u{1F4E6} \u6B63\u5728\u51C6\u5907\u89E3\u538B: ${absSrcFile}...`));
2466
- console.log(pc16.cyan(`\u{1F4E5} \u76EE\u6807\u8F93\u51FA\u76EE\u5F55: ${destDir}`));
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
- pc16.yellow(
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(pc16.green(`\u2728 \u63D0\u53D6\u6210\u529F\uFF01\u5DF2\u4FDD\u5B58\u5230: ${destDir}`));
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
- pc16.red("\u274C \u63D0\u53D6\u5931\u8D25:"),
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 pc17 from "picocolors";
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(pc17.cyan("\u{1F916} \u6B63\u5728\u4E3A\u60A8\u68C0\u67E5\u5E76\u66F4\u65B0 xx \u547D\u4EE4\u884C\u5DE5\u5177..."));
2504
- console.log(pc17.dim(`\u6267\u884C\u547D\u4EE4: npm ${args.join(" ")}
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
- pc17.cyan("\n\u{1F916} \u6B63\u5728\u4E3A\u60A8\u5F3A\u5236\u8986\u76D6\u5E76\u5237\u65B0\u7EC8\u7AEF\u81EA\u52A8\u8865\u5168\u811A\u672C...")
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
- pc17.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")
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
- pc17.red(`
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
- pc17.red(
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(pc17.red("\u9519\u8BEF\u8BE6\u60C5:"), err.message);
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 pc18 from "picocolors";
2539
- import { join as join9, basename as basename7, relative as relative2, resolve as resolve13 } from "path";
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(pc18.cyan(`[zip] \u627E\u5230\u76EE\u6807\u76EE\u5F55\u4E0B\u7684\u5FFD\u7565\u6587\u4EF6: ${targetIgnorePath}`));
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(pc18.cyan(`[zip] \u627E\u5230\u5F53\u524D\u76EE\u5F55\u4E0B\u7684\u5FFD\u7565\u6587\u4EF6: ${cwdIgnorePath}`));
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(pc18.dim(`[zip] \u672A\u627E\u5230\u5FFD\u7565\u6587\u4EF6\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u8FC7\u6EE4\u89C4\u5219\u3002`));
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(pc18.red(`[zip] \u8BFB\u53D6\u5FFD\u7565\u6587\u4EF6\u5931\u8D25\uFF0C\u5C06\u4F7F\u7528\u5185\u7F6E\u9ED8\u8BA4\u89C4\u5219\u3002`), err);
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(pc18.red("\u274C \u9519\u8BEF: \u672A\u6307\u5B9A\u6709\u6548\u7684\u8F93\u5165\u76EE\u5F55\u3002"));
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 = resolve13(srcDir);
2297
+ const absSrcDir = resolve12(srcDir);
2626
2298
  try {
2627
2299
  const stat = await fs14.stat(absSrcDir);
2628
2300
  if (!stat.isDirectory()) {
2629
- console.error(pc18.red(`\u274C \u9519\u8BEF: '${srcDir}' \u4E0D\u662F\u4E00\u4E2A\u6709\u6548\u7684\u76EE\u5F55\u3002`));
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(pc18.red(`\u274C \u9519\u8BEF: \u627E\u4E0D\u5230\u76EE\u5F55 '${srcDir}'\u3002`));
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(pc18.cyan(`\u{1F4E6} \u6B63\u5728\u590D\u5236\u76EE\u5F55\u5E76\u8FC7\u6EE4\u5FFD\u7565\u9879...`));
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(pc18.cyan(`\u26A1 \u6B63\u5728\u6253\u5305\u4E3A ZIP \u538B\u7F29\u5305...`));
2316
+ console.log(pc19.cyan(`\u26A1 \u6B63\u5728\u6253\u5305\u4E3A ZIP \u538B\u7F29\u5305...`));
2645
2317
  await compressZip(tempCopyTarget, outputZip);
2646
- console.log(pc18.green(`\u2728 \u6253\u5305\u6210\u529F\uFF01\u538B\u7F29\u5305\u4FDD\u5B58\u4E3A: ${outputZip}`));
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(pc18.red("\u274C \u6253\u5305\u5931\u8D25:"), 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 });